Repository navigation
fix(server): Claude threads no longer inherit the launching Claude session or race MCP connects - #25976
fix(server): Claude threads no longer inherit the launching Claude session or race MCP connects#25976juliusmarminge wants to merge 3 commits into
Conversation
…Code session env These tests reproduce #25959. The env createClaudeAdapterV2 passes to the SDK query still carries a parent Claude Code session's variables (CLAUDECODE, CLAUDE_CODE_ENTRYPOINT, CLAUDE_CODE_SESSION_ID, CLAUDE_CODE_MESSAGING_SOCKET, CLAUDE_EFFORT), and never sets MCP_CONNECTION_NONBLOCKING=false, so MCP tools can miss a turn's first request. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hat launched T3 Every Claude spawn path (turns, capability and version probes, text generation) strips the host Claude Code session markers before the instance environment is merged, so a value set on the instance still wins. Turns default MCP_CONNECTION_NONBLOCKING to false so new threads send a stable tool list on their first request and share one prompt cache. Fixes #25959 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…only overridden Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ApprovabilityVerdict: Needs Human Approval Macroscope's review found this PR requires human approval — This focused server fix sanitizes inherited Claude session variables and changes the default MCP connection behavior for Claude turns, affecting existing production request paths. Because it changes a product default, the change warrants human review. You can add or adjust custom eligibility rules. Learn more. |
Thread transfer impact✅ Thread transfer remains within every enforced ceiling.
Baseline: Scenario and decoded snapshot size10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Filter and merge Claude environment apps/server/src/provider/Drivers/ClaudeHome.ts |
Adds a helper that removes selected Claude session variables from a copy of the host environment, then merges provider-instance values. |
Use filtered environment in Claude execution apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.ts, apps/server/src/provider/Drivers/ClaudeDriver.ts, apps/server/src/orchestration-v2/Adapters/ClaudeAdapterV2.test.ts |
The adapter and driver use the Claude-specific environment helper. The adapter sets MCP_CONNECTION_NONBLOCKING to "false" before merging, so an instance value can override it. Tests check filtering, retained host values, instance overrides, and the default. |
Priority:
Estimated code review effort: 3 (Moderate) | ~20 minutes
Change: Bug fix · Severity of issue fixed: Medium
Suggested labels: bugfix
Suggested reviewers: maria-rcks, saphid
Merge Risk: 
Minimal · up to 134bf
-
The environment isolation change is ready to merge after normal checks; no material issue remains established.
Pre-merge checks: 
4
-
Full details: Linked Issues check
-
Explanation
The PR addresses the active direct issue
#25959.mergeClaudeProcessEnvironmentremoves inherited Claude Code session markers and then merges the instance environment, so instance values remain effective. The adapter and driver use this environment for turns, probes, and text generation. Turns setMCP_CONNECTION_NONBLOCKINGtofalseby default while preserving an instance or host override. Added tests cover session-variable removal, retained user environment, instance entrypoint override, and MCP opt-out. The reported validation passes.
Full details: Out of Scope Changes check
-
Explanation
The diff stays within issue
#25959. It changes Claude environment construction, MCP connection timing, and focused automated tests for those behaviors. No unrelated product behavior or unrelated files are changed.
-
Finishing Touches
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Comment @coderabbitai help to get the list of available commands.
Problem
Claude threads fail to share a prompt cache across new threads, for two reasons.
claudeit spawns inherits that session's environment:CLAUDECODE,CLAUDE_CODE_ENTRYPOINT=claude-desktop, the session id, the messaging socket and token,CLAUDE_EFFORT,CLAUDE_PID, and so on. The spawned process runs as a child of a session it does not belong to.Reproduced on main e9236274a3 with the dev server launched under a fake host session's variables, a Claude instance whose
binaryPathlogs its env, and a user-scope stdio MCP server that connects after 0.5 to 4 s. Every probe and turn receivedCLAUDE_CODE_ENTRYPOINT=claude-desktopand the host session's variables. Of four new threads, one went out with the slow server's tools and wrote 52,691 tokens of fresh cache. In the others the tools only arrived on the second request, and that request rewrote the prefix.Change
mergeClaudeProcessEnvironmentinClaudeHome.tsremoves a fixed list of Claude Code host-session markers from the host environment, then merges the instance's ownenvironmentas before. A value set on the instance still wins.HostProcess.Environmentlike the adapter does, instead ofprocess.env.MCP_CONNECTION_NONBLOCKINGtofalseunless the host or instance env sets it. The first request then waits for MCP servers to connect, so every new thread sends the same tool list.CLAUDE_CONFIG_DIR,ANTHROPIC_*, proxy and telemetry variables still passes through.Scope and approval
Fixes #25959
Verification
ClaudeAdapterV2.test.ts, "ClaudeAdapterV2 turn environment":does not leak a parent Claude Code session into the spawned claudefails on main withCLAUDECODE: "1",CLAUDE_CODE_ENTRYPOINT: "claude-desktop", the session id, socket and effort all present. It passes with the fix, and it fails again ifCLAUDE_CODE_ENTRYPOINTis removed from the scrub list.connects MCP servers before the first request unless the instance opts outfails on main with[undefined, "true"]. It passes with the fix.ClaudeAdapterV2.test.ts,ClaudeHome.test.tsandClaudeTextGeneration.test.ts: 258 passed.vp run check:changedpasses.CLAUDECODE=1,CLAUDE_CODE_ENTRYPOINT=claude-desktop, hostCLAUDE_CODE_SESSION_ID,CLAUDE_CODE_MESSAGING_SOCKET/TOKEN,CLAUDE_EFFORT,CLAUDE_PID,CLAUDE_CODE_CHILD_SESSIONCLAUDE_CODE_ENTRYPOINT=sdk-ts(set by the SDK),MCP_CONNECTION_NONBLOCKING=false, no host-session variables in any of the 7 spawnsTranscripts: before-main-e9236274a3.txt, after-fix-f072531c75.txt. Scripts: claude-wrap (env-logging
binaryPath), slow-mcp.mjs (stdio MCP server with a jitteredinitialize), shapes.py (reads request shapes and cache usage from the transcripts).open -alaunch from a Claude Desktop session, and claude.ai connectors. The run used a user-scope stdio server through the hub API on Linux; the code path does not depend on the platform.Model and harness: Claude Opus 5.5 in Claude Code, run as a T3 Code issue lead, with Claude Opus 5.5 and GPT-6.1 Sol step agents.
🤖 Generated with Claude Code