Feature request: ${VAR} env var expansion in user-scope .claude.json MCP configs

Resolved 💬 3 comments Opened Apr 4, 2026 by Buttonskill Closed May 15, 2026

Problem

MCP server configs in user-scope .claude.json require hardcoded credential values in the env block. This means plaintext tokens (API keys, JWTs, brain keys) are stored in a JSON file on disk.

Project-scope .mcp.json already supports ${VAR} expansion (confirmed via resolved #2065). User-scope .claude.json does not.

Current Behavior

// ~/.claude.json -- secrets stored as plaintext literals
"mcpServers": {
  "my-server": {
    "env": {
      "API_TOKEN": "sk-abc123-literal-secret-in-file"
    }
  }
}

Desired Behavior

// ~/.claude.json -- references env vars, expanded at server startup
"mcpServers": {
  "my-server": {
    "env": {
      "API_TOKEN": "${MY_API_TOKEN}"
    }
  }
}

The server process would receive the expanded value from the OS environment at spawn time.

Why This Matters

  • Security: Plaintext credentials in .claude.json are readable by any process running as the user. Env var references let users store secrets in OS-native credential stores (Credential Manager, keychain, encrypted env files).
  • Rotation: Changing a credential currently requires claude mcp remove + claude mcp add. With ${VAR}, just update the env var source.
  • Bootstrapping: Automated setup scripts (e.g., dotfile managers) can set env vars once and register servers without embedding secrets.
  • Consistency: .mcp.json already supports this. .claude.json should too.

Environment

  • Claude Code 2.1.92 on Windows 11 (Git Bash/MSYS2)
  • MCP SDK StdioClientTransport constructs child env from whitelist + explicit env block
  • Confirmed ${VAR} is passed as literal string in current .claude.json parsing

View original on GitHub ↗

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