Skip to content

docs(learnings): document MCP double-spawn upstream bug (#526)#527

Open
RayCharlizard wants to merge 3 commits intoaaddrick:mainfrom
RayCharlizard:fix/526-mcp-double-spawn-learnings
Open

docs(learnings): document MCP double-spawn upstream bug (#526)#527
RayCharlizard wants to merge 3 commits intoaaddrick:mainfrom
RayCharlizard:fix/526-mcp-double-spawn-learnings

Conversation

@RayCharlizard
Copy link
Copy Markdown
Collaborator

Summary

Adds docs/learnings/mcp-double-spawn.md capturing #526's root-cause analysis so future contributors hitting the symptom find a quick pointer instead of re-investigating from zero.

The bug: stdio MCP servers in claude_desktop_config.json get spawned twice when both the chat panel and the Code/Agent (Cowork) panel are active. Reporter (@communitytranslations) traced it to two parallel session managers in upstream Electron main (LocalSessions and LocalAgentModeSessions) each holding an independent Claude Agent SDK query whose stdio transport (Du.spawn) bypasses the global MCP registry (hZ map / oUt accessor) that would dedupe them.

I independently verified our packaging is not implicated:

  • All 7 patches in scripts/patches/*.sh — zero references to MCP, mcpServer, LocalSessions, LocalAgentModeSessions, transportToClient, MessageChannelMain, n2t, hZ, oUt
  • scripts/launcher-common.sh and scripts/packaging/*.sh — no MCP or config-load logic
  • scripts/doctor.sh:420 only reads the config to JSON-lint it; not in the runtime spawn path

The entry documents:

  • Symptoms with example ps -ef output
  • Upstream root cause with the relevant minified symbols (flagged as drift-prone)
  • Status: upstream Anthropic bug, not patchable here — explicitly waves off future contributors from regex-patching minified symbols
  • Workaround for affected MCP authors (lockfile + idempotent writes, per reporter's cb7bfbb)
  • Routing guidance: primary venue is in-app feedback or support@anthropic.com; anthropics/claude-code defensible as secondary since the SDK transport is shared surface area; the embedded CLI is not the cause

Also adds the entry to the docs/learnings/ index in CLAUDE.md.

Test plan

  • docs/learnings/mcp-double-spawn.md renders cleanly
  • CLAUDE.md learnings index includes the new entry in the right position
  • No code paths touched; no patch surface modified

Generated with Claude Code
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
70% AI / 30% Human
Claude: surveyed patches to verify packaging exoneration, drafted the learnings entry, wrote the comment plan
Human: routed the issue, caught a missed contrarian pass and triggered the policy update, approved scope and tone

Copy link
Copy Markdown
Owner

@aaddrick aaddrick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the exoneration claims hold. Re-grepped case-sensitive across scripts/patches/*.sh, scripts/launcher-common.sh, scripts/packaging/*.sh, and extended to nix/, worker/, scripts/setup/, build.sh, frame-fix-wrapper.js, cowork-vm-service.js, and staging/. Zero relevant hits. scripts/doctor.sh:420 is JSON-lint only, and CI is green. Analysis is solid.

One real bug on line 46: the IPC namespace table has claude.web_$_LocalAgentModeSessions_* but should be claude.web_$_LocalAgentModeSessions_$_*. The _$_ separator is structural — build-reference/app-extracted/.vite/build/index.js:64565 has the actual channel names (claude.web_$_LocalAgentModeSessions_$_start, _$_sendMessage). The LocalSessions row above it is correct, so the separator probably got dropped during column alignment. This matters because it's a literal grep target for the next debugger.

The Routing Upstream Reports section lists anthropics/claude-code as defensible secondary because the SDK transport is shared surface area, but the SDK lives in anthropics/claude-agent-sdk-typescript (separate public repo, issues enabled). Pointing SDK-transport reports at claude-code while the doc itself says the CLI isn't on the spawn path is the exact contradiction your "don't frame as CLI double-spawning" warning was trying to prevent — CLI maintainers can close as off-topic and bounce the reporter. Either swap in claude-agent-sdk-typescript or drop the secondary venue.

Nit while you're on line 46: the original issue body had a 4-column table with a Logs prefix column ([CCD] / [LAM]). Those prefixes are what users grep ~/.config/Claude/logs/ for to confirm they're hitting this bug specifically — worth adding back. Optional and probably skip on its own, but if you re-roll: the workaround section punts to cb7bfbb for the lockfile reference, and a one-liner about atomic reclaim (rename-over, not unlink-then-open) would head off the naive port. @RayCharlizard once the separator and routing get fixed I'm good to merge.


Written by Claude Opus 4.7 via Claude Code

RayCharlizard added a commit to RayCharlizard/claude-desktop-debian that referenced this pull request Apr 27, 2026
- Fix `LocalAgentModeSessions` IPC namespace: add missing `_$_`
  separator (was `claude.web_$_LocalAgentModeSessions_*`, should be
  `claude.web_$_LocalAgentModeSessions_$_*`). Verified against the
  channel names in the actual minified source.
- Add back the `Logs prefix` column (`[CCD]` / `[LAM]`) the original
  issue body had — these are the literal grep targets in
  `~/.config/Claude/logs/` for confirming the bug hit.
- Re-route the secondary upstream venue from `anthropics/claude-code`
  to `anthropics/claude-agent-sdk-typescript`. The SDK transport
  (`spawnLocalProcess` / `Du.spawn`) lives in the SDK's own public
  repo (issues enabled); pointing at `claude-code` while saying the
  CLI isn't on the spawn path is the exact contradiction the warning
  paragraph below it tries to prevent.
- Workaround note: reclaim a stale lock via `rename()` over the path,
  not `unlink()` then re-open. Heads off the obvious-but-racy port
  for anyone copying the pattern.

Co-Authored-By: Claude <claude@anthropic.com>
@RayCharlizard
Copy link
Copy Markdown
Collaborator Author

Thanks for the catch on the separator — that one would have wasted real time for the next person grepping. Pushed 5fe1d69 with all four:

  • Separator fix on line 46: table now reads claude.web_\$_LocalAgentModeSessions_\$_*. Verified my edit lines up with the channel names you cited at index.js:64565 (_\$_start, _\$_sendMessage).
  • Logs prefix column restored: [CCD] / [LAM] back in a 4-column table, plus a one-liner pointing readers at ~/.config/Claude/logs/ so they know what to grep when confirming the bug.
  • Routing swapped: secondary venue is now anthropics/claude-agent-sdk-typescript (verified public + issues enabled). You're right that pointing SDK-transport reports at claude-code while the doc itself says the CLI isn't on the spawn path was the exact rake the warning paragraph was trying to head off.
  • Atomic reclaim added: workaround section now calls out rename() over unlink()-then-re-open near the cb7bfbb reference. Cheap to add, heads off the naive port.

Ready when you are.


Written by Claude Opus 4.7 via Claude Code

RayCharlizard and others added 3 commits April 27, 2026 16:35
Captures the reporter's root-cause analysis for issue aaddrick#526: stdio MCP
servers in claude_desktop_config.json get spawned twice when both the
chat panel and the Code/Agent (Cowork) panel are active. The
duplication happens entirely in upstream Anthropic Claude Desktop main
(LocalSessions and LocalAgentModeSessions each hold an independent
Claude Agent SDK query whose stdio transport bypasses the global hZ
MCP registry).

Includes verification that this packaging is not implicated, the
lockfile + idempotent-write workaround pattern for affected MCP
authors, and routing guidance for upstream reports.

Co-Authored-By: Claude <claude@anthropic.com>
Drop redundant "Anthropic" qualifier in Status section and reword
CLAUDE.md index bullet to noun-phrase form matching siblings.

Co-Authored-By: Claude <claude@anthropic.com>
- Fix `LocalAgentModeSessions` IPC namespace: add missing `_$_`
  separator (was `claude.web_$_LocalAgentModeSessions_*`, should be
  `claude.web_$_LocalAgentModeSessions_$_*`). Verified against the
  channel names in the actual minified source.
- Add back the `Logs prefix` column (`[CCD]` / `[LAM]`) the original
  issue body had — these are the literal grep targets in
  `~/.config/Claude/logs/` for confirming the bug hit.
- Re-route the secondary upstream venue from `anthropics/claude-code`
  to `anthropics/claude-agent-sdk-typescript`. The SDK transport
  (`spawnLocalProcess` / `Du.spawn`) lives in the SDK's own public
  repo (issues enabled); pointing at `claude-code` while saying the
  CLI isn't on the spawn path is the exact contradiction the warning
  paragraph below it tries to prevent.
- Workaround note: reclaim a stale lock via `rename()` over the path,
  not `unlink()` then re-open. Heads off the obvious-but-racy port
  for anyone copying the pattern.

Co-Authored-By: Claude <claude@anthropic.com>
@RayCharlizard RayCharlizard force-pushed the fix/526-mcp-double-spawn-learnings branch from 5fe1d69 to 564a3d1 Compare April 27, 2026 21:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants