You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Remote MCP headers: {env:...} interpolation not working #23664
{env:VAR_NAME} syntax in remote MCP server headers is not interpolated — the literal string {env:VAR_NAME} is sent as the header value instead of the resolved environment variable.
{env:VAR} (and ${VAR}) placeholders in mcp.servers.<name>.headers of a type: remote server are sent to the server as an empty string, even when the variable is exported in the OpenCode process environment (verified via ps eww). This makes Bearer-authenticated remote MCP servers unusable without hardcoding the token in the (often git-tracked) config file. Related: #23664 (Apr 2026) — still reproducible on v2.0.18 (Sep 2026).
Steps to Reproduce
export N8N_MCP_TOKEN=<valid-token> (confirmed present in the OpenCode process environment).
opencode mcp list → n8n failed: Error POSTing to endpoint: {"message":"Unauthorized: Invalid authorization header format -Malformed Bearer token"}.
Evidence that the header arrives empty (not literal, not wrong value) Probed the endpoint directly (token values redacted), same body shape the client sends:
Authorization sent
Server response
Bearer
HTTP 200 + tools/list result
Bearer fromenv (non-empty junk)
HTTP 401 {"message":"Unauthorized"}
Bearer {env:N8N_MCP_TOKEN} (lit)
HTTP 401 {"message":"Unauthorized"}
Bearer (empty)
HTTP 401 {"message":"...Malformed Bearer token"}
OpenCode's failure matches the empty row exactly — and stays identical when the variable is guaranteed non-empty in the parent process, and with ${VAR} syntax too. Only a hardcoded literal token connects.
Expected Behavior {env:N8N_MCP_TOKEN} resolves to the process environment value, as documented
(https://opencode.ai/docs/mcp-servers/ Context7 example) and as it already works in the environment block of type: local servers.
Environment
OpenCode: v2.0.18 (standalone binary, Bun runtime)
OS: macOS (darwin, arm64)
Shell: zsh
Server: self-hosted n8n 2.40.7, Streamable HTTP MCP endpoint on loopback
Impact
Blocks any setup with Bearer-authenticated remote MCP servers whose tokens live outside the config file — including multi-server setups (e.g. several n8n instances with per-project tokens in .env), where hardcoding N tokens into tracked config is not acceptable.
Activity
rekram1-node commentedon Jun 11, 2026
unable to reproduce on latest
gtso86 commentedon Sep 28, 2026
Description
{env:VAR}(and${VAR}) placeholders inmcp.servers.<name>.headersof atype: remoteserver are sent to the server as an empty string, even when the variable is exported in the OpenCode process environment (verified viaps eww). This makes Bearer-authenticated remote MCP servers unusable without hardcoding the token in the (often git-tracked) config file. Related: #23664 (Apr 2026) — still reproducible on v2.0.18 (Sep 2026).Steps to Reproduce
export N8N_MCP_TOKEN=<valid-token>(confirmed present in the OpenCode process environment).{ "mcp": { "servers": { "n8n": { "type": "remote", "url": "http://localhost:5678/mcp-server/http", "oauth": false, "headers": { "Authorization": "Bearer {env:N8N_MCP_TOKEN}" } } } } }{"message":"Unauthorized: Invalid authorization header format -Malformed Bearer token"}.Evidence that the header arrives empty (not literal, not wrong value) Probed the endpoint directly (token values redacted), same body shape the client sends:
OpenCode's failure matches the empty row exactly — and stays identical when the variable is guaranteed non-empty in the parent process, and with ${VAR} syntax too. Only a hardcoded literal token connects.
Expected Behavior
{env:N8N_MCP_TOKEN}resolves to the process environment value, as documented(https://opencode.ai/docs/mcp-servers/ Context7 example) and as it already works in the environment block of type: local servers.
Environment
Impact
Blocks any setup with Bearer-authenticated remote MCP servers whose tokens live outside the config file — including multi-server setups (e.g. several n8n instances with per-project tokens in .env), where hardcoding N tokens into tracked config is not acceptable.