Skip to content

Duplicate in-flight JSON-RPC request ids silently misrouted request-scoped messages #527

Description

@arpitjain099

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions