VS Code extension: SessionStart $CLAUDE_ENV_FILE not applied to MCP server ${VAR}/header auth (works in CLI)

Resolved 💬 2 comments Opened May 30, 2026 by KAGDACI Closed Jun 3, 2026

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

  1. A SessionStart hook appends export MY_SECRET='xyz' to $CLAUDE_ENV_FILE.
  2. Ensure MY_SECRET is not an OS environment variable.
  3. Configure a remote HTTP MCP with "headers": { "X-Api-Key": "${MY_SECRET}" } (or supply the same value via a server-level headersHelper).
  4. CLI / terminal: the header is populated → the MCP authenticates (HTTP 200).
  5. VS Code extension: ${MY_SECRET} resolves empty → the server returns 401 → the SDK initiates OAuth → Incompatible auth server: does not support dynamic client registration.
  6. In the extension, a tool call running Test-Path env:MY_SECRET (PowerShell) or printenv MY_SECRET (bash) returns empty, while OS-inherited vars are present.
  7. Developer: Reload Window does not help — the root Code.exe process 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 envFile in .mcp.json for loading secrets (would address the secret-injection need directly).
  • #63207 — PreToolUse hooks should have a way of updating the environment (adjacent env-propagation gap).

View original on GitHub ↗

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