mirror of
https://github.com/aaddrick/claude-desktop-debian.git
synced 2026-05-17 08:36:35 +03:00
docs: archive upstream report draft for #546 (filed as anthropics/claude-code#55353) (#552)
* docs(upstream-reports): draft anthropics/claude-code report for #546 Adds a ready-to-file draft of the upstream MCP double-spawn report, matched to the anthropics/claude-code bug_report.yml schema and written in aaddrick's documented voice. Includes a filing checklist (GitHub issue + in-app /bug + bidirectional comment back on #546) and a note about the template mismatch since the form is built for the Claude Code CLI rather than Claude Desktop. Refs #546 Co-Authored-By: Claude <claude@anthropic.com> * docs(upstream-reports): link claude-desktop-debian repo in draft body Co-Authored-By: Claude <claude@anthropic.com> * docs(upstream-reports): add download-rate context next to repo link Adds an approximate "~2,300 package downloads/day across the last 3 releases" parenthetical so the upstream report leads with a sense of how many users the bug affects. Computed from GitHub release asset download counts: 13,823 installable binary downloads (deb + rpm + AppImage, both arches) across 1.5354.0, 1.5220.0, and 1.4758.0 over a ~6-day window. Co-Authored-By: Claude <claude@anthropic.com> * docs(upstream-reports): voice pass on draft body and title Refines the draft for the upstream `anthropics/claude-code` issue through the aaddrick-voice profile. Changes are surgical: - Title: em-dash separator → colon (matches voice's documented preference for colons; removes em-dash signal site-wide). - "What's Wrong?": opens with personal-experience framing ("I was reading", "What I found"), splits compound sentences, swaps announcement-colons for periods. - "What Should Happen?": same period-for-colon swap on the fix paragraph. No content shifts. Symbol table, code blocks, log signals, links, and form-field labels untouched. Co-Authored-By: Claude <claude@anthropic.com> * docs(upstream-reports): drop bogus /bug filing step User confirmed `/bug` and `/feedback` are inert in both Claude Desktop and Claude Code. Earlier web research suggesting they route to engineering was wrong. Replaced step 4 of the filing checklist with a note about what's actually in the Help menu (Get Support goes to the support chat, wrong queue) and what the Troubleshooting submenu IS useful for (attaching Installation ID / logs to a GitHub issue). Co-Authored-By: Claude <claude@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Claude <claude@anthropic.com>
This commit is contained in:
164
docs/upstream-reports/546-mcp-double-spawn.md
Normal file
164
docs/upstream-reports/546-mcp-double-spawn.md
Normal file
@@ -0,0 +1,164 @@
|
||||
# Upstream report draft: MCP double-spawn (issue #546)
|
||||
|
||||
This is the draft for the upstream bug report covering [#546](https://github.com/aaddrick/claude-desktop-debian/issues/546). Filing target is `anthropics/claude-code` GitHub Issues, with an in-app `/bug` from Claude Desktop as a complement so the report ties to build telemetry.
|
||||
|
||||
## Template mismatch note
|
||||
|
||||
The `anthropics/claude-code` bug template is built for the Claude Code CLI, not Claude Desktop. Required fields like "Claude Code Version" and "Terminal/Shell" don't apply cleanly. Other Claude Desktop bug reports in the same repo work around this by putting `N/A — Claude Desktop <version>` in the version field and selecting `Other` for terminal (see #43705, #36319, #14807).
|
||||
|
||||
## Title
|
||||
|
||||
```
|
||||
[BUG] Claude Desktop 1.5354.0: stdio MCP servers double-spawn from independent CCD/LAM coordinator registries
|
||||
```
|
||||
|
||||
## Form fields
|
||||
|
||||
### 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
|
||||
|
||||
### What's Wrong?
|
||||
|
||||
I maintain [claude-desktop-debian](https://github.com/aaddrick/claude-desktop-debian) (~2,300 package downloads/day across the last 3 releases), which repackages the Windows Electron build for Linux. I was reading the MCP spawn path in 1.5354.0 and found that stdio MCP servers configured in `claude_desktop_config.json` get spawned twice when both the chat panel and Code/Agent panel are active.
|
||||
|
||||
The user-visible symptom is two `node` processes per MCP, both children of the Electron main PID. Killing one disconnects one panel and the other keeps working. They're independent client/server pairs with no failover between them.
|
||||
|
||||
The original symptom report came from @communitytranslations against an earlier build (tracked in our repo as #526). I went back and read the bundle to confirm the cause. What I found was different from what we'd previously documented.
|
||||
|
||||
CCD wraps the spawn path in a per-key promise queue keyed by server name. It shuts down any prior entry in its global registry Map before respawning. That's correct dedup within CCD. But LAM (`LocalMcpServerManager`) has its own `this.connections` Map and its own `getOrCreateConnection` path. It never consults CCD's registry.
|
||||
|
||||
CCD and LAM each maintain independent spawn lifecycle management. They each spawn their own copy of the same MCP server. The double-spawn is structural in the current architecture. Each coordinator legitimately holds its own connection.
|
||||
|
||||
There's also a third coordinator class, `SshMcpServerManager`, that follows the same per-coordinator-registry pattern. It uses an SSH transport, so it doesn't contribute to local-node double-spawn directly. Its existence suggests per-coordinator isolated state is a deliberate pattern, not a one-off.
|
||||
|
||||
Secondary bug worth flagging while you're in this code. The `child_process.spawn` wrapper does proper signal escalation (end stdin, wait 2s, SIGTERM, wait 2s, SIGKILL). The `utilityProcess.fork` wrapper doesn't. It sends `process.kill()` (default SIGTERM), waits 5s, then calls `kill()` again with the same default signal. No SIGKILL escalation. A built-in-node MCP server that ignores SIGTERM could leak as an orphaned utility process.
|
||||
|
||||
### What Should Happen?
|
||||
|
||||
One process per stdio MCP server entry in `claude_desktop_config.json`, regardless of how many panels are open. Resource-side that means no more 2x memory and 2x stdin/stdout traffic per server. User-side that means `ps` shows one entry per declared server.
|
||||
|
||||
The fix is architectural. CCD and LAM share a registry, or the local-spawn factory dedups at the transport layer, or LAM proxies through CCD when running in-process. Any of those would collapse the duplication.
|
||||
|
||||
### Error Messages/Logs
|
||||
|
||||
The user-facing log prefixes are stable across releases. Grep `~/.config/Claude/logs/` for:
|
||||
|
||||
```
|
||||
[CCD]
|
||||
[LAM]
|
||||
[LocalMcpServerManager]
|
||||
[SshMcpServerManager]
|
||||
```
|
||||
|
||||
For the spawn lifecycle specifically, look for:
|
||||
|
||||
```
|
||||
"Launching MCP Server: <name>" (CCD spawn entry)
|
||||
"Shutting down MCP Server: <name>" (CCD shutdown entry)
|
||||
"local-mcp-server-cleanup" (LAM cleanup path)
|
||||
```
|
||||
|
||||
Two of these per declared MCP server is the diagnostic signal.
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
1. Linux host running Claude Desktop at or near 1.5354.0
|
||||
2. Declare at least one stdio MCP server in `~/.config/Claude/claude_desktop_config.json`
|
||||
3. Open Claude Desktop, start a session, open the Code/Agent panel and let it initialize fully (the original report waited about 5 minutes)
|
||||
4. `ps -ef | grep <server-binary-name>`
|
||||
|
||||
Expected: 1 process per MCP. Actual: 2 processes per MCP, both children of the same Electron main PID.
|
||||
|
||||
### Claude Model
|
||||
|
||||
Not sure / Multiple models
|
||||
|
||||
### Is this a regression?
|
||||
|
||||
I don't know
|
||||
|
||||
### Last Working Version
|
||||
|
||||
(leave blank)
|
||||
|
||||
### Claude Code Version
|
||||
|
||||
```
|
||||
N/A — this is a Claude Desktop issue. Bundle version: 1.5354.0
|
||||
```
|
||||
|
||||
### Platform
|
||||
|
||||
Anthropic API
|
||||
|
||||
### Operating System
|
||||
|
||||
Ubuntu/Debian Linux
|
||||
|
||||
### Terminal/Shell
|
||||
|
||||
Other
|
||||
|
||||
### Additional Information
|
||||
|
||||
Bundle reference table for 1.5354.0. Symbols rename across releases, so each row has a stable string anchor for re-finding them.
|
||||
|
||||
| Role | Symbol in 1.5354.0 | Stable anchor |
|
||||
|---|---|---|
|
||||
| CCD spawn function | `BPt` | `"Launching MCP Server:"` |
|
||||
| CCD shutdown function | `CPt` | `"Shutting down MCP Server:"` |
|
||||
| CCD per-key promise queue | `dPt` | called by CCD spawn fn: `await dPt(e, async () => {...})` |
|
||||
| CCD server registry Map | `xX` | `.get()` immediately preceding the CCD shutdown log line |
|
||||
| Shared transport factory | `oPt` | `"built-in-node"` literal in factory body |
|
||||
| LAM manager class | `p0A` | `"[LocalMcpServerManager]"` or `"local-mcp-server-cleanup"` |
|
||||
| SSH manager class | `Rde` | `"[SshMcpServerManager]"` or `"ssh-mcp-server-cleanup"` |
|
||||
| `utilityProcess.fork` wrapper | `mFr` | constructed in shared factory's `built-in-node` branch |
|
||||
| `child_process.spawn` wrapper | `tFr` | constructed in shared factory's default branch |
|
||||
|
||||
Extraction commands (verified against 1.5354.0):
|
||||
|
||||
```bash
|
||||
cd build-reference/app-extracted/.vite/build
|
||||
|
||||
# CCD spawn function name
|
||||
grep -Pzo 'async function \K\w+(?=\(\w*\)\s*\{(?s).{0,800}?Launching MCP Server)' index.js | tr '\0' '\n'
|
||||
|
||||
# Shared transport factory (anchored on the unique 'built-in-node' string)
|
||||
grep -Pzo 'async function \K\w+(?=\([^)]*\)\s*\{(?s).{0,400}?built-in-node)' index.js | tr '\0' '\n'
|
||||
|
||||
# All coordinator classes following the per-coordinator-registry pattern
|
||||
grep -Pzo 'class \K\w+(?=\s*\{(?s).{0,300}?this\.connections\s*=\s*new Map)' index.js | tr '\0' '\n'
|
||||
|
||||
# LAM manager class specifically
|
||||
grep -Pzo 'class \K\w+(?=\s*\{(?s).{0,500}?local-mcp-server-cleanup)' index.js | tr '\0' '\n'
|
||||
```
|
||||
|
||||
Two questions where a one-line answer from the team would help us route this downstream:
|
||||
|
||||
1. Is per-coordinator isolated state intentional, or is it legacy drift from when each coordinator instantiated its transport inline?
|
||||
2. Is the recent extraction of the shared transport factory (`oPt`) the start of a dedup refactor, or incidental cleanup?
|
||||
|
||||
If (1) is "intentional," we'll point users at the lockfile workaround as the supported path. If (2) is "in progress," this report saves you the duplicate analysis work.
|
||||
|
||||
Full provenance: [aaddrick/claude-desktop-debian#546](https://github.com/aaddrick/claude-desktop-debian/issues/546). Related learnings doc updates: [#527](https://github.com/aaddrick/claude-desktop-debian/pull/527) and [#547](https://github.com/aaddrick/claude-desktop-debian/pull/547).
|
||||
|
||||
## Filing checklist
|
||||
|
||||
When you're ready to file:
|
||||
|
||||
1. Open https://github.com/anthropics/claude-code/issues/new?template=bug_report.yml
|
||||
2. Paste each section above into the matching form field
|
||||
3. Submit
|
||||
4. Drop the GitHub issue URL as a comment on [#546](https://github.com/aaddrick/claude-desktop-debian/issues/546) so the trail is bidirectional
|
||||
|
||||
Note: there is no in-app engineering bug-report path in Claude Desktop. `/bug` and `/feedback` are inert. The Help menu has "Get Support" (routes to the support chat, wrong queue for engineering) and "Troubleshooting" (self-diagnostic — useful for attaching `Copy Installation ID` or `Show Logs in File Manager` output to a GitHub issue, but not a reporting step on its own).
|
||||
|
||||
## Voice and authorship
|
||||
|
||||
Drafted using the [aaddrick-voice](https://github.com/aaddrick/written-voice-replication/blob/78f178dcf832943bcf1d5a65bf7627c3a20053a6/.claude/agents/aaddrick-voice.md) style profile against the form schema in `anthropics/claude-code/.github/ISSUE_TEMPLATE/bug_report.yml`.
|
||||
|
||||
---
|
||||
Written by Claude Opus 4.7 via [Claude Code](https://claude.ai/code)
|
||||
Reference in New Issue
Block a user