Plugin MCP reconnect fails: ${CLAUDE_PLUGIN_ROOT} not substituted after /model or session reconnect

Resolved 💬 1 comment Opened Jun 5, 2026 by randomvariable Closed Jul 12, 2026

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

  1. Install a plugin that registers an MCP server via .mcp.json using ${CLAUDE_PLUGIN_ROOT} in the args (standard plugin pattern)
  2. Start a Claude Code session — plugin MCP connects successfully on first load
  3. Run /model to switch models — triggers MCP reconnect
  4. 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"]
    }
  }
}

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗