MCP stdio reconnect spawns literal unexpanded ${HOME} in command → ENOENT, server lost for the session (still on 2.1.215; prior reports stale-closed)

Status Open
Reported on v2.1.215
Maintainer reply None cached
Activity 0 comments · opened Jul 21, 2026

Summary

${VAR} expansion in a stdio MCP server's command is applied on the initial session connect, but not on the mid-session auto-reconnect path. The reconnect spawns the literal unexpanded string, fails with ENOENT in ~2ms, and the server's tools are reported disconnected for the rest of the session.

Prior reports of this exact bug were closed without a fix: #65747 (canonical, closed as stale by github-actions on 2026-07-12 with "open a new issue if this is still relevant"), #67483 and #70146 (closed as duplicates of it). It still reproduces on the current release, so filing fresh per the stale-bot's instruction.

Environment

  • Claude Code 2.1.215, macOS (darwin 24.6.0)
  • Server registered in user-scope ~/.claude.json:
{
  "mcpServers": {
    "example": {
      "type": "stdio",
      "command": "${HOME}/go/bin/example-mcp",
      "env": { "EXAMPLE_TOKEN": "..." }
    }
  }
}

Observed (from ~/Library/Caches/claude-cli-nodejs/<project>/mcp-logs-example/*.jsonl, binary name genericized)

03:40:09.533Z Starting connection with timeout of 30000ms
03:40:09.580Z Successfully connected (transport: stdio) in 48ms        <-- initial connect: ${HOME} expanded, server runs fine
...
03:43:10.206Z Starting connection with timeout of 30000ms              <-- mid-session reconnect attempt
03:43:10.208Z Connection failed after 2ms: ENOENT: no such file or directory, posix_spawn '${HOME}/go/bin/example-mcp'

Two stdio servers registered with ${HOME} commands failed at the same instant on the same reconnect sweep; servers registered with bare commands on PATH (npx, uvx) or absolute paths were unaffected. After the failed reconnect the session reports the server's tools as no longer available; there is no retry with expansion applied.

claude mcp list health checks the same entry successfully (it expands ${HOME}), which makes this confusing to diagnose: the server shows ✔ Connected from the CLI while the live session has lost it.

Expected

The reconnect path should apply the same environment-variable expansion to command (and args/env) as the initial spawn.

Workaround

Register the server with an absolute path instead of ${HOME}.

View original on GitHub ↗