VS Code extension: SessionStart $CLAUDE_ENV_FILE not applied to MCP server ${VAR}/header auth (works in CLI)
Summary
In the Claude Code VS Code extension, environment variables written by a SessionStart hook to $CLAUDE_ENV_FILE are not applied to (a) MCP server ${VAR} expansion (env / headers / headersHelper / url) or (b) Bash/PowerShell tool subprocesses. The CLI applies them correctly.
Practical effect: a remote HTTP MCP that authenticates via a header ${VAR} resolved from a SessionStart-loaded secret works in the CLI/terminal but silently fails in the VS Code extension — the header resolves empty → the server returns 401 → the SDK falls back to OAuth and errors with Incompatible auth server: does not support dynamic client registration.
Environment
- Claude Code 2.1.142 (VS Code extension)
- OS: Windows 11
- Surfaces: remote HTTP/SSE MCP
${VAR}expansion (headers/headersHelper/url); Bash + PowerShell tool env
Reproduction
- A
SessionStarthook appendsexport MY_SECRET='xyz'to$CLAUDE_ENV_FILE. - Ensure
MY_SECRETis not an OS environment variable. - Configure a remote HTTP MCP with
"headers": { "X-Api-Key": "${MY_SECRET}" }(or supply the same value via a server-levelheadersHelper). - CLI / terminal: the header is populated → the MCP authenticates (HTTP 200).
- VS Code extension:
${MY_SECRET}resolves empty → the server returns 401 → the SDK initiates OAuth →Incompatible auth server: does not support dynamic client registration. - In the extension, a tool call running
Test-Path env:MY_SECRET(PowerShell) orprintenv MY_SECRET(bash) returns empty, while OS-inherited vars are present. Developer: Reload Windowdoes not help — the rootCode.exeprocess environment persists across the reload.
Expected
The VS Code extension applies SessionStart $CLAUDE_ENV_FILE to the session environment (MCP servers + tool subprocesses), matching CLI behavior.
Actual
$CLAUDE_ENV_FILE is ignored for MCP/tool env in the extension; only the OS process environment present at editor-launch is used.
Impact
Breaks single-source-of-secrets setups (one .env, loaded per-session by a SessionStart hook) for the extension, and pushes users toward persistent OS environment variables — widening the secret blast radius, since every spawned user process / marketplace extension inherits them.
Workaround
For remote HTTP MCPs, a server-level headersHelper that reads the secret from .env at connection time works in both CLI and extension (it runs at connect time, sidestepping the env-propagation gap). No clean equivalent exists for subprocess MCP env blocks.
Related issues
- #60697 — CLAUDE_ENV_FILE propagation is bash-only (PowerShell tool + child plugins). Same root mechanism; this report extends it to MCP-server
${VAR}/ header auth and the VS Code extension specifically, with the concrete remote-MCP-auth failure mode. - #28942 — Support
envFilein.mcp.jsonfor loading secrets (would address the secret-injection need directly). - #63207 — PreToolUse hooks should have a way of updating the environment (adjacent env-propagation gap).
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗