MCP server connection failure in -p mode produces no diagnostic — orchestrators cannot detect or recover
Summary
When an MCP server fails to connect during a -p (headless) session, Claude Code silently proceeds without those tools. There is zero signal in stderr or the stream-json output. The system/init event simply omits the failed server's tools from the tool list. Orchestrators have no way to detect the failure except by counting tools and comparing against an expected baseline.
This causes confusing downstream failures: the model sees the tool in conversation history (from a prior request), tries ToolSearch (returns empty), tries direct invocation (gets "No such tool available"), and the user sees a broken session with no explanation.
Environment
- Claude Code version: 2.1.92
- OS: Linux (Docker, Node 20 bookworm-slim)
- MCP server: HTTP-based (SnapLogic Triggered Pipeline), configured in
.mcp.json - Mode:
-pwith--output-format stream-json --verbose --dangerously-skip-permissions - Session type:
--resume(second request in a session)
Steps to Reproduce
- Configure an HTTP MCP server in
.mcp.json(e.g., one that calls an external REST endpoint) - Start a session with
-pthat uses a tool from that server — it works - Resume the session with
--resume— the MCP server fails to connect (transient network issue, slow response, etc.) - The resumed session proceeds with zero MCP tools and no error output
We've observed this multiple times in a production orchestration system. The MCP server is healthy (other sessions connect fine seconds later), but the specific resume attempt silently loses all MCP tools.
Evidence from Session
First request (fresh session, --session-id):
system/init → tools: 70 (22 built-in + 48 MCP)
mcp_servers: [{"name":"snaplogic-core","status":"connected"}]
total_deferred_tools: 61
ToolSearch("select:mcp__snaplogic-core__NotifyBySlackJeanClaude") → matches: [tool found]
Resumed request (--resume, same session, ~60 seconds later):
system/init → tools: 22 (built-in only, 0 MCP)
mcp_servers: [] (server not listed at all)
total_deferred_tools: 13
ToolSearch("NotifyBySlackJeanClaude") → matches: [], total_deferred_tools: 13
Direct call mcp__snaplogic-core__NotifyBySlackJeanClaude → "Error: No such tool available"
stderr: Empty (no MCP connection errors reported)
Docker logs: No MCP-related errors
Expected Behavior
system/initshould include failed MCP servers with"status": "failed"and a"reason"field (timeout, connection refused, etc.) — not silently omit them- A
system/mcp_errorevent should be emitted in the stream-json output when an MCP server fails to connect - stderr should log a warning when an MCP server configured in
.mcp.jsonfails to connect
Requested Feature
A --require-mcp <name1,name2> flag that makes -p mode exit with a non-zero code if the listed MCP servers don't connect successfully. This would let orchestrators fail fast and retry instead of proceeding with a broken tool set.
Related Issues
- #43298 — "Remote MCP servers not visible in -p mode" (closed as completed in v2.1.89, but we're on 2.1.92 and still see it)
- #41792 — Headless MCP startup docs omit
MCP_CONNECTION_NONBLOCKING - #33559 — MCP tool errors not surfaced in autonomous mode
- #39061 — Need canonical way for MCP servers to provide startup error messages
- anthropics/claude-code-action#813 — MCP fails without logs in GitHub Actions
Workaround
We parse the system/init event from stream-json output and compare the tool count against the expected baseline. If tools dropped significantly, we know an MCP server failed. But this is fragile and requires maintaining expected tool counts per MCP server.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗