Transient MCP server disconnect evicts its tools from the front `tools` array → full prompt-cache prefix invalidation (re-added on reconnect = second miss)

Resolved 💬 2 comments Opened Jun 6, 2026 by seidnerj Closed Jul 13, 2026

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 front tools array, and the next request shows cache_read collapse with cache_creation re-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.

View original on GitHub ↗

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