MCP tool call issued during session re-initialisation is silently discarded

Status Open
Maintainer reply None cached
Activity 1 comment · opened Aug 3, 2026

Summary

When a streamable-http MCP connector's session goes stale, the client correctly
receives 404, re-initialises, and the new session works. But a tool call issued
around that re-initialisation is neither dispatched, retried, nor failed
— it is
silently discarded. The caller sees either a 300s hang ending in an abort, or a
bogus successful-but-empty result.

Server-side logs show the re-init completing normally and then no request for the
tool call ever arriving
.

Environment

  • Claude Code CLI, long-lived Remote Control sessions.
  • Auth: claude.ai login (keyless — ANTHROPIC_API_KEY deliberately unset), so these

are claude.ai org connectors, not locally-registered mcpServers entries.

  • Backends: self-hosted MCP servers speaking streamable-http behind a reverse proxy,

fronted by OAuth. Stateful sessions (server default).

  • Reproduced on two independent connectors with different backends.

Symptom A — 300s hang, no response

A memory_read-style tool call hung with no output. The client reported at 120s
"still running after 120s, moved to background", and at 300s:

MCP server "<name>" tool "<tool>" sent no response or progress for 300s; aborting.

Retried ~10 seconds later: hung identically. Both attempts produced zero server-side
requests.

Symptom B — returns "completed with no output"

The same defect on a second connector, milder. A read-only directory-listing tool
returned promptly with "completed with no output" — not an error, not data. The very
next call on the same connector succeeded normally.

This variant is the clearer evidence the fault is client-side: a network problem would
time out or error, it would not synthesise a clean empty success.

Server-side evidence

Reverse-proxy access log timestamps requests at receipt, so a request that arrived
and then stalled would still appear. Nothing appears.

Connector 1, around the hang:

17:19:52  POST /mcp -> 404      stale session id
17:19:53  POST /mcp -> 200      initialize
17:19:53  POST /mcp -> 202      notifications/initialized
17:19:54  POST /mcp -> 200
17:19:54  POST /mcp -> 200
17:19:55  POST /mcp -> 200      tools/list (16.5 KB)   <-- re-init COMPLETE, connector live
          ... tool call issued here; TWO attempts ~10s apart ...
          ... no further requests for 11 minutes ...
17:30:58  POST /mcp -> 404      next session, same cycle

Connector 2, symptom B captured live:

18:35:04  POST /mcp -> 404      stale session id
18:35:05  POST /mcp -> 200      initialize
18:35:06  POST /mcp -> 202
18:35:07  POST /mcp -> 200 x3   tools/list etc.
          <-- first tool call landed in this window: "completed with no output"
18:35:19  POST /mcp -> 200      second tool call: worked

Backend health during both: service up for 1d10h with no restarts, no crashes, no
tracebacks. An equivalent query executes in 19 ms; an unauthenticated probe returns
401 in 31 ms. The backend was idle and healthy throughout.

Why the session went stale (context, not the bug)

Worth stating because it is easy to misdiagnose: the server's session store had no
idle timeout configured
, sessions are removed only on shutdown / explicit terminate /
session-task crash, and the journal shows none of those. So the 404 was the client
presenting a session ID minted by an earlier server process — i.e. the client
appears to cache session IDs across backend restarts and only discovers they are dead
on reuse.

That 404 is correct server behaviour and the re-initialisation that follows works
fine. The bug is only that a call issued in that window is lost.

Expected

A tool call must reach a terminal state. Any of these would be acceptable:

  • replay it onto the newly-established session, or
  • fail it fast with a transport error so the caller can retry, or
  • at minimum surface a timeout distinguishable from a successful empty result.

Silently discarding a call while reporting success (symptom B) is the worst outcome,
because the model treats the empty result as fact.

Actual

The call is dropped. No dispatch, no retry, no error. Caller waits out its full 300s
timeout, or receives a fabricated empty success.

Workaround

Running the affected servers with stateless_http=True removes the session ID entirely,
so there is no stale-session 404 and no re-init window for a call to be lost in. After
switching two backends, reconnects show zero 404s and no recurrence so far.

This removes the trigger, not the defect — a call lost for any other reason would
still be discarded the same way.

Relationship to other issues

  • Closely related behaviour observed on the same setup: once a connector is stranded, it is never retried for the

session's lifetime and the reconnect command is unavailable over Remote Control, so an
RC session has no in-session recovery path at all. Together, these mean a brief blip
costs a connector for the whole session.

  • #60385 (closed 2026-07-15) — different defect, same general area: a tool call reaching

no terminal state over Remote Control.

  • Not related to #64350 / #64384 (WAF false-positives on tool-call bodies): those were

blocked requests that arrived and were rejected at the edge. Here nothing arrives,
and the backend is not behind that WAF path.

View original on GitHub ↗

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