MCP race: first API request is serialized before HTTP MCP servers finish connecting — tool_use fails with "No such tool available" (breaks --resume)
Summary
When using the Agent SDK (Python) with an external streamable HTTP MCP server, the CLI does not wait for MCP servers to finish connecting before serializing the first API request. The tool list of turn 1 is a snapshot taken at request time, and tool_use validation runs against that snapshot — not the live registry. If the model calls an MCP tool in turn 1, it gets No such tool available, even though the server finishes connecting successfully a few hundred ms later (and is connected at the moment of the call).
This bites hardest on --resume: the model knows the MCP tool names from session history (it used them successfully minutes earlier), so it calls them immediately in turn 1 — exactly inside the race window. Fresh sessions usually survive by accident because the first MCP call tends to happen in later turns.
Environment
- claude-agent-sdk (Python) 0.2.126, bundled CLI 2.1.218 (
claude-code/2.1.218 (sdk-py, agent-sdk/0.2.126)per MCP transport log) - Linux (Docker container), Node v26.3.0
- MCP server:
{"type": "http", "url": "https://mcp.airtable.com/mcp", "headers": {"Authorization": "Bearer …"}}(Airtable's public MCP server; connect takes ~370–450 ms) - Streaming input mode,
permission_mode=bypassPermissions
Millisecond timeline (from the CLI's own logs)
Session A (fresh) at 12:22 — works:
12:22:23.347 [mcp-log] Starting connection with timeout of 30000ms
12:22:23.791 [mcp-log] Successfully connected (transport: http) in 445ms
12:22:43.877 [mcp-log] Calling MCP tool: ping <- turn 3, ~20 s in — tools present, OK
Session A resumed one minute later — fails:
12:23:20.718 [mcp-log] Initializing HTTP transport to https://mcp.airtable.com/mcp
12:23:20.790 [session.jsonl] user message serialized <- first API request goes out HERE
12:23:21.091 [mcp-log] Successfully connected (transport: http) in 373ms <- 301 ms too late
12:23:24.571 [session.jsonl] assistant tool_use: mcp__<server>__list_automations
12:23:24.574 [session.jsonl] tool_result: <tool_use_error>Error: No such tool available:
mcp__<server>__list_automations</tool_use_error> <- rejected in 3 ms,
3.5 s AFTER the server successfully connected
The MCP log for the failing run shows a clean, successful connection and no errors — the server was up and connected for the entire turn; only the turn-1 tool snapshot predates it.
Expected behavior (any of these would fix it)
- Delay the first API request until MCP servers finish connecting (bounded by the existing 30 s connect timeout), or
- Re-validate an incoming
tool_useagainst the live MCP tool registry before rejecting withNo such tool available, or - At minimum, return a distinguishable error (e.g. "MCP server <name> is still connecting — retry") so the model/harness can self-heal instead of concluding the server is down.
Actual behavior
No such tool available — indistinguishable from a genuinely nonexistent tool. In our case the model then told the user "the MCP server disconnected", which was false.
Repro sketch
- Configure an external HTTP MCP server with realistic connect latency (~300–500 ms, any remote streamable HTTP server).
- Run a session where the model successfully calls one of its tools.
- Resume the session and immediately send a prompt that makes the model call the same tool in turn 1 (it will — it knows the tool from history).
- Turn 1 races the reconnect; the call fails with
No such tool availablewhile the mcp-log showsSuccessfully connecteda few hundred ms after the request went out.
Logs used: ~/.cache/claude-cli-nodejs/<cwd-slug>/mcp-logs-<server>/*.jsonl and ~/.claude/projects/<cwd-slug>/<session>.jsonl.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗