Session hangs indefinitely mid-turn: ide MCP tool calls (auto getDiagnostics on Write) have no timeout, while connect does
Environment
- Claude Code: 2.1.232 and 2.1.233 (one hung session on each)
- Platform: WSL2 Ubuntu (kernel 6.18.33.2-microsoft-standard-WSL2), Windows host
- IDE integration: Claude Code JetBrains Plugin 0.1.14-beta in IntelliJ IDEA 2026.2 (IDE on the Windows host), transport
ws-ide - Model: claude-opus-5 (not relevant to the bug)
Summary
If the IDE plugin's websocket endpoint dies leaving the connection half-open (no FIN/RST — in our case the JetBrains plugin wedged while IntelliJ kept running), the next Write tool use hangs the session forever: Claude Code auto-invokes getDiagnostics on the ide MCP server after the file write, that call has no timeout, and the turn never completes. No error, no feedback; user messages just queue up.
Two sessions hung this way on 2026-08-15/16: one for 2h21m, one for 4h12m, both until manually killed. The user's last queued prompt in one of them was literally "What are you doing? You haven't given feedback in a long time."
The asymmetry: the connect path has a 30s timeout (CONNECT_TIMEOUT fires and the session degrades gracefully to no-IDE mode), but in-flight tool calls on an established connection can block indefinitely.
Evidence (from ~/.cache/claude-cli-nodejs/<project>/mcp-logs-ide/)
Session A (Claude Code 2.1.233): emitted a Write tool_use at 2026-08-15T09:57:36Z (per session transcript); no tool_result ever arrived. The ide MCP log shows:
"debug":"Tool 'getDiagnostics' still running (31s elapsed)"
"debug":"Tool 'getDiagnostics' still running (63s elapsed)"
... (269 "still running" entries, one every ~30s) ...
"debug":"Tool 'getDiagnostics' failed after 8477s: MCP error -32000: Connection closed" ← at 12:18:53Z, when the process was killed
12:18:53Z − 8477s = 09:57:36Z, exactly the timestamp of the pending Write.
Session B (Claude Code 2.1.232): same pattern, Write at 2026-08-15T14:16:21Z:
... (479 "still running" entries) ...
"debug":"Tool 'getDiagnostics' failed after 15132s: MCP error -32000: Connection closed" ← at 18:28:33Z, on manual kill
18:28:33Z − 15132s = 14:16:21Z, again exactly the pending Write.
Both sessions had connected successfully to the plugin at startup:
"debug":"Successfully connected (transport: ws-ide) in 116ms"
"debug":"Connection established with capabilities: {... \"serverVersion\":{\"name\":\"Claude Code JetBrains Plugin\",\"version\":\"0.1.14-beta\"}}"
and had dozens of getDiagnostics completed in 4s-style successes before the endpoint wedged.
By contrast, sessions started after the endpoint died fail fast and work fine:
"debug":"Starting connection with timeout of 30000ms"
"debug":"Connection timeout triggered after 31995ms (limit: 30000ms)"
"error":"Connection failed (CONNECT_TIMEOUT): MCP server \"ide\" connection timed out after 30000ms"
Key observations
- The client already knows the call is stuck. The watchdog logs
Tool 'getDiagnostics' still running (Ns elapsed)every ~30 seconds — 269 and 479 times respectively — but never cancels, times out, or surfaces anything to the user. - A half-open websocket defeats TCP-level detection. The IDE process (IntelliJ) stayed alive; only the plugin endpoint wedged, so no FIN/RST arrived and the call blocked until process kill. There appears to be no application-level ping/keepalive on
ws-ide. - The hang is invisible. The session shows no spinner state distinguishable from normal work; the user waited hours and queued messages before killing it.
- Side effect on kill: in Session B, the pending
Writeexecuted during teardown (file mtime matches the SIGINT timestamp) — surprising after a 4-hour-old intent, and worth considering in its own right.
Expected behavior
- A per-call timeout on
ideMCP tool invocations — especially harness-initiated ones like the automaticgetDiagnosticsafterWrite, which the model never asked for and whose result is best-effort. On timeout: log, skip diagnostics, complete theWritenormally. - And/or websocket ping/keepalive on
ws-ideso a half-open connection is detected and the session degrades to no-IDE mode, the same wayCONNECT_TIMEOUTalready does at startup. - The existing "still running (Ns elapsed)" watchdog is the natural place to enforce a cap.
Reproduction sketch
- Start a Claude Code session from a terminal associated with an IDE running the Claude Code plugin (JetBrains in our case), so the
ideMCP connects (ws-ide). - Wedge the plugin endpoint without closing the TCP connection (e.g., SIGSTOP the IDE/plugin process, or drop its packets with a firewall rule) — simulating the plugin hang we experienced.
- Ask Claude to write any file. The turn blocks forever in the auto
getDiagnostics; the ide MCP log accumulatesstill runningentries every ~30s indefinitely.