Class: MCP::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/mcp/configuration.rb

Constant Summary collapse

LATEST_STABLE_PROTOCOL_VERSION =
"2026-07-28"
ROOTS_SAMPLING_LOGGING_DEPRECATED_PROTOCOL_VERSION =
"2026-07-28"
SUPPORTED_STABLE_PROTOCOL_VERSIONS =
[
  LATEST_STABLE_PROTOCOL_VERSION, "2025-11-25", "2025-06-18", "2025-03-26", "2024-11-05",
].freeze
DEFAULT_NEGOTIATED_PROTOCOL_VERSION =
"2025-03-26"
LATEST_MODERN_PROTOCOL_VERSION =

Protocol versions of the stateless "modern" lifecycle introduced by the MCP 2026-07-28 spec release (SEP-2575), where each request carries its own version in _meta and is validated against this list independently, with no handshake. These are reachable only through server/discover and the per-request envelope. https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2575

"2026-07-28"
SUPPORTED_MODERN_PROTOCOL_VERSIONS =
[LATEST_MODERN_PROTOCOL_VERSION].freeze
SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS =

Protocol versions reachable through the legacy initialize handshake, derived so the era partition (handshake = stable minus modern) cannot drift when a new revision lands. Per the SEP-2575 era model, an era is a property of the protocol version itself: legacy versions establish a session via initialize (2025-11-25 and earlier), and modern versions carry the version on every request in _meta with no handshake at all. The handshake therefore never negotiates a modern version: a client asking initialize for one is counter-offered LATEST_HANDSHAKE_PROTOCOL_VERSION, matching the TypeScript and Python SDKs.

(SUPPORTED_STABLE_PROTOCOL_VERSIONS - SUPPORTED_MODERN_PROTOCOL_VERSIONS).freeze
LATEST_HANDSHAKE_PROTOCOL_VERSION =
SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.first

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(exception_reporter: nil, around_request: nil, instrumentation_callback: nil, protocol_version: nil, validate_tool_call_arguments: true, validate_tool_call_results: false, instrument_server_context: false) ⇒ Configuration

Returns a new instance of Configuration.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/mcp/configuration.rb', line 56

def initialize(exception_reporter: nil, around_request: nil, instrumentation_callback: nil, protocol_version: nil,
  validate_tool_call_arguments: true, validate_tool_call_results: false, instrument_server_context: false)
  @exception_reporter = exception_reporter
  @around_request = around_request
  @instrumentation_callback = instrumentation_callback
  @protocol_version = protocol_version
  if protocol_version
    validate_protocol_version!(protocol_version)
  end
  validate_value_of_validate_tool_call_arguments!(validate_tool_call_arguments)
  validate_value_of_validate_tool_call_results!(validate_tool_call_results)
  validate_value_of_instrument_server_context!(instrument_server_context)

  @validate_tool_call_arguments = validate_tool_call_arguments
  @validate_tool_call_results = validate_tool_call_results
  @instrument_server_context = instrument_server_context
end

Instance Attribute Details

#around_requestObject



122
123
124
# File 'lib/mcp/configuration.rb', line 122

def around_request
  @around_request || default_around_request
end

#exception_reporterObject



114
115
116
# File 'lib/mcp/configuration.rb', line 114

def exception_reporter
  @exception_reporter || default_exception_reporter
end

#instrumentation_callbackObject

Deprecated.

Use #around_request instead. instrumentation_callback fires only after a request completes and cannot wrap execution in a surrounding block (e.g. for Application Performance Monitoring (APM) spans).

See Also:



134
135
136
# File 'lib/mcp/configuration.rb', line 134

def instrumentation_callback
  @instrumentation_callback || default_instrumentation_callback
end

#validate_tool_call_argumentsObject

Returns the value of attribute validate_tool_call_arguments.



144
145
146
# File 'lib/mcp/configuration.rb', line 144

def validate_tool_call_arguments
  @validate_tool_call_arguments
end

#validate_tool_call_resultsObject

Returns the value of attribute validate_tool_call_results.



145
146
147
# File 'lib/mcp/configuration.rb', line 145

def validate_tool_call_results
  @validate_tool_call_results
end

Class Method Details

.handshake_protocol_version?(version) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
# File 'lib/mcp/configuration.rb', line 34

def handshake_protocol_version?(version)
  SUPPORTED_HANDSHAKE_PROTOCOL_VERSIONS.include?(version)
end

.modern_protocol_version?(version) ⇒ Boolean

Returns:

  • (Boolean)


30
31
32
# File 'lib/mcp/configuration.rb', line 30

def modern_protocol_version?(version)
  SUPPORTED_MODERN_PROTOCOL_VERSIONS.include?(version)
end

.reject_modern_handshake_version!(version) ⇒ Object

The one statement of the client-side handshake contract, shared by every transport: a modern version cannot ride the legacy initialize handshake.

Raises:

  • (ArgumentError)


40
41
42
43
44
45
# File 'lib/mcp/configuration.rb', line 40

def reject_modern_handshake_version!(version)
  return unless version && modern_protocol_version?(version)

  raise ArgumentError, "protocol version #{version.inspect} cannot be negotiated through the legacy " \
                       "`initialize` handshake; use `mode: :modern` (or `:auto`) instead"
end

Instance Method Details

#around_request?Boolean

Returns:

  • (Boolean)


126
127
128
# File 'lib/mcp/configuration.rb', line 126

def around_request?
  !@around_request.nil?
end

#exception_reporter?Boolean

Returns:

  • (Boolean)


118
119
120
# File 'lib/mcp/configuration.rb', line 118

def exception_reporter?
  !@exception_reporter.nil?
end

#instrument_server_context=(instrument_server_context) ⇒ Object

Opt in to exposing the user-defined server_context in the around_request / instrumentation_callback data hash. Off by default: the hash is application-supplied and may hold values a tracing backend should not receive, so surfacing it has to be a deliberate choice.



90
91
92
93
94
# File 'lib/mcp/configuration.rb', line 90

def instrument_server_context=(instrument_server_context)
  validate_value_of_instrument_server_context!(instrument_server_context)

  @instrument_server_context = instrument_server_context
end

#instrument_server_context?Boolean

Returns:

  • (Boolean)


147
148
149
# File 'lib/mcp/configuration.rb', line 147

def instrument_server_context?
  !!@instrument_server_context
end

#instrumentation_callback?Boolean

Deprecated.

Use #around_request? instead.

Returns:

  • (Boolean)

See Also:



140
141
142
# File 'lib/mcp/configuration.rb', line 140

def instrumentation_callback?
  !@instrumentation_callback.nil?
end

#merge(other) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/mcp/configuration.rb', line 159

def merge(other)
  return self if other.nil?

  exception_reporter = if other.exception_reporter?
    other.exception_reporter
  else
    @exception_reporter
  end

  around_request = if other.around_request?
    other.around_request
  else
    @around_request
  end

  instrumentation_callback = if other.instrumentation_callback?
    other.instrumentation_callback
  else
    @instrumentation_callback
  end

  protocol_version = if other.protocol_version?
    other.protocol_version
  else
    @protocol_version
  end

  validate_tool_call_arguments = other.validate_tool_call_arguments
  validate_tool_call_results = other.validate_tool_call_results

  Configuration.new(
    exception_reporter: exception_reporter,
    around_request: around_request,
    instrumentation_callback: instrumentation_callback,
    protocol_version: protocol_version,
    validate_tool_call_arguments: validate_tool_call_arguments,
    validate_tool_call_results: validate_tool_call_results,
    instrument_server_context: other.instrument_server_context?,
  )
end

#protocol_versionObject

The pin scopes the initialize handshake, so an unset pin reads as the version that handshake settles on by default. Reading the newest version of any era here would hand back a value the writer rejects, and no caller wants the modern revision: a modern connection carries its version on every request instead of consulting configuration.



106
107
108
# File 'lib/mcp/configuration.rb', line 106

def protocol_version
  @protocol_version || LATEST_HANDSHAKE_PROTOCOL_VERSION
end

#protocol_version=(protocol_version) ⇒ Object



74
75
76
77
78
# File 'lib/mcp/configuration.rb', line 74

def protocol_version=(protocol_version)
  validate_protocol_version!(protocol_version)

  @protocol_version = protocol_version
end

#protocol_version?Boolean

Returns:

  • (Boolean)


110
111
112
# File 'lib/mcp/configuration.rb', line 110

def protocol_version?
  !@protocol_version.nil?
end

#validate_tool_call_arguments?Boolean

Returns:

  • (Boolean)


151
152
153
# File 'lib/mcp/configuration.rb', line 151

def validate_tool_call_arguments?
  !!@validate_tool_call_arguments
end

#validate_tool_call_results?Boolean

Returns:

  • (Boolean)


155
156
157
# File 'lib/mcp/configuration.rb', line 155

def validate_tool_call_results?
  !!@validate_tool_call_results
end