[Bug] MCP tool call wedges indefinitely without client-side timeout (CLI, no MCP_TOOL_TIMEOUT default)
Type: Bug / robustness + feature (default timeout)
Claude Code version: 2.1.181 • OS: macOS 24.6.0 (darwin), zsh • Model: Opus 4.8 (1M context)
Summary
A single in-flight MCP tool call (run_snowflake_query, stdio MCP server) stalled server-side before the backend ever received the work, and Claude Code blocked on it for 6,348 seconds (~106 minutes) with no client-side timeout and no user-visible elapsed-time feedback. The session looked frozen ("Claude hung"); the only way out was a manual interrupt. This is distinct from the Claude Desktop timeout reports (#22542, #64614), which are the opposite problem — an over-aggressive fixed cap. Here the CLI has no effective cap.
What I expected
Either (a) a sane default per-tool-call timeout that aborts a wedged MCP call and returns a tool error, or (b) clear, continuously-updating user-facing feedback (elapsed time / "still running") plus a way to cancel just the tool call — so a stalled MCP server doesn't present as a frozen UI.
What happened
- Two sequential
run_snowflake_querycalls (not a parallel batch). Call 1 returned cleanly in ~2.7s. - Call 2 was dispatched and never returned. The MCP server's own log shows it received the call and emitted
still running (N s elapsed)heartbeats every 30s, climbing to 6,341s, thenTool 'run_snowflake_query' failed after 6348s: MCP error -32001: user-cancel— i.e., it ended only on my manual interrupt. - The backend (Snowflake) has zero record of call 2 ever executing — no SUCCESS, FAIL, CANCELLED, or RUNNING row. So the stall was in the MCP server's submit path, before the query reached the backend.
MCP_TIMEOUTandMCP_TOOL_TIMEOUTwere unset (env + all settings.json). The call ran unbounded.
MCP server log excerpt (Snowflake MCP Server v2.14.7)
2026-06-18T19:32:21.833Z | Calling MCP tool: run_snowflake_query
2026-06-18T19:32:51.835Z | Tool 'run_snowflake_query' still running (30s elapsed)
2026-06-18T19:33:21.836Z | Tool 'run_snowflake_query' still running (60s elapsed)
... (heartbeats every 30s) ...
2026-06-18T21:18:03.467Z | Tool 'run_snowflake_query' still running (6341s elapsed)
2026-06-18T21:18:10.413Z | Tool 'run_snowflake_query' failed after 6348s: MCP error -32001: user-cancel
During that ~106 min the session transcript recorded no events between the tool dispatch and the user interrupt.
Impact
Any stdio MCP tool call that wedges server-side hangs the whole Claude Code session indefinitely. The MCP layer clearly has the progress signal (it logs still running (N s elapsed)), but it is not surfaced in the TUI and does not feed a timeout. Users experience it as a random freeze "with some frequency."
Requests
- Ship a sane default
MCP_TOOL_TIMEOUT(per-tool-call execution ceiling) so a wedged call aborts and returns a tool error instead of hanging forever. #22542 already asks forMCP_TOOL_TIMEOUTparity — please confirm/document its CLI semantics and give it a non-infinite default. - Surface long-running tool feedback in the TUI — the
still running (N s elapsed)heartbeat already exists in the MCP log; show it (elapsed counter) so a slow/stalled call is distinguishable from a frozen client. - Allow cancelling a single tool call without interrupting the whole turn/session.
Repro (approximate)
- Configure a stdio MCP server whose tool can stall in its submit path (network read / connection-handshake stall after a prior successful call).
- Issue a tool call that triggers the stall.
- Observe: no client-side timeout fires; the TUI shows no elapsed time; the session appears frozen until manual interrupt.
(In my case the trigger query was a COUNT(DISTINCT CASE WHEN … IN (subquery)) over a LATERAL FLATTEN of a 30M-row table — a heavy compile — but the defect is the unbounded, feedback-less wait, not the query.)
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗