MCP server env ${VAR} left unexpanded when server is respawned mid-session (reconnect)

Status Closed — not planned
Reported on v2.1.215
Maintainer reply None cached
Activity 3 comments · opened Jul 20, 2026 · closed Aug 22, 2026

Summary

When an MCP server is (re)spawned mid-session (e.g. via /mcp reconnect, or an auto-reconnect after the server drops), the ${VAR} references in that server's env block are not expanded. The literal string (e.g. ${JIRA_URL}) is passed to the server process. On the initial spawn at Claude Code startup, the same config expands correctly.

Environment

  • Claude Code 2.1.215 (Desktop-embedded), macOS 15 (Darwin 25.5.0)
  • Env vars defined in ~/.claude/settings.json env; referenced as ${VAR} in ~/.claude.json mcpServers.<name>.env

Expected

${VAR} in an MCP server's env expands to its value on every spawn, including reconnects.

Actual

  • Initial spawn (at CC startup): ${VAR} → real value ✅
  • Reconnect / mid-session respawn: ${VAR} → literal ${VAR}

Evidence

Six live mcp-atlassian processes across sessions, identical config, correlated purely with spawn timing:

| PID | spawned vs parent CC start | JIRA_URL in process env |
|---|---|---|
| 20777 | +2s (initial) | https://jira.example.com ✅ |
| 31849 | +1s (initial) | real ✅ |
| 27046 | +55min (reconnect) | ${JIRA_URL} ❌ |
| 33057 | +63s (reconnect) | ${JIRA_URL} ❌ |

Both parent CC processes had JIRA_URL unset in their own env, confirming the value only ever arrives via ${VAR} expansion — which the reconnect path skips. Same binary (2.1.215), same CLAUDE_CONFIG_DIR (default) for working and broken cases. After a full relaunch, the initial spawn expanded correctly again.

Reproduction

  1. Define FOO=bar in ~/.claude/settings.json env.
  2. In an MCP server config, set env: { "FOO": "${FOO}" }.
  3. Start Claude Code → server gets FOO=bar.
  4. /mcp reconnect <server> → server now gets FOO=${FOO} (literal).

Impact

Any MCP server relying on ${VAR} env indirection breaks after a reconnect — auth/URL vars resolve to literal placeholders, causing failures like Invalid URL '${JIRA_URL}/rest/...': No scheme supplied.

Workaround

Fully relaunch Claude Code (fresh initial spawn) rather than /mcp reconnect.

Note

The mid-session respawns were inferred to be reconnects from spawn timing (large gap between parent CC start and MCP start); the timing correlation itself is directly observed from the process table.

View original on GitHub ↗

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