CC spawns project .mcp.json stdio server twice per launch (t+0 instance outside client-manager accounting) — single-connection backends lose their tools client

Status Open
Reported on v2.1.227
Maintainer reply None cached
Activity 2 comments · opened Aug 11, 2026

Summary

As of 2026-08-11, on one of our Linux boxes, every fresh interactive claude launch spawns the project .mcp.json stdio MCP server TWICE from the same claude process — one instance immediately at launch (t+0s, outside the MCP client manager's accounting: it never appears in ~/.cache/claude-cli-nodejs/<cwd>/mcp-logs-<server>/), and one ~2s later via the normal client manager (which does log). Our stdio server's backend enforces one connection per client identity, so the second (legitimate) connection is rejected and the session comes up with zero tools (Failed to fetch tools: Not connected). The early instance's connection then drops ~15s after boot.

The same binaries booted cleanly (single server instance) on the same box one day earlier, with no binary, config, plugin, or hook change in between (all verified by mtime/content) — which makes us suspect a server-side feature-gate rollout changed startup behavior.

Hard evidence (process lineage, captured at 250ms resolution during boot)

claude 3226325 (18:52:13)
├─ npm exec tsx …/mcp/index.ts  3226389  (18:52:13 — same second as claude itself)
│   └─ sh → node tsx → node 3226678     ← connects to backend 18:52:15.5 (NOT in mcp-logs)
└─ npm exec tsx …/mcp/index.ts  3226699  (18:52:15 — the client-manager spawn)
    └─ sh → node tsx → node 3226778     ← connects 18:52:16.5 (IS in mcp-logs; loses to the first)

The early instance's intermediate npm/sh wrappers exit within ~5s (orphaning its node process to systemd --user); its connection drops at ~t+15s.

A/B matrix (all reproduce, 7/7 boots)

| CC version | --dangerously-load-development-channels flag | cwd | result |
|---|---|---|---|
| 2.1.227 | yes | fresh scratch dir, only .mcp.json | dup spawn |
| 2.1.226 | yes | same | dup spawn |
| 2.1.227 | no | same | dup spawn |
| 2.1.226 | no | same, pre-trusted | dup spawn |

  • Same .mcp.json content booted clean at 2026-08-10 21:24 (single instance).
  • Ruled out on-disk: MCP registration exists in exactly ONE scope (project .mcp.json; user/managed/local scopes verified empty of this server); plugins unchanged (mtimes); hooks unchanged; ~/.codex/config.toml unchanged; npx cache unchanged since before the last clean boot (tsx 4.23.12).
  • LocalMcpServerManager (from #53134): zero hits in mcp-logs and zero in the 2.1.227 binary's strings.
  • Not the dual-scope bug (#66474): single registration.

Client-manager log for the losing (legitimate) connection

"Starting connection with timeout of 30000ms"
"Server stderr: MCP ready..."          <- server up
"Successfully connected (transport: stdio) in 2349ms"
"STDIO connection closed after 0s (cleanly)"   <- backend rejected as duplicate
"tools/list failed (Connection closed); retrying in 250ms"
"Failed to fetch tools: Not connected"

Environment

  • claude 2.1.226 and 2.1.227 (native installer, Linux x86_64, Ubuntu 22.04 / kernel 5.15)
  • .mcp.json: single stdio server, command: npx, args: ["tsx", "<path>/index.ts"]
  • Enterprise (Claude Enterprise) org
  • Interactive TTY sessions inside tmux; also reproduces outside our normal launch wrapper

Questions

  1. What is the t+0 spawn? (It precedes the client manager by ~2s and is invisible to mcp-logs.) A prewarmed subagent, preflight probe, or a newly-gated second MCP consumer?
  2. Is there a supported way to disable it, or to make internal consumers share the client manager's connection?
  3. If this is a staged rollout, can the cohort be identified so affected single-connection stdio backends can prepare?

Happy to provide more forensics (we have subsecond process captures and both sides' logs for 8 boots).

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗