MCP stdio command with ${HOME} works on first launch but ENOENTs on auto-reconnect (literal ${HOME} reaches posix_spawn)
Summary
A local (stdio) MCP server whose command in .mcp.json contains ${HOME} connects fine on the initial launch, but after any transient disconnect the auto-reconnect fails with ENOENT because the literal string ${HOME} is passed to posix_spawn (not expanded). The server then stays disconnected until a full Claude Code restart.
In other words: ${HOME} in command is expanded on the initial spawn but not on reconnect.
Environment
- Claude Code 2.1.139
- macOS 15.7.7 (arm64)
- Local/stdio MCP server,
commandconfigured as${HOME}/go/bin/my-mcp
Repro
.mcp.jsonwith:
``json``
{ "mcpServers": { "demo": { "command": "${HOME}/go/bin/my-mcp" } } }
- Start Claude Code → the server connects:
Successfully connected (transport: stdio). - Let the server drop (idle close / transient network blip). Claude Code attempts an auto-reconnect.
- The reconnect fails:
Connection failed: ENOENT: no such file or directory, posix_spawn '${HOME}/go/bin/my-mcp'. - The server stays disconnected for the rest of the session until Claude Code is fully restarted (the restart re-runs the initial-spawn path, which expands
${HOME}).
Evidence
From ~/Library/Caches/claude-cli-nodejs/<project>/mcp-logs-<server>/*.jsonl, same session:
- initial spawn:
"debug":"Successfully connected (transport: stdio) in 34ms" - later reconnect:
"error":"Connection failed: ENOENT: no such file or directory, posix_spawn '${HOME}/go/bin/my-mcp'"
The reconnect log shows the literal ${HOME} reaching posix_spawn.
Expected
${HOME} (and other env vars) in a server command should be expanded consistently on reconnect, the same as on the initial spawn.
Actual
Initial spawn expands ${HOME} (appears to go through a shell); the reconnect path uses posix_spawn with the raw, unexpanded string → ENOENT → the server is permanently down until restart. This makes long-lived sessions silently lose MCP servers after any transient drop.
Workaround
Use an absolute path in command (no env var), e.g. /Users/you/go/bin/my-mcp. With no ${...} to expand, both the initial and reconnect spawns succeed.
Related
Looks like the same spawn-path non-expansion as #37580 (~ tilde in MCP stdio args → ENOENT). This report is the ${HOME}-in-command, expanded-on-init-but-not-on-reconnect manifestation, which also explains the "works at first, then silently stays disconnected" symptom.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗