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.

Parameters:

  • headers (Hash) (defaults to: {})

    HTTP headers from the request (default: {})

  • params (Hash) (defaults to: {})

    Query parameters from the request (default: {})

  • method (String, nil) (defaults to: nil)

    HTTP method or transport-specific method (default: nil)

  • path (String, nil) (defaults to: nil)

    Request path or transport-specific path (default: nil)

  • transport_metadata (Hash) (defaults to: {})

    Transport-specific metadata (default: {})



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
  @transport_metadata = ().freeze
end

Instance Attribute Details

#headersHash (readonly)

HTTP headers from the request

Returns:

  • (Hash)

    the current value of headers



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

Returns:

  • (String, nil)

    the current value of method



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

def method
  @method
end

#paramsHash (readonly)

Query parameters from the request

Returns:

  • (Hash)

    the current value of params



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

def params
  @params
end

#pathString? (readonly)

Request path or transport-specific path

Returns:

  • (String, nil)

    the current value of path



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

def path
  @path
end

#transport_metadataHash (readonly)

Transport-specific metadata

Returns:

  • (Hash)

    the current value of transport_metadata



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

def 
  @transport_metadata
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.

Parameters:

  • request (RequestContext, Hash)

    the request to coerce

  • transport_type (String) (defaults to: "http")

    transport identifier used when building from a Rack env

Returns:

Raises:

  • (ArgumentError)

    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.

Parameters:

  • rack_env (Hash)

    The Rack environment hash

  • transport_type (String)

    The transport type identifier

Returns:

  • (RequestContext)

    A request context populated from the Rack environment



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.

Parameters:

  • transport_type (String)

    The transport type identifier

Returns:



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.

Parameters:

  • key (String, Symbol)

    one of :headers, :params, :method, :path, :transport_metadata

Returns:

  • (Object, nil)


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").

Parameters:

  • key (String, Symbol)

    the top-level key

  • rest (Array)

    further keys passed to the nested value's #dig

Returns:

  • (Object, nil)


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.

Parameters:

  • name (String)

    The header name

Returns:

  • (String, nil)

    The header value or nil if not found



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.

Returns:

  • (Boolean)

    True if headers are present, false otherwise



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.

Returns:

  • (Boolean)

    True if method is an HTTP method and path is present



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.

Returns:

  • (String)

    Detailed string representation



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?

Parameters:

  • key (String, Symbol)

    the top-level key to check

Returns:

  • (Boolean)


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.

Parameters:

  • attributes (Hash)

    attributes to merge

Returns:



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.

Parameters:

  • key (String, Symbol)

    The metadata key

Returns:

  • (Object, nil)

    The metadata value or nil if not found



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

def (key)
  @transport_metadata[key.to_s]
end

#param(name) ⇒ String?

Get a specific parameter value.

Parameters:

  • name (String)

    The parameter name

Returns:

  • (String, nil)

    The parameter value or nil if not found



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.

Returns:

  • (Boolean)

    True if parameters are present, false otherwise



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.

Returns:

  • (Hash)

    Hash representation of the request context



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: @transport_metadata
  }
end

#to_sString

String representation of the request context.

Returns:

  • (String)

    String representation for debugging



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