MCP stdio command with ${HOME} works on first launch but ENOENTs on auto-reconnect (literal ${HOME} reaches posix_spawn)

Resolved 💬 2 comments Opened Jun 22, 2026 by kabirgup Closed Jun 24, 2026

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, command configured as ${HOME}/go/bin/my-mcp

Repro

  1. .mcp.json with:

``json
{ "mcpServers": { "demo": { "command": "${HOME}/go/bin/my-mcp" } } }
``

  1. Start Claude Code → the server connects: Successfully connected (transport: stdio).
  2. Let the server drop (idle close / transient network blip). Claude Code attempts an auto-reconnect.
  3. The reconnect fails: Connection failed: ENOENT: no such file or directory, posix_spawn '${HOME}/go/bin/my-mcp'.
  4. 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.

View original on GitHub ↗

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