Checks
Operating system
macOS 26.3.0 (Apple M3 Pro)
Expected behaviour
Environment variable substitution in MCP server headers should work with $VAR_NAME or ${VAR_NAME} syntax, consistent with the env block in the same config and with other MCP clients (Cursor, Goose).
Actual behaviour
The headers field requires ${env:VAR_NAME} syntax. Using $VAR_NAME (same syntax that works in the env block) silently passes the literal string instead of the resolved value. The remote MCP server rejects it with "API key is not configured or invalid" -- no warning from the CLI.
Steps to reproduce
- Create an agent config with a remote MCP server using
$VAR syntax in headers:
{
"mcpServers": {
"context7": {
"type": "http",
"url": "https://mcp.context7.com/mcp",
"env": {
"CONTEXT7_API_KEY": "$CONTEXT7_API_KEY"
},
"headers": {
"CONTEXT7_API_KEY": "$CONTEXT7_API_KEY"
},
"disabled": false
}
}
}
- Run
kiro-cli chat --agent my-agent --trust-all-tools
- Ask the model to call a Context7 tool
- Observe: "API key is not configured or invalid"
- Change headers to
"${env:CONTEXT7_API_KEY}" -- works
The env block uses $VAR and works. The headers block requires ${env:VAR} but nothing documents this. The ${env:VAR} syntax is only discoverable by reading the source (substitute_env_vars in crates/chat-cli/src/mcp_client/client.rs).
Other MCP clients for comparison:
- Cursor:
${VAR_NAME}
- Goose:
$VAR_NAME
- Kiro/Q CLI:
${env:VAR_NAME} (undocumented)
Environment
version: 1.26.1
hash: 9d6226020f759dab8f2fad1b1d7179a50f1479ef
date: 2026-02-16T21:58:46.784323Z
variant: full
os: macOS 26.3.0
chip: Apple M3 Pro
shell: /bin/zsh 5.9
terminal: Kitty
install-method: brew
Checks
q doctorin the affected terminal sessionq restartand replicated the issue againOperating system
macOS 26.3.0 (Apple M3 Pro)
Expected behaviour
Environment variable substitution in MCP server
headersshould work with$VAR_NAMEor${VAR_NAME}syntax, consistent with theenvblock in the same config and with other MCP clients (Cursor, Goose).Actual behaviour
The
headersfield requires${env:VAR_NAME}syntax. Using$VAR_NAME(same syntax that works in theenvblock) silently passes the literal string instead of the resolved value. The remote MCP server rejects it with "API key is not configured or invalid" -- no warning from the CLI.Steps to reproduce
$VARsyntax in headers:{ "mcpServers": { "context7": { "type": "http", "url": "https://mcp.context7.com/mcp", "env": { "CONTEXT7_API_KEY": "$CONTEXT7_API_KEY" }, "headers": { "CONTEXT7_API_KEY": "$CONTEXT7_API_KEY" }, "disabled": false } } }kiro-cli chat --agent my-agent --trust-all-tools"${env:CONTEXT7_API_KEY}"-- worksThe
envblock uses$VARand works. Theheadersblock requires${env:VAR}but nothing documents this. The${env:VAR}syntax is only discoverable by reading the source (substitute_env_varsincrates/chat-cli/src/mcp_client/client.rs).Other MCP clients for comparison:
${VAR_NAME}$VAR_NAME${env:VAR_NAME}(undocumented)Environment