/mcp reconnect after config-hash-stale spawns literal unexpanded ${CLAUDE_PLUGIN_ROOT} → -32000

Resolved 💬 3 comments Opened Jun 11, 2026 by tsuromer Closed Jun 15, 2026

Summary

After Claude Code marks an MCP plugin client stale (excludeStalePluginClients: marking stale (config hash changed)), a subsequent /mcp reconnect spawns the server command with a literal, unexpanded ${CLAUDE_PLUGIN_ROOT} in the path, so the reconnect always fails with -32000.

Observed (client MCP log)

excludeStalePluginClients: marking stale (config hash changed)
Sending SIGINT to MCP server process
SIGTERM failed, sending SIGKILL to MCP server process
...
Starting connection with timeout of 30000ms
Server stderr: python3: can't open file '/home/user/.../${CLAUDE_PLUGIN_ROOT}/server.py': [Errno 2] No such file or directory
Connection failed after 54ms: MCP error -32000: Connection closed

The identical command works at session launch (template expanded correctly) and from a shell. Only the post-stale /mcp reconnect path loses the expansion. Seen on 2.1.170, Linux, server loaded via --dangerously-load-development-channels.

Impact

/mcp is the natural recovery for a dropped MCP server; with this bug the only working recovery is a full exit + --resume.

Expected

Reconnect re-resolves the plugin command template exactly as initial launch does.

View original on GitHub ↗

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