Opening this as the public record for the defect fixed in #521, as @koic suggested.
A request id is the only key that routes request-scoped messages back to the request that caused them, and nothing checked whether the id was already taken. A second request arriving under an id still in flight took the routing entry over, and from that point:
- progress and log notifications for the first request were written to the second request's SSE stream, through
active_stream in the Streamable HTTP transport;
- server-to-client requests, so sampling and elicitation prompts, resolved through the same map and were misdirected the same way;
drop_broken_stream removed whichever stream held the id rather than the one that had actually failed, so a collision closed one stream and unregistered the other;
ServerSession#register_in_flight was keyed the same way outside the transport, so notifications/cancelled routing broke on every transport, stdio included.
The spec places the uniqueness obligation on the sender, and the 2026-07-28 revision draws it at exactly this window: "The request ID MUST NOT match the ID of any other request the sender has issued and not yet received a response for". The defect was that the server neither enforced the rule nor refused the violation, and misrouted silently instead.
#521 refuses a request whose id is already in flight, as Invalid Request from the server core and 409 from the Streamable HTTP transport before any stream is registered, and identity-guards every removal keyed by request id. Only the in-flight window is enforced, so sequential reuse of an id still works.
I reported this privately first. It was handled as a public fix rather than an advisory because reaching it needs the victim's Mcp-Session-Id, which already permits tool execution in that session, so nothing new is gained by the misrouting.
Opening this as the public record for the defect fixed in #521, as @koic suggested.
A request id is the only key that routes request-scoped messages back to the request that caused them, and nothing checked whether the id was already taken. A second request arriving under an id still in flight took the routing entry over, and from that point:
active_streamin the Streamable HTTP transport;drop_broken_streamremoved whichever stream held the id rather than the one that had actually failed, so a collision closed one stream and unregistered the other;ServerSession#register_in_flightwas keyed the same way outside the transport, sonotifications/cancelledrouting broke on every transport, stdio included.The spec places the uniqueness obligation on the sender, and the 2026-07-28 revision draws it at exactly this window: "The request ID MUST NOT match the ID of any other request the sender has issued and not yet received a response for". The defect was that the server neither enforced the rule nor refused the violation, and misrouted silently instead.
#521 refuses a request whose id is already in flight, as Invalid Request from the server core and 409 from the Streamable HTTP transport before any stream is registered, and identity-guards every removal keyed by request id. Only the in-flight window is enforced, so sequential reuse of an id still works.
I reported this privately first. It was handled as a public fix rather than an advisory because reaching it needs the victim's
Mcp-Session-Id, which already permits tool execution in that session, so nothing new is gained by the misrouting.