[BUG] ${VAR} substitution not applied to .mcp.json headers values (HTTP transport)

Resolved 💬 2 comments Opened Apr 21, 2026 by Alish3r Closed Apr 22, 2026

Environment

  • Claude Code version: 2.1.112
  • OS: Windows 10 Pro (native, not WSL)
  • Terminal: bash (Git Bash)

Bug Description

In .mcp.json for an HTTP-transport MCP server, ${ENV_VAR} placeholders in the headers map are not substituted with the environment variable value. The literal string ${ENV_VAR} is sent to the server. The same substitution works correctly in the env block for stdio-transport servers.

This is the same root cause as the previously reported (and bot-auto-closed) #6204. Filing a fresh report per that thread's guidance ("please file a new issue and reference this one"), adding native-Windows repro and additional diagnostic evidence.

Steps to Reproduce

  1. Set env var in the shell that launches Claude Code:

``bash
export STITCH_API_KEY="AQ.Ab8..."
`
(Also confirmed set via
"env" block in .claude/settings.local.json` — same result.)

  1. Configure .mcp.json:

``json
{
"mcpServers": {
"stitch": {
"type": "http",
"url": "https://stitch.googleapis.com/mcp",
"headers": {
"X-Goog-Api-Key": "${STITCH_API_KEY}"
}
}
}
}
``

  1. Start Claude Code. claude mcp list shows ✓ Connected because initialize is unauthenticated on this server.
  1. Invoke any tool → server returns 401 because Claude Code sent no key. Claude Code then attempts OAuth DCR, which Google does not support, so the tool becomes unusable.

Expected Behavior

${STITCH_API_KEY} in headers should be substituted with the env var value, exactly as it is in env blocks.

Actual Behavior

Placeholder sent verbatim. Verified with a mitmproxy between Claude Code and the server — header value is the literal string \${STITCH_API_KEY}.

Workaround

Hardcode the secret directly in headers, then gitignore .mcp.json. Functional but defeats the whole point of env-var substitution.

"headers": { "X-Goog-Api-Key": "AQ.Ab8...actual-value..." }

Impact

Any remote MCP server requiring API-key-style header auth (Google Cloud services, internal enterprise MCP gateways, etc.) cannot use secrets hygiene with Claude Code's .mcp.json — forced to either paste secrets into source control or build a local command wrapper.

Related

  • #6204 (closed by stale-bot; still reported as occurring by multiple users at close time)
  • #16497 (meta: auto-close bot closing live bugs)

View original on GitHub ↗

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