Remote MCP connector: concurrent conversations share one MCP session, causing responses to cross between them

Status Open
Maintainer reply None cached
Activity 1 comment · opened Jul 19, 2026

Remote MCP connector: concurrent conversations share one MCP session, causing responses to cross between them

Surface: claude.ai remote MCP connectors (custom connector over streamable HTTP + OAuth)
Date observed: 2026-07-19, ~22:20 UTC
Server: self-hosted Python MCP server, mcp 1.26.0 / fastmcp 3.2.0, stateful streamable HTTP

What happened

Two of my Claude conversations were using the same custom connector at the same time. Within a 217 ms window, the server received two tools/call requests — one from each conversation, arriving from the same connector egress addresses:

22:20:43.472  POST /mcp  CallToolRequest   (conversation A — a journal-append tool)
22:20:43.689  POST /mcp  CallToolRequest   (conversation B — an entity-update tool)

Conversation B's tool call returned conversation A's response payload — a receipt from a completely different tool, referencing a different record and a different conversation's id. B's own write had in fact succeeded; only the response was wrong. To the model in conversation B, the result was indistinguishable from a genuine reply, and it spent the next turn reasoning about a receipt for work it had never requested.

Root cause, and where each half lives

The failure needs both halves:

  1. Server/SDK half. In stateful streamable HTTP, the MCP Python SDK registers each in-flight request's response stream in a per-session dict keyed by the bare JSON-RPC request id (streamable_http.py, _handle_post_request). A second request arriving on the same session with an already-in-flight id overwrites the first's entry, so the first response is delivered to the second caller. I've filed this separately against modelcontextprotocol/python-sdk with a minimal reproduction: https://github.com/modelcontextprotocol/python-sdk/issues/3137
  1. Connector half — this issue. The collision only happens if two independent conversations share one MCP session. Each conversation numbers its own JSON-RPC requests independently starting from 1, so if the connector multiplexes them over a single session, colliding ids are not an edge case — they're the expected steady state. That is what the timing and the crossed payloads indicate here.

Neither half is wrong in isolation: sharing a session is a reasonable pooling strategy, and id-keying is a reasonable registry design for a single-client session. Together they silently misroute responses between a user's conversations.

Why I'm reporting the connector side separately

Even after the SDK is fixed, session sharing across conversations is worth being explicit about, because it changes what server authors must assume:

  • Any per-session state a server keeps (auth context, request counters, in-flight registries, progress tokens, cancellation scopes) is shared across conversations that the user reasonably believes are isolated.
  • Third-party MCP servers built on other SDKs may have their own variants of the same id-keyed assumption.
  • Server authors currently have no signal that a session is shared. If connector requests carried a per-conversation identifier — or if sessions were not shared across conversations — servers could key their state correctly.

Impact

For a single-user server like mine, the blast radius was one wrong tool result. On a multi-user MCP server behind the same connector infrastructure, the same mechanics deliver one user's tool output to another user's conversation, with no error and no way for the receiving side to detect it.

Mitigation on my side (in case it helps others)

Switching my servers to stateless HTTP (FASTMCP_STATELESS_HTTP=true) gives each request its own transport and eliminates the collision entirely — verified against a reproduction that swaps reliably in stateful mode and is clean in stateless. This is only available to servers that don't need stateful features (server-initiated messages, resumability, subscriptions).

Ask

  1. Confirm whether remote connectors intentionally multiplex multiple conversations over a single MCP session.
  2. If so, consider either giving each conversation its own session, or exposing a per-conversation identifier to the server so per-session state can be partitioned correctly.
  3. Document the sharing behavior for custom-connector authors either way — the assumption that one MCP session equals one logical client is a natural one to make, and it is currently wrong in a way that fails silently.

Related but distinct: #79231 (connectors intermittently failing to attach at session start).

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗