claude-code - 💡(How to fix) Fix Claude Desktop (Windows): stdio MCP `tools/call` silently dropped after successful handshake — host-side dispatch never delivers the call to the subprocess [3 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#60550Fetched 2026-05-20 03:55:41
View on GitHub
Comments
3
Participants
2
Timeline
5
Reactions
0
Timeline (top)
commented ×3closed ×1labeled ×1

On Claude Desktop for Windows, any stdio MCP server's tools/call is silently dropped before reaching the subprocess. The handshake (initialize + tools/list + resources/list) completes successfully — tools appear in the LLM's available-tools list (Claude in chat confirms it can see them) — but when the LLM emits a tool_use for any of those tools, the request never arrives at the stdio subprocess. The client surfaces a ~4-minute timeout error claiming "the local MCP server was unresponsive", while the subprocess log shows zero tools/call entries during that window.

This is not the same as #60224 (slow initialize causing the tool list to be dropped from ToolSearch). Here the tool list registers correctly and is visible to the LLM; the break is one stage downstream — between the LLM emitting tool_use and Claude Desktop forwarding it as JSON-RPC tools/call to the subprocess.

A trivial 60-line, zero-dependency stdio server reproduces the bug, ruling out SDK / slow-init / dependency-related causes.

Error Message

2026-05-19 10:11:01 [error] Session local_e94d8111-... query error: Claude Code process exited with code 1073807364 at BPi.getProcessExitError (...\app-1.7196.3\resources\app.asar.vite\build\index.js:406:8122) at ChildProcess.i (...\index.js:406:11166)

Root Cause

On Claude Desktop for Windows, any stdio MCP server's tools/call is silently dropped before reaching the subprocess. The handshake (initialize + tools/list + resources/list) completes successfully — tools appear in the LLM's available-tools list (Claude in chat confirms it can see them) — but when the LLM emits a tool_use for any of those tools, the request never arrives at the stdio subprocess. The client surfaces a ~4-minute timeout error claiming "the local MCP server was unresponsive", while the subprocess log shows zero tools/call entries during that window.

This is not the same as #60224 (slow initialize causing the tool list to be dropped from ToolSearch). Here the tool list registers correctly and is visible to the LLM; the break is one stage downstream — between the LLM emitting tool_use and Claude Desktop forwarding it as JSON-RPC tools/call to the subprocess.

A trivial 60-line, zero-dependency stdio server reproduces the bug, ruling out SDK / slow-init / dependency-related causes.

Fix Action

Fix / Workaround

(Exit 1073807364 = 0x40010004 = DBG_TERMINATE_PROCESS.) The crash occurred while trying to spawn the bundled Code daemon for an archived Code session whose cwd no longer existed on disk. Triggered by a Sentry.caught flood (50+ entries in two seconds), after which LocalMcpServerManager never reports Connected (N tools) again — but per-server handshakes continue completing successfully. Tool dispatch is broken from that moment on, persistently, across launches / versions / a full uninstall + reinstall + userdata wipe.

This suggests the degraded state is server-side / account-tied: a fresh Claude Desktop install with empty local data reproduces the same tools/call black-hole behaviour. Local-state interventions (cache wipe, session-file delete, version downgrade, full reinstall) do not recover dispatch.

The host's tool_use → tools/call dispatcher uses a registry whose populate-once code path is gated on LocalMcpServerManager.Connected events. After the 1073807364 cascade the manager logs Closing all (0 servers) on every quit cleanup and never re-runs whatever code emits Connected (N tools) — so for the rest of the install's lifetime, the registry has the tools listed (tools/list works → LLM sees them) but no entry in the dispatch table (LLM-emitted tool_use for those names has no route, silently discarded, eventually timing out client-side).

Code Example

{
  "mcpServers": {
    "hello-test": {
      "command": "C:\\Program Files\\nodejs\\node.exe",
      "args": ["C:\\path\\to\\server.mjs"]
    }
  }
}

---

import { createInterface } from 'node:readline';
const rl = createInterface({ input: process.stdin });
const send = (m) => process.stdout.write(JSON.stringify(m) + '\n');
const TOOL = { name: 'hello_test', description: 'Trivial diagnostic tool.', inputSchema: { type: 'object', properties: {} } };
rl.on('line', (line) => {
  if (!line.trim()) return;
  const msg = JSON.parse(line);
  const handlers = {
    initialize: () => ({ protocolVersion: msg.params.protocolVersion, capabilities: { tools: {} }, serverInfo: { name: 'hello-test', version: '0.1.0' } }),
    'tools/list': () => ({ tools: [TOOL] }),
    'tools/call': () => ({ content: [{ type: 'text', text: 'It works.' }] }),
  };
  const fn = handlers[msg.method];
  if (fn && msg.id != null) send({ jsonrpc: '2.0', id: msg.id, result: fn() });
});
process.stderr.write('hello-test ready over stdio\n');

---

2026-05-19T13:49:39.229Z [hello-test] Server started and connected successfully
2026-05-19T13:49:39.760Z [hello-test] Message from client: {"method":"initialize",...,"id":0}
2026-05-19T13:49:39.763Z [hello-test] Message from server: {"jsonrpc":"2.0","id":0,"result":...}     # 3 ms
2026-05-19T13:49:40.052Z [hello-test] Message from client: {"method":"notifications/initialized",...}
2026-05-19T13:49:40.056Z [hello-test] Message from client: {"method":"tools/list",...,"id":1}
2026-05-19T13:49:40.058Z [hello-test] Message from server: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"hello_test",...}]}}
# user asks Claude to invoke hello_test at ~13:50 UTC
# (4 min timeout, no further entries)

---

[LocalMcpServerManager] Connected to <server> (N tools)

---

2026-05-19 10:11:01 [error] Session local_e94d8111-... query error:
  Claude Code process exited with code 1073807364
    at BPi.getProcessExitError (...\app-1.7196.3\resources\app.asar\.vite\build\index.js:406:8122)
    at ChildProcess.i (...\index.js:406:11166)
RAW_BUFFERClick to expand / collapse

Summary

On Claude Desktop for Windows, any stdio MCP server's tools/call is silently dropped before reaching the subprocess. The handshake (initialize + tools/list + resources/list) completes successfully — tools appear in the LLM's available-tools list (Claude in chat confirms it can see them) — but when the LLM emits a tool_use for any of those tools, the request never arrives at the stdio subprocess. The client surfaces a ~4-minute timeout error claiming "the local MCP server was unresponsive", while the subprocess log shows zero tools/call entries during that window.

This is not the same as #60224 (slow initialize causing the tool list to be dropped from ToolSearch). Here the tool list registers correctly and is visible to the LLM; the break is one stage downstream — between the LLM emitting tool_use and Claude Desktop forwarding it as JSON-RPC tools/call to the subprocess.

A trivial 60-line, zero-dependency stdio server reproduces the bug, ruling out SDK / slow-init / dependency-related causes.

Environment

  • App: Claude Desktop (Windows)
  • Versions reproduced on: 1.7196.3, 1.7196.0, 1.6608.0 (all via winget downgrade)
  • OS: Windows 11 Enterprise (Build 26200)
  • MCP server type: stdio
  • CCD version logged: 2.1.142
  • Repros on: fresh install with no userdata, and restored userdata backup
  • Network: works fine for tools/list traffic — no general transport issue

Minimal repro (60 lines, no dependencies)

Add to claude_desktop_config.json:

{
  "mcpServers": {
    "hello-test": {
      "command": "C:\\Program Files\\nodejs\\node.exe",
      "args": ["C:\\path\\to\\server.mjs"]
    }
  }
}

server.mjs — single trivial tool, no I/O, ~2 ms handshake:

import { createInterface } from 'node:readline';
const rl = createInterface({ input: process.stdin });
const send = (m) => process.stdout.write(JSON.stringify(m) + '\n');
const TOOL = { name: 'hello_test', description: 'Trivial diagnostic tool.', inputSchema: { type: 'object', properties: {} } };
rl.on('line', (line) => {
  if (!line.trim()) return;
  const msg = JSON.parse(line);
  const handlers = {
    initialize: () => ({ protocolVersion: msg.params.protocolVersion, capabilities: { tools: {} }, serverInfo: { name: 'hello-test', version: '0.1.0' } }),
    'tools/list': () => ({ tools: [TOOL] }),
    'tools/call': () => ({ content: [{ type: 'text', text: 'It works.' }] }),
  };
  const fn = handlers[msg.method];
  if (fn && msg.id != null) send({ jsonrpc: '2.0', id: msg.id, result: fn() });
});
process.stderr.write('hello-test ready over stdio\n');

Restart Claude Desktop. Ask Claude to invoke hello_test.

Expected: tool returns "It works." within seconds. Actual: ~4-minute client-side timeout; subprocess log shows the handshake completed but no tools/call was ever delivered.

Server-log evidence

2026-05-19T13:49:39.229Z [hello-test] Server started and connected successfully
2026-05-19T13:49:39.760Z [hello-test] Message from client: {"method":"initialize",...,"id":0}
2026-05-19T13:49:39.763Z [hello-test] Message from server: {"jsonrpc":"2.0","id":0,"result":...}     # 3 ms
2026-05-19T13:49:40.052Z [hello-test] Message from client: {"method":"notifications/initialized",...}
2026-05-19T13:49:40.056Z [hello-test] Message from client: {"method":"tools/list",...,"id":1}
2026-05-19T13:49:40.058Z [hello-test] Message from server: {"jsonrpc":"2.0","id":1,"result":{"tools":[{"name":"hello_test",...}]}}
# user asks Claude to invoke hello_test at ~13:50 UTC
# (4 min timeout, no further entries)

grep "tools/call" mcp-server-hello-test.log0 matches.

What I ruled out

HypothesisTestedResult
Specific to one MCP serverReproduces on 3 distinct servers (incl. trivial hello-test)❌ Not server-specific
Slow initialize (sibling of #60224)Handshake completes in 2-5 ms on hello-test❌ Not init-timeout
Claude Desktop binary version regressionReproduces on 1.7196.3, 1.7196.0, 1.6608.0 via winget downgrade❌ Same bug on older binaries
Corrupted local userdataRepro on fresh install with empty %APPDATA%\Roaming\Claude\❌ Persists across wipe
Corrupted MCP cache (mcp-needs-auth-cache.json)Deleted manually❌ No change
Orphan Code-tab session filesAll deleted; tested with empty claude-code-sessions/❌ No change
Config path / command typoBoth tools/list and tools/call would fail if so; only tools/call fails❌ Path/command are fine
Corporate proxy interferenceAll other MCP traffic and Anthropic API calls succeed❌ Network layer fine

Correlated host-side anomalies

%APPDATA%\Roaming\Claude\logs\main.log shows the structured-log line:

[LocalMcpServerManager] Connected to <server> (N tools)

…fires correctly on early sessions today (07:51, 08:58, 09:03, 09:32, 09:56) and stops firing entirely after a triggering event at 10:11:01, despite the per-server logs continuing to show successful handshakes on every subsequent launch.

The triggering event was a Code-daemon subprocess crash:

2026-05-19 10:11:01 [error] Session local_e94d8111-... query error:
  Claude Code process exited with code 1073807364
    at BPi.getProcessExitError (...\app-1.7196.3\resources\app.asar\.vite\build\index.js:406:8122)
    at ChildProcess.i (...\index.js:406:11166)

(Exit 1073807364 = 0x40010004 = DBG_TERMINATE_PROCESS.) The crash occurred while trying to spawn the bundled Code daemon for an archived Code session whose cwd no longer existed on disk. Triggered by a Sentry.caught flood (50+ entries in two seconds), after which LocalMcpServerManager never reports Connected (N tools) again — but per-server handshakes continue completing successfully. Tool dispatch is broken from that moment on, persistently, across launches / versions / a full uninstall + reinstall + userdata wipe.

This suggests the degraded state is server-side / account-tied: a fresh Claude Desktop install with empty local data reproduces the same tools/call black-hole behaviour. Local-state interventions (cache wipe, session-file delete, version downgrade, full reinstall) do not recover dispatch.

Hypothesis

The host's tool_use → tools/call dispatcher uses a registry whose populate-once code path is gated on LocalMcpServerManager.Connected events. After the 1073807364 cascade the manager logs Closing all (0 servers) on every quit cleanup and never re-runs whatever code emits Connected (N tools) — so for the rest of the install's lifetime, the registry has the tools listed (tools/list works → LLM sees them) but no entry in the dispatch table (LLM-emitted tool_use for those names has no route, silently discarded, eventually timing out client-side).

If that mapping is mirrored to account-side state, it explains why fresh installs inherit the bug.

Suggested fixes (any of these would resolve it)

  1. Make tool_use → tools/call dispatch fall back to looking up the MCP server by name from the tools/list registry when the per-tool dispatch table has no entry. Currently the silent drop suggests it doesn't.
  2. Emit [LocalMcpServerManager] Connected (N tools) independent of the Code-daemon process state — the protocol-level handshake on the subprocess is what should drive this event, not whatever component crashed at 1073807364.
  3. Add a recovery path that rebuilds the dispatch table from the current handshake state on every fresh launch, so a transient crash doesn't permanently brick the host for the account.
  4. Surface the missing-dispatch-route condition as a visible error in the chat (rather than a 4-min timeout with no diagnostic), so users can tell the difference between "server hung" and "host didn't route the call".

Related

  • #60224 — sibling bug at one stage upstream (tool list dropped from ToolSearch when initialize is slow). Same area (area:mcp), same platform (platform:windows), different precise failure mode.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING