Transient MCP server disconnect evicts its tools from the front `tools` array → full prompt-cache prefix invalidation (re-added on reconnect = second miss)
Summary
When an MCP server transiently disconnects mid-session, Claude Code removes that server's tools from the per-turn tools array sent to /v1/messages. Because tools sits at the very front of the cached prefix (before system and messages, with no cache_control of its own), dropping any entry changes the prefix hash and invalidates the entire downstream cache. On reconnect the tools are re-added — a second invalidation. A server that flaps repeatedly therefore forces repeated full-prefix cache_creation at the ephemeral rate.
This is the same class as #49038 (there the trigger is non-deterministic Agent-tool reordering; here it is MCP tool eviction/re-insertion).
Evidence (Proxyman wire capture, no proxy-side modification)
Reading the actual /v1/messages request bodies before and after killing an MCP server's process:
- Tool-search OFF (
ENABLE_TOOL_SEARCH=auto:100, all MCP tools serialized in the front array): the disconnected server's tools are removed from the fronttoolsarray, and the next request showscache_readcollapse withcache_creationre-writing the full static prefix. - Tool-search ON (front array = builtins +
ToolSearch+ surfaced MCP tools): a server's surfaced tools likewise drop out of the front array on disconnect.
In both modes the prefix hash changes, so everything after tools (the remaining tool defs, system, and the messages prefix up to the cache breakpoint) is re-cached. On reconnect the tools return and the prefix changes again.
Impact
Cheap at shallow depth (a short-prefix lineage stays warm for the ~5-minute TTL), but expensive when a server first flaps deep in a 200k+ token context — each transition re-creates the whole prefix at 2x base input price.
Suggested direction
Distinguish a transient disconnect from a deliberate removal (/mcp disable / disabledMcpjsonServers): keep a transiently-unreachable server's tool definitions resident in the tools array until it is deliberately removed, so the prefix stays byte-identical across flaps. If the model should be informed they are momentarily unreachable, a single cache-safe <system-reminder> appended to the latest user message naming the server (not every tool — cf. #55852) conveys it without disturbing the cached prefix. Any re-insertion must preserve the existing emission order (builtin tools sorted by name, then MCP tools sorted by name.localeCompare) so the array is byte-identical to the connected state — otherwise the re-insertion itself is a cache miss.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗