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.jsonare 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.jsonalready supports this..claude.jsonshould 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
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗