[BUG] MCP tool errors not surfaced to model in autonomous mode — silent data loss
Problem
When an MCP tool returns isError: true in its response, Claude Code in autonomous mode (claude -p) does not treat this as a blocking failure. The model sees the error text but continues as if the operation succeeded. In autonomous sessions without a human to catch this, it leads to silent data loss.
Reproduction
- Connect an MCP server with a tool that can fail (e.g., a memory/state store)
- Run
claude -p "Store this fact: 'test data'" --dangerously-skip-permissions - If the MCP tool's backend is down, it returns
{ isError: true, content: [{ type: "text", text: "Error: store failed" }] } - The model sees the error text but may proceed to report success to the user/orchestrator
- Subsequent reads return nothing — the data was never persisted
Real-world impact
We operate a production memory system via MCP. Our MCP handler was wrapping a backend write in try/catch and returning a success-looking response even on failure:
// Before fix — MCP tool swallowed the error
try {
await backend.store(data);
return { content: [{ text: `Recorded: "${data}"` }] };
} catch (err) {
console.error(err); // logged but not surfaced
return { content: [{ text: `Recorded: "${data}"` }] }; // still "succeeded"
}
This is partly our bug (we fixed it to return isError: true), but the deeper issue is: even when the MCP tool correctly returns isError: true, autonomous Claude Code sessions don't halt or retry. The model acknowledges the error in its reasoning but may still tell the orchestrator "done" — because there's no mechanism to force a retry or mark the task as failed based on MCP tool errors.
Expected behavior
In autonomous mode, MCP tool errors should be treated with the same severity as a failed Bash command:
- The model should explicitly acknowledge the failure in its output
- If the failed tool was critical to the task, the model should retry or report failure — not silently continue
- The
--output-format jsontermination metadata should include MCP tool errors in anerrorsarray - Orchestrators should be able to detect "task completed but had MCP errors" vs "task completed cleanly"
Suggested approach
- Track MCP
isErrorresponses during the session - Include them in JSON output metadata:
"mcp_errors": [{ "tool": "memory_store", "error": "..." }] - Optionally: add a
--strict-mcp-errorsflag that treats any MCPisErroras a blocking failure (similar toset -ein bash)
Environment
- Claude Code: latest (v2.1.74)
- MCP transport: Streamable HTTP
- Mode:
claude -pwith--dangerously-skip-permissions
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗