Plugin MCP reconnect fails: ${CLAUDE_PLUGIN_ROOT} not substituted after /model or session reconnect
Description
When Claude Code reconnects a plugin's MCP server (e.g. after /model command or session restart), the ${CLAUDE_PLUGIN_ROOT} placeholder in the plugin's .mcp.json args is not substituted with the actual plugin root path. This causes the spawned node process to immediately exit with MODULE_NOT_FOUND, and Claude Code retries for 30 seconds before surfacing a timeout error.
Steps to reproduce
- Install a plugin that registers an MCP server via
.mcp.jsonusing${CLAUDE_PLUGIN_ROOT}in the args (standard plugin pattern) - Start a Claude Code session — plugin MCP connects successfully on first load
- Run
/modelto switch models — triggers MCP reconnect - Observe error:
Failed to reconnect to plugin:<name>:<name>: MCP server "plugin:<name>:<name>" connection timed out after 30000ms
Expected behavior
${CLAUDE_PLUGIN_ROOT} substituted consistently on both initial connect and all subsequent reconnects.
Actual behavior
Initial connect: substitution works, MCP starts correctly (~26ms).
Reconnect: substitution skipped, node receives literal ${CLAUDE_PLUGIN_ROOT}/scripts/mcp-runtime.mjs as the file path → MODULE_NOT_FOUND → immediate exit → 30s retry loop → timeout.
Diagnostics
Running the unsubstituted path directly:
$ node '${CLAUDE_PLUGIN_ROOT}/scripts/mcp-runtime.mjs'
Error: Cannot find module '/path/to/project/${CLAUDE_PLUGIN_ROOT}/scripts/mcp-runtime.mjs'
code: 'MODULE_NOT_FOUND'
The substitution that works on first load does NOT happen on reconnect triggered by /model.
Environment
- Claude Code version: 2.1.161
- OS: Linux (CachyOS / Arch)
- Node.js: v26.1.0
- Plugin: local dev
Workaround
Hardcode the absolute path in the plugin's .mcp.json instead of using ${CLAUDE_PLUGIN_ROOT}. This is fragile (breaks on reinstall/path change) but confirms the substitution is the root cause.
Plugin .mcp.json (standard pattern that triggers the bug)
{
"mcpServers": {
"my-plugin": {
"command": "node",
"args": ["${CLAUDE_PLUGIN_ROOT}/scripts/mcp-runtime.mjs"]
}
}
}This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗