fix(StatelessHTTPServerTransport): reject colliding in-flight JSON-RPC ids (#254, #265) - #267
Open
jpurnell wants to merge 1 commit into
Open
Conversation
…C ids Per-request state (response waiter + HTTP context) was keyed by the client-chosen JSON-RPC id. Those ids are client-scoped, and this transport is multi-client, so concurrent POSTs with colliding ids (most clients start at 1) would: - overwrite the first request's response waiter — the first POST hangs forever and its continuation leaks (modelcontextprotocol#254); and - overwrite the first request's HTTP context — a handler processing one client's request could read another client's Authorization header (modelcontextprotocol#265). Reject a request whose id is already in flight with HTTP 409 / JSON-RPC -32600 instead of silently displacing the first. This isolates every in-flight exchange and closes both the hang/leak and the cross-client context disclosure. Transparent support for concurrent colliding ids is deferred to the stateless core (SEP-2575). Adds a regression test asserting the duplicate is rejected promptly (no hang), the first request's context is never overwritten, and only the first request reaches the server. Fixes modelcontextprotocol#254 Fixes modelcontextprotocol#265
jpurnell
force-pushed
the
fix/stateless-transport-id-correlation
branch
from
July 29, 2026 15:07
f7921c6 to
b79c7b3
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
StatelessHTTPServerTransportkeys per-request state — the response waiter and theoriginating HTTP context — on the client-chosen JSON-RPC id. JSON-RPC ids are
client-scoped, and this transport is explicitly multi-client, so concurrent POSTs with
colliding ids are legal and common (most clients start their id sequence at
1). Twoconcurrent requests sharing an id currently:
displaced and never resumed; that HTTP exchange hangs forever and the continuation leaks
(StatelessHTTPServerTransport: concurrent requests sharing a JSON-RPC id overwrite each other's response waiter (hang + continuation leak) #254); and
httpRequestContexts[id]) → a handlerprocessing one client's request can read another client's
Authorizationheader viaServer.currentHandlerContext.httpContext(StatelessHTTPServerTransport keys per-request HTTP context by client-chosen JSON-RPC id — concurrent clients with colliding ids can observe each other's HTTPRequest (including Authorization) #265).Fix
Reject a request whose id is already in flight with HTTP 409 / JSON-RPC
-32600instead of silently displacing the first request. The in-flight context map is populated
synchronously before any suspension, so it is a reliable "id in flight" marker on the
transport actor. This isolates every in-flight exchange and closes both the hang/leak and
the cross-client context disclosure.
This is the minimal, non-behavioral-change-to-
ctx.idfix. Transparent support forconcurrent colliding ids (via internal id remapping) is a larger change tied to the
stateless-core semantics in SEP-2575 (#245) and is intentionally out of scope here.
Tests
Adds
testCollidingInFlightRequestIDsRejected:httpRequestContextis never overwritten (auth stays isolated),All existing HTTP-server transport and handler-context tests pass unchanged; full MCP
suite green (552 tests).
Fixes #254
Fixes #265