Plugin .orphaned_at marker permanently disables MCP server after transient transport disconnect

Resolved 💬 3 comments Opened May 9, 2026 by blicksten Closed May 13, 2026

Bug

After a transient MCP transport disconnect (e.g., the local MCP server daemon respawning), Claude Code writes ~/.claude/plugins/cache/<plugin>/<version>/.orphaned_at and never re-evaluates the plugin even when the daemon recovers. Result: every MCP tool that came from that plugin becomes permanently unavailable (deferred-unavailable namespace) until the user runs /clear or restarts the VS Code window.

This is reproducible in our environment any time the local MCP gateway process respawns — even when the new instance is fully healthy and serving requests.

Reproduction

  1. Have an MCP server running via ~/.claude/plugins/cache/<plugin>/<version>/.mcp.json.
  2. Restart the MCP server process (simulating a respawn — e.g., on a content-equivalent regen, on a crash, or on an admin /shutdown).
  3. Observe a .orphaned_at marker appears in the plugin cache directory.
  4. Even after the server is healthy and accepting connections, Claude Code does not re-attach. ToolSearch (and the namespace itself) reports deferred-unavailable.

Investigation findings (2026-05-09)

We've shipped a server-side mitigation that signals reconnect to Claude Code, but the client-side path appears to ignore it:

  • The Claude Code extension (extension.js, ~2.1 MB minified, no source maps) contains a string reference to reconnectMcpServer but the actual HTTP transport retry logic is not accessible to us.
  • The plugin (mcp-gateway-local) is purely declarative (.mcp.json + plugin.json only — no transport state of its own).
  • Our daemon enqueues reconnect patch actions correctly on every plugin regen (including startup), and exposes them via GET /api/v1/claude-code/pending-actions for Claude Code to poll. The patch flow is wired and verified by 7/7 unit tests in our repo.
  • We also fall back to bumping the .mcp.json mtime (os.Chtimes) on respawn to fire the plugin manager's fs-watcher path, since content-equivalent regens preserve mtime by default.

Despite both signals being correctly sent server-side, the .orphaned_at marker remains and tools stay unavailable until either:

  1. The user runs /clear (in-session MCP transport teardown + re-establish), or
  2. An external hook deletes .orphaned_at and touches .mcp.json mtime (we ship mcp-rehydrate.sh for this), or
  3. The VS Code window is restarted.

Feature request

Any one of these would unblock us; we'd be happy with the cheapest path:

  • (a) Documentation only — clarify the .orphaned_at marker semantics so operators know exactly what triggers it, what clears it, and what state Claude Code's MCP client is in when it's present. Right now the marker is invisible from the UI and undocumented.
  • (b) Automatic HTTP transport retry in the MCP client when the daemon enqueues a reconnect action via /api/v1/claude-code/pending-actions (or when the plugin's .mcp.json mtime changes). This is the canonical fix.
  • (c) Debug flag (e.g., CLAUDE_MCP_DEBUG_RECONNECT=1 / --mcp-debug) that logs reconnect attempts, transport disconnects, and .orphaned_at write/read events to stderr or a known file. Would let us narrow down whether the issue is in transport-disconnect detection, reconnect-action consumption, or fs-watcher dispatch.

Environment

  • Claude Code version: 2.1.137
  • VS Code version: 1.119
  • OS: Windows 11 Enterprise

Happy to provide additional logs, traces, or a minimal reproducer on request. Our local mitigation hook is at hooks/mcp-rehydrate.sh (deletes the marker + touches mtime) and works reliably as a workaround, but the client-side transport reconnect path is the canonical fix-surface that only Claude Code can address.

View original on GitHub ↗

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