ruby-sdk/lib/mcp.rb
Koichi ITO d3aec1c3e6 Add Stateless Lifecycle Foundations per SEP-2575
## Motivation and Context

SEP-2575 (modelcontextprotocol/modelcontextprotocol#2575, merged for the 2026-07-28 spec release) replaces
the `initialize` handshake with a stateless "modern" lifecycle: every request carries its protocol version,
client info, and client capabilities in reserved `_meta` keys, and the server validates each request independently.
This change lays the shared vocabulary for that lifecycle without changing any behavior:

- `MCP::Configuration` gains `LATEST_MODERN_PROTOCOL_VERSION` ("2026-07-28"), `SUPPORTED_MODERN_PROTOCOL_VERSIONS`,
  and `Configuration.modern_protocol_version?`. Modern versions are deliberately kept out of `SUPPORTED_STABLE_PROTOCOL_VERSIONS`
  so `initialize` can never negotiate them and `protocol_version=` keeps rejecting them.
- `MCP::ErrorCodes` gains `HEADER_MISMATCH` (-32020), completing the spec's stateless lifecycle error code block alongside
   the existing -32021/-32022 constants.
- New `MCP::RequestEnvelope` parses and validates the per-request `_meta` triple (`io.modelcontextprotocol/protocolVersion`,
  `clientInfo`, `clientCapabilities`, plus the optional deprecated `logLevel`). A request is classified as modern only
  when the full triple is present, matching the TypeScript SDK's `RequestMetaEnvelopeSchema` and the Python SDK's `_has_modern_envelope`,
  so partial or legacy `_meta` entries keep flowing through the legacy path untouched.
- New typed errors `Server::UnsupportedProtocolVersionError` (-32022 with `data: { supported:, requested: }`) and
  `Server::MissingRequiredClientCapabilityError` (-32021 with `data: { requiredCapabilities: }`) reuse the established `RequestHandlerError`
  `error_code`/`error_data` plumbing (the -32042 URL elicitation precedent).

Nothing dispatches through `RequestEnvelope` yet; the server-side modern handling, transport routing, and client support build on
this in follow-up changes.

Refs #389.

## How Has This Been Tested?

New `test/mcp/request_envelope_test.rb` covers the modern-triple classification (full triple, partial triple, string keys,
legacy `progressToken`), parsed field access, the -32022 error data shape, and invalid-request errors for incomplete or mistyped triples.
`test/mcp/configuration_test.rb` asserts the new constants, the predicate, and that modern versions stay rejected by `protocol_version=`.
`test/mcp/server_test.rb` asserts both typed errors surface on the wire with their SEP-2575 codes and data through `Server#handle`.
`test/mcp/error_codes_test.rb` pins -32020.

## Breaking Changes

None. Constants and classes are additive; no request path changes behavior.
2026-07-26 20:03:57 +09:00

37 lines
1 KiB
Ruby

# frozen_string_literal: true
require_relative "json_rpc_handler"
require_relative "mcp/configuration"
require_relative "mcp/string_utils"
require_relative "mcp/transport"
require_relative "mcp/version"
module MCP
autoload :Annotations, "mcp/annotations"
autoload :Apps, "mcp/apps"
autoload :Cancellation, "mcp/cancellation"
autoload :CancelledError, "mcp/cancelled_error"
autoload :Client, "mcp/client"
autoload :Content, "mcp/content"
autoload :ErrorCodes, "mcp/error_codes"
autoload :Icon, "mcp/icon"
autoload :Prompt, "mcp/prompt"
autoload :RequestEnvelope, "mcp/request_envelope"
autoload :Resource, "mcp/resource"
autoload :ResourceTemplate, "mcp/resource_template"
autoload :ResultType, "mcp/result_type"
autoload :Server, "mcp/server"
autoload :ServerSession, "mcp/server_session"
autoload :Tool, "mcp/tool"
autoload :TraceContext, "mcp/trace_context"
class << self
def configure
yield(configuration)
end
def configuration
@configuration ||= Configuration.new
end
end
end