Class: VectorMCP::RequestContext

Inherits:
Object
  • Object
show all
Defined in:
lib/vector_mcp/request_context.rb

Overview

Encapsulates request-specific data for MCP sessions. This provides a formal interface for transports to populate request context and for handlers to access request data without coupling to session internals.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(headers: {}, params: {}, method: nil, path: nil, transport_metadata: {}) ⇒ RequestContext

Initialize a new request context with the provided data.



23
24
25
26
27
28
29
# File 'lib/vector_mcp/request_context.rb', line 23

def initialize(headers: {}, params: {}, method: nil, path: nil, transport_metadata: {})
  @headers = normalize_headers(headers).freeze
  @params = normalize_params(params).freeze
  @method = method&.to_s&.freeze
  @path = path&.to_s&.freeze
   = ().freeze
end

Instance Attribute Details

#headersHash (readonly)

HTTP headers from the request



13
14
15
# File 'lib/vector_mcp/request_context.rb', line 13

def headers
  @headers
end

#methodString? (readonly)

HTTP method (GET, POST, etc.) or transport-specific method



13
14
15
# File 'lib/vector_mcp/request_context.rb', line 13

def method
  @method
end

#paramsHash (readonly)

Query parameters from the request



13
14
15
# File 'lib/vector_mcp/request_context.rb', line 13

def params
  @params
end

#pathString? (readonly)

Request path or transport-specific path



13
14
15
# File 'lib/vector_mcp/request_context.rb', line 13

def path
  @path
end

#transport_metadataHash (readonly)

Transport-specific metadata



13
14
15
# File 'lib/vector_mcp/request_context.rb', line 13

def 
  
end

Class Method Details

.coerce(request, transport_type = "http") ⇒ RequestContext

Coerce an arbitrary request representation into a RequestContext. This is the single boundary where legacy request shapes (raw Rack environments, {headers:, params:} hashes with symbol or string keys) are converted; everything downstream of authentication trusts this type.

Raises:

  • if the input cannot be coerced



137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/vector_mcp/request_context.rb', line 137

def self.coerce(request, transport_type = "http")
  case request
  when RequestContext
    request
  when Hash
    return from_rack_env(request, transport_type) if request.key?("REQUEST_METHOD")

    from_normalized_hash(request)
  else
    raise ArgumentError, "Cannot coerce #{request.class} into a VectorMCP::RequestContext"
  end
end

.from_rack_env(rack_env, transport_type) ⇒ RequestContext

Create a request context from a Rack environment. This is a convenience method for HTTP-based transports.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/vector_mcp/request_context.rb', line 201

def self.from_rack_env(rack_env, transport_type)
  # Handle nil rack_env by returning a minimal context
  return minimal(transport_type) if rack_env.nil?

  new(
    headers: VectorMCP::Util.extract_headers_from_rack_env(rack_env),
    params: VectorMCP::Util.extract_params_from_rack_env(rack_env),
    method: rack_env["REQUEST_METHOD"],
    path: rack_env["PATH_INFO"],
    transport_metadata: {
      transport_type: transport_type.to_s,
      remote_addr: rack_env["REMOTE_ADDR"],
      user_agent: rack_env["HTTP_USER_AGENT"],
      content_type: rack_env["CONTENT_TYPE"]
    }
  )
end

.minimal(transport_type) ⇒ RequestContext

Create a minimal request context for non-HTTP transports. This is useful for non-HTTP transports or testing contexts.



118
119
120
121
122
123
124
125
126
# File 'lib/vector_mcp/request_context.rb', line 118

def self.minimal(transport_type)
  new(
    headers: {},
    params: {},
    method: transport_type.to_s.upcase,
    path: "/",
    transport_metadata: { transport_type: transport_type.to_s }
  )
end

Instance Method Details

#[](key) ⇒ Object?

Hash-style read access for compatibility with custom authentication handlers written against the legacy {headers:, params:} request hash.



170
171
172
# File 'lib/vector_mcp/request_context.rb', line 170

def [](key)
  hash_view[key.to_sym]
end

#dig(key, *rest) ⇒ Object?

Dig into the context like a nested hash, e.g. context.dig(:headers, "X-API-Key").



188
189
190
191
192
193
# File 'lib/vector_mcp/request_context.rb', line 188

def dig(key, *rest)
  value = self[key]
  return value if rest.empty?

  value&.dig(*rest)
end

#header(name) ⇒ String?

Get a specific header value.



63
64
65
# File 'lib/vector_mcp/request_context.rb', line 63

def header(name)
  @headers[name.to_s]
end

#headers?Boolean

Check if the request context has any headers.



48
49
50
# File 'lib/vector_mcp/request_context.rb', line 48

def headers?
  !@headers.empty?
end

#http_transport?Boolean

Check if this is an HTTP-based transport.



86
87
88
89
90
91
92
# File 'lib/vector_mcp/request_context.rb', line 86

def http_transport?
  return false unless @method && @path

  # Check if method is an HTTP method
  http_methods = %w[GET POST PUT DELETE HEAD OPTIONS PATCH TRACE CONNECT]
  http_methods.include?(@method.upcase)
end

#inspectString

Detailed string representation for debugging.



229
230
231
232
233
234
# File 'lib/vector_mcp/request_context.rb', line 229

def inspect
  "#<#{self.class.name}:0x#{object_id.to_s(16)} " \
    "method=#{@method.inspect} path=#{@path.inspect} " \
    "headers=#{@headers.inspect} params=#{@params.inspect} " \
    "transport_metadata=#{@transport_metadata.inspect}>"
end

#key?(key) ⇒ Boolean Also known as: has_key?, include?, member?



176
177
178
# File 'lib/vector_mcp/request_context.rb', line 176

def key?(key)
  hash_view.key?(key.to_sym)
end

#merge(attributes) ⇒ RequestContext

Return a new context with the given attributes merged in. Nested hashes (headers, params, transport_metadata) are merged key-wise; scalar attributes are replaced.



100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/vector_mcp/request_context.rb', line 100

def merge(attributes)
  current = to_h
  merged = current.dup
  attributes.each do |key, value|
    merged[key] = if value.is_a?(Hash) && current[key].is_a?(Hash)
                    current[key].merge(value)
                  else
                    value
                  end
  end
  RequestContext.new(**merged)
end

#metadata(key) ⇒ Object?

Get transport-specific metadata.



79
80
81
# File 'lib/vector_mcp/request_context.rb', line 79

def (key)
  [key.to_s]
end

#param(name) ⇒ String?

Get a specific parameter value.



71
72
73
# File 'lib/vector_mcp/request_context.rb', line 71

def param(name)
  @params[name.to_s]
end

#params?Boolean

Check if the request context has any parameters.



55
56
57
# File 'lib/vector_mcp/request_context.rb', line 55

def params?
  !@params.empty?
end

#to_hHash

Convert the request context to a hash representation. This is useful for serialization and debugging.



35
36
37
38
39
40
41
42
43
# File 'lib/vector_mcp/request_context.rb', line 35

def to_h
  {
    headers: @headers,
    params: @params,
    method: @method,
    path: @path,
    transport_metadata: 
  }
end

#to_sString

String representation of the request context.



222
223
224
# File 'lib/vector_mcp/request_context.rb', line 222

def to_s
  "<RequestContext method=#{@method} path=#{@path} headers=#{@headers.keys.size} params=#{@params.keys.size}>"
end