feat(core,server): expose the per-request envelope on the request handler context#2231
feat(core,server): expose the per-request envelope on the request handler context#2231felixweinberger wants to merge 4 commits into
Conversation
|
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/server
@modelcontextprotocol/server-legacy
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
@modelcontextprotocol/client
@modelcontextprotocol/codemod
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
43d0c8a to
2fbd605
Compare
2f09caf to
5be01e3
Compare
|
Trimmed 4 of the 7 unit tests after a mutation-based audit (break each behavior, check which layers catch it). Removed: the synthetic-subclass seam test, the capabilities/info passthrough test, the pinned-older-version test (defective — it pinned the SDK default, so an always-emit-default bug passed it), and the {}-capabilities-shape test — every mutation they catch is also caught by the e2e cells across all transports. Kept the 3 unit tests that guard pre-handshake state, which is wire-unobservable: 2 of 7 mutations produced zero e2e failures and only these tests caught them. |
4190607 to
dbab53e
Compare
Exposes the per-request envelope on the request handler context:
ctx.mcpReq.protocolVersion(both sides) andctx.client.{capabilities, info}(server side). Handlers can finally answer "what protocol version am I serving, who is calling, and what can they do."Motivation and Context
Today a request handler cannot know any of this: the negotiated protocol version is discarded (fixed in #2230), and client capabilities/info are only reachable through connection-scoped getters on the Server instance, not from handler context.
This is the keystone of the per-request envelope groundwork for the 2026-07-28 spec release (#2184): under the draft spec, protocol version and client facts travel on every request (
_meta), and handlers/SDK internals need one place to read them that works identically in both eras. This PR makes that place exist, sourced from the 2025 handshake (the only source today); the 2026_metasourcing plugs into the same fields when per-request envelope support lands.API shape:
ctx.mcpReq.protocolVersion: string— onBaseContext(request fact, both server and client handlers)ctx.client: { capabilities, info }— on the server context only (peer facts; the client's peer is a server, whose facts come fromgetServerCapabilities())How Has This Been Tested?
protocol:envelope:ctx-version-readable,protocol:envelope:ctx-capabilities-readable) with scenarios covering: the negotiated version (including a pinned older version), capabilities/info matching what the client declared, empty-capabilities clients, and a client-side sampling handler reading the version.Breaking Changes
None. Additive only.
Types of changes
Checklist
Additional context
protected get negotiatedProtocolVersion()onProtocol, overridden byServer/Clientto surface their retained negotiated version;_onrequestcentralizes the pre-initialize fallback.ctx.client.*and the existing connection-scopedgetClientCapabilities()/getClientVersion()is documented in both JSDoc and the e2e manifest; the structural supersession is recorded when 2026 connections become possible (the connection-scoped getters have no meaning without a handshake).