[BUG] stdio MCP tools silently fail after Claude Code restart — internal session ID mismatch (v8.sessionId overwritten by GP())
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report
- [x] I am using the latest version of Claude Code
Claude Code Version
2.1.79
Platform
Linux (WSL2)
What's Wrong?
After restarting Claude Code (any restart, not just /resume), all stdio MCP tool calls silently fail with [Tool result missing due to internal error]. The MCP server connects and processes calls successfully (confirmed in logs), but results are never returned to the model.
This is caused by an internal session ID mismatch between the MCP connection and the tool dispatch.
Root Cause (Confirmed via Source Analysis)
The bug is in the session ID lifecycle in cli.js:
Step 1: Claude Code starts
v8.sessionId = Tu8() → e.g. "1fddedc7" (new random UUID)
Step 2: MCP servers connect and register handlers under "1fddedc7"
Step 3: Conversation is loaded (resume or auto-continue)
GP(oldConversationId) is called → v8.sessionId = "503380ba" (old conversation ID)
Step 4: Tool call dispatched
Uses v8.sessionId = "503380ba" ← MISMATCH with MCP handler under "1fddedc7"
Result is routed to "503380ba" handler → not found → silently dropped
Key functions involved (from minified cli.js):
// v8 global state — sessionId initialized at module load
v8 = { sessionId: Tu8(), ... }
// L8() returns current sessionId
function L8() { return v8.sessionId }
// GP() overwrites sessionId — called on conversation load
function GP(A, q=null) { v8.sessionId = A, v8.sessionProjectDir = q }
// Called in nGz() when resuming:
if (q.continue) {
let Y = await k86(void 0, void 0); // load most recent conversation
if (Y.sessionId) {
GP(mJ(Y.sessionId), ...) // ← THIS overwrites v8.sessionId with old conversation ID
}
}
MCP Log Evidence
Two consecutive log entries from the same log file, same Claude Code run:
// MCP startup (step 2)
{"debug":"Successfully connected to stdio server in 2008ms",
"sessionId":"1fddedc7-51d7-4b21-80c4-26b9e2e0c8ea"}
// Tool call dispatch (step 4) — DIFFERENT session ID
{"debug":"Calling MCP tool: resolve-library-id",
"sessionId":"503380ba-a413-4e29-9cd2-59918159c4ec"}
{"debug":"Tool 'resolve-library-id' completed successfully in 1s",
"sessionId":"503380ba-a413-4e29-9cd2-59918159c4ec"}
The tool completes on the MCP side but Claude never receives the result.
Why the First Session Ever Works
When Claude Code is run for the first time in a project (no existing conversation):
v8.sessionId = Tu8()→ e.g."abc123"- MCP connects under
"abc123" - New conversation created →
GP("abc123")→ same ID, no mismatch - Tool calls work ✅
On every subsequent restart, a new startup UUID is generated but GP restores the old conversation ID → mismatch → broken.
Steps to Reproduce
- Configure any stdio MCP server in
.mcp.json - Start Claude Code in a project that has existing conversation history
- Try to call any MCP tool →
[Tool result missing due to internal error] - Check
~/.cache/claude-cli-nodejs/<project>/mcp-logs-<server>/— you will see startup sessionId ≠ tool call sessionId
What Should Happen
After GP(conversationId) is called, the MCP handlers should be re-registered under the new v8.sessionId. Or alternatively, MCP connections should be initialized after the session ID is finalized (after GP() is called), not before.
Proposed Fix
Option A — Re-initialize MCP after GP() in the resume path:
if (Y.sessionId) {
GP(mJ(Y.sessionId), ...);
await reinitializeMcpConnections(); // re-register under new v8.sessionId
}
Option B — Finalize session ID before starting MCP:
Move GP() call to before MCP server startup, so MCP always connects under the correct final session ID.
Option C — Don't use v8.sessionId for MCP handler routing; use a stable per-process identifier instead.
Impact
- Affects all stdio MCP tools on every restart when conversation history exists
- The project's
.mcp.jsonconfiguration and server health are irrelevant — the bug is internal - Workaround: delete/rename the most recent
.jsonlconversation file before launching Claude Code (forces fresh session where startup UUID = conversation UUID = match)
Additional Information
Verified on Claude Code v2.1.79, Linux/WSL2, with both HTTP→stdio (context7) and custom stdio (code-index) MCP servers. The issue is transport-agnostic for stdio — reproduced with npx-based and uv-based servers.
Related (different root cause, same symptom class):
- #27142 (HTTP MCP stale session)
- #9608 (HTTP MCP 404 re-init)
- #14009 (experimental MCP CLI stale session — similar race condition)
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗