ruby-sdk/lib
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Koichi ITO b1818f25c8 Support W3C Trace Context Propagation via _meta per SEP-414
## Motivation and Context

SEP-414 (modelcontextprotocol/modelcontextprotocol#414, merged for
the 2026-07-28 spec release) documents OpenTelemetry trace context propagation
conventions for MCP: the un-prefixed `_meta` keys `traceparent`,
`tracestate`, and `baggage` are reserved (an explicit exception to
the reverse-DNS prefix rule) so trace context can flow between MCP clients and
servers per the W3C Trace Context and Baggage specifications.

This follows the TypeScript SDK's approach (typescript-sdk#2270):
guarantee `_meta` passthrough, export constants for the reserved key names,
and lock the behavior in with regression tests and documentation, without adding
an OpenTelemetry dependency (the Python SDK's python-sdk#2381 makes
`opentelemetry-api` a hard dependency instead, which conflicts with
this SDK's keep-dependencies-minimal policy):

- New `MCP::TraceContext` module exposing `TRACEPARENT_META_KEY`,
  `TRACESTATE_META_KEY`, `BAGGAGE_META_KEY`, and `META_KEYS`.
- The server side already passes incoming request `_meta` to tool and prompt
  handlers untouched via `server_context[:_meta]`; new regression tests pin
  that guarantee for the three reserved keys.
- Every `MCP::Client` request method (`call_tool`, `read_resource`,
  `get_prompt`, `complete`, `ping`, and the `list_*` methods) gains
  a `meta:` keyword so Ruby clients can inject trace context (or any other
  `_meta` entries) into outgoing requests; per SEP-414, trace context
  should flow on every request, not only tool calls. The caller's hash is
  never mutated. On `call_tool`, `progress_token` takes precedence over
  a `progressToken` entry in `meta`, and an empty merge result omits `_meta`
  entirely, preserving the existing wire format.
- README documents the convention and how to bridge the values to a tracing
  system such as the `opentelemetry-ruby` gems.

Scope is intentionally client-to-server: server-initiated requests
(`sampling/createMessage`, `roots/list`, `elicitation/create`) do not accept
`meta:` yet; propagating trace context on those is a separate follow-up.

Resolves #374.

## How Has This Been Tested?

- New `test/mcp/trace_context_test.rb` pins the exact reserved key names and
  the frozen `META_KEYS` list.
- New tests in `test/mcp/server_test.rb` assert that `tools/call` and
  `prompts/get` deliver `traceparent`, `tracestate`, and `baggage` (alongside
  `progressToken`) to handlers through `server_context[:_meta]` unchanged.
- New tests in `test/mcp/client_test.rb` cover the `meta:` keyword: the
  trace keys are sent in `_meta` on `call_tool` and `read_resource`,
  a table-driven test exercises the remaining request methods (`tools/list`,
  `resources/list`, `resources/templates/list`, `prompts/list`,
  `prompts/get`, `completion/complete`, `ping`), `progress_token` overrides
  a `progressToken` entry in `meta` without duplicating the key,
  the caller's `meta` hash is not mutated, and requests without `meta:`
  serialize exactly as before (wire-format regressions for both the empty `meta`
  hash and the no-params list request).

## Breaking Changes

None. `MCP::TraceContext` and the `meta:` keyword are purely additive, and
requests without `meta:` serialize exactly as before.
2026-06-12 14:36:24 +09:00
..
mcp Support W3C Trace Context Propagation via _meta per SEP-414 2026-06-12 14:36:24 +09:00
json_rpc_handler.rb Support notifications/cancelled per MCP specification 2026-05-03 04:02:22 +09:00
mcp.rb Support W3C Trace Context Propagation via _meta per SEP-414 2026-06-12 14:36:24 +09:00