Streamable HTTP MCP bearer_token_env_var reported as unset although present in parent shell
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What version of Codex CLI is running?
codex-cli 0.150.1 (also reproduced with 0.147.0)
What subscription do you have?
Plus
Which model were you using?
gpt-5.5 high
What platform is your computer?
Linux 6.5.0-14-generic x86_64 x86_64
What terminal emulator and version are you using (if applicable)?
macOS Terminal.app via SSH to Ubuntu 22.04
Codex doctor report
{
"schemaVersion": 1,
"generatedAt": "1787938611s since unix epoch",
"overallStatus": "warning",
"codexVersion": "0.150.1",
"checks": {
"app_server.status": {
"id": "app_server.status",
"category": "app-server",
"status": "ok",
"summary": "background server is running",
"details": {
"app-server version": "0.141.0",
"control socket": "/home/marco/.codex/app-server-control/app-server-control.sock",
"daemon state dir": "/home/marco/.codex/app-server-daemon",
"mode": "ephemeral",
"pid file": "/home/marco/.codex/app-server-daemon/app-server.pid (missing)",
"settings": "/home/marco/.codex/app-server-daemon/settings.json (missing)",
"status": "running",
"update-loop pid file": "/home/marco/.codex/app-server-daemon/app-server-updater.pid (missing)"
},
"remediation": null,
"durationMs": 142
},
"auth.credentials": {
"id": "auth.credentials",
"category": "auth",
"status": "ok",
"summary": "auth is configured",
"details": {
"auth file": "/home/marco/.codex/auth.json",
"auth storage mode": "File",
"stored API key": "false",
"stored ChatGPT tokens": "true",
"stored agent identity": "false",
"stored auth mode": "chatgpt"
},
"remediation": null,
"durationMs": 0
},
"config.load": {
"id": "config.load",
"category": "config",
"status": "ok",
"summary": "config loaded",
"details": {
"CODEX_HOME": "/home/marco/.codex",
"config.toml": "/home/marco/.codex/config.toml",
"config.toml parse": "ok",
"cwd": "/home/marco",
"enabled feature flags": "shell_tool, view_image, unified_exec, unified_exec_zsh_fork, shell_snapshot, code_mode_host, terminal_resize_reflow, sqlite, hooks, enable_request_compression, unbounded_connection_retries, multi_agent, apps, tool_search_always_defer_mcp_tools, tool_suggest, plugins, in_app_browser, in_app_chat, in_app_dictation, in_app_local_automation, in_app_updates, browser_use, browser_use_full_cdp_access, browser_use_external, computer_use, remote_plugin, plugin_sharing, image_generation, resize_all_images, item_ids, skill_mcp_dependency_install, skill_search, mentions_v2, steer, guardian_approval, goals, collaboration_modes, tool_call_mcp_elicitation, auth_elicitation, personality, fast_mode, tui_app_server, remote_compaction_v2, compaction_image_budget, workspace_dependencies",
"feature flag overrides": "none",
"feature flags enabled": "45",
"log dir": "/home/marco/.codex/log",
"mcp servers": "1",
"model": "gpt-5.5",
"model provider": "openai",
"sqlite home": "/home/marco/.codex"
},
"remediation": null,
"durationMs": 0
},
"git.environment": {
"id": "git.environment",
"category": "git",
"status": "ok",
"summary": "git version 2.34.1",
"details": {
"PATH git #1": "/usr/bin/git",
"PATH git #2": "/bin/git",
"PATH git entries": "2",
"git build options": "git version 2.34.1; cpu: x86_64; no commit associated with this build; sizeof-long: 8; sizeof-size_t: 8; shell-path: /bin/sh",
"git exec path": "/usr/lib/git-core",
"git version": "git version 2.34.1",
"repo detected": "false",
"selected git": "/usr/bin/git"
},
"remediation": null,
"durationMs": 77
},
"installation": {
"id": "installation",
"category": "install",
"status": "ok",
"summary": "installation looks consistent",
"details": {
"PATH codex #1": "/usr/bin/codex",
"PATH codex #2": "/bin/codex",
"PATH codex entries": "2",
"current executable": "/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
"install context": "npm (package /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl, bin /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin, resources /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-resources, path /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-path)",
"managed by bun": "false",
"managed by npm": "true",
"managed by pnpm": "false",
"managed package root": "/usr/lib/node_modules/@openai/codex",
"npm update target": "/usr/lib/node_modules/@openai/codex"
},
"remediation": null,
"durationMs": 56
},
"mcp.config": {
"id": "mcp.config",
"category": "mcp",
"status": "ok",
"summary": "MCP configuration is locally consistent",
"details": {
"configured servers": "1",
"disabled servers": "0",
"streamable_http servers": "1"
},
"remediation": null,
"durationMs": 122
},
"network.env": {
"id": "network.env",
"category": "network",
"status": "ok",
"summary": "network-related environment looks readable",
"details": {
"managed proxy": "not configured",
"proxy env vars": "none",
"respect system proxy": "disabled"
},
"remediation": null,
"durationMs": 0
},
"network.provider_reachability": {
"id": "network.provider_reachability",
"category": "reachability",
"status": "ok",
"summary": "active provider endpoints are reachable over HTTP",
"details": {
"ChatGPT inference URL": "https://chatgpt.com/backend-api/<redacted> reachable (HTTP 405)",
"reachability mode": "ChatGPT auth"
},
"remediation": null,
"durationMs": 127
},
"network.websocket_reachability": {
"id": "network.websocket_reachability",
"category": "websocket",
"status": "ok",
"summary": "Responses WebSocket handshake succeeded",
"details": {
"DNS": "2 IPv4, 2 IPv6, first IPv4",
"auth mode": "chatgpt",
"connect timeout": "15000 ms",
"endpoint": "wss://chatgpt.com/backend-api/<redacted>",
"handshake result": "HTTP 101 Switching Protocols",
"model provider": "openai",
"provider name": "OpenAI",
"proxy env vars": "none",
"reasoning header": "false",
"server model present": "false",
"supports websockets": "true",
"wire API": "responses"
},
"remediation": null,
"durationMs": 731
},
"runtime.provenance": {
"id": "runtime.provenance",
"category": "runtime",
"status": "ok",
"summary": "running npm on linux-x86_64",
"details": {
"commit": "unknown",
"current executable": "/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin/codex",
"install method": "npm (package /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl, bin /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/bin, resources /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-resources, path /usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-path)",
"platform": "linux-x86_64",
"version": "0.150.1"
},
"remediation": null,
"durationMs": 0
},
"runtime.search": {
"id": "runtime.search",
"category": "search",
"status": "ok",
"summary": "search is OK (bundled)",
"details": {
"search command": "/usr/lib/node_modules/@openai/codex/node_modules/@openai/codex-linux-x64/vendor/x86_64-unknown-linux-musl/codex-path/rg",
"search command readiness": "file exists",
"search provider": "bundled"
},
"remediation": null,
"durationMs": 0
},
"sandbox.helpers": {
"id": "sandbox.helpers",
"category": "sandbox",
"status": "ok",
"summary": "sandbox configuration is readable",
"details": {
"approval policy": "OnRequest",
"codex-linux-sandbox helper": "/home/marco/.codex/tmp/arg0/codex-arg0C6DEgh/codex-linux-sandbox",
"execve wrapper helper": "/home/marco/.codex/tmp/arg0/codex-arg0C6DEgh/codex-execve-wrapper",
"filesystem sandbox": "restricted",
"network sandbox": "restricted"
},
"remediation": null,
"durationMs": 0
},
"security.endpoint": {
"id": "security.endpoint",
"category": "security",
"status": "ok",
"summary": "endpoint protection is not inspected on this platform",
"details": {
"endpoint products": "not inspected on this platform"
},
"remediation": null,
"durationMs": 0
},
"state.paths": {
"id": "state.paths",
"category": "state",
"status": "ok",
"summary": "state paths and databases are inspectable",
"details": {
"CODEX_HOME": "/home/marco/.codex (dir)",
"active rollout files": "29 files, 16767736 total bytes, 578197 average bytes",
"archived rollout files": "14 files, 2857359 total bytes, 204097 average bytes",
"goals DB": "/home/marco/.codex/goals_1.sqlite (file)",
"goals DB integrity": "ok",
"log DB": "/home/marco/.codex/logs_2.sqlite (file)",
"log DB integrity": "ok",
"log dir": "/home/marco/.codex/log (missing)",
"memories DB": "/home/marco/.codex/memories_1.sqlite (file)",
"memories DB integrity": "ok",
"queue DB": "/home/marco/.codex/queue_1.sqlite (file)",
"queue DB integrity": "ok",
"sqlite home": "/home/marco/.codex (dir)",
"state DB": "/home/marco/.codex/state_5.sqlite (file)",
"state DB integrity": "ok",
"thread history DB": "/home/marco/.codex/thread_history_1.sqlite (file)",
"thread history DB integrity": "ok"
},
"remediation": null,
"durationMs": 95
},
"state.rollout_db_parity": {
"id": "state.rollout_db_parity",
"category": "threads",
"status": "warning",
"summary": "rollout files and state DB thread inventory differ",
"details": {
"default model provider": "openai",
"rollout DB active files": "27",
"rollout DB active rows": "27",
"rollout DB archive mismatches": "0",
"rollout DB archived files": "14",
"rollout DB archived rows": "14",
"rollout DB duplicate DB paths": "0",
"rollout DB duplicate rollout thread ids": "0",
"rollout DB malformed file names": "0",
"rollout DB missing active rows": "0",
"rollout DB missing archived rows": "0",
"rollout DB model providers": "openai=41",
"rollout DB rows": "41",
"rollout DB scan cap reached": "false",
"rollout DB scan error sample": [
"/home/marco/.codex/sessions/2025/09/08/rollout-2025-09-08T11-56-09-99d744ab-aae2-47ad-a01e-58bdad3052a3.jsonl (rollout at /home/marco/.codex/sessions/2025/09/08/rollout-2025-09-08T11-56-09-99d744ab-aae2-47ad-a01e-58bdad3052a3.jsonl has no usable header record)",
"/home/marco/.codex/sessions/2025/09/07/rollout-2025-09-07T21-28-18-9feb02b4-66af-46b4-9f89-e2f5d6c8860e.jsonl (rollout at /home/marco/.codex/sessions/2025/09/07/rollout-2025-09-07T21-28-18-9feb02b4-66af-46b4-9f89-e2f5d6c8860e.jsonl has no usable header record)"
],
"rollout DB scan errors": "2",
"rollout DB sources": "vscode=39, cli=2",
"rollout DB stale rows": "0"
},
"issues": [
{
"severity": "warning",
"cause": "rollout scan was incomplete or found bad files",
"measured": "2 scan errors, 0 malformed names, scan cap reached: false",
"expected": "rollout directories are fully scannable",
"remedy": "Check file permissions and unexpected files under CODEX_HOME sessions.",
"fields": []
}
],
"remediation": null,
"durationMs": 110
},
"system.disk": {
"id": "system.disk",
"category": "disk",
"status": "ok",
"summary": "sufficient free disk space (485.5 GiB)",
"details": {
"CODEX_HOME available": "485.5 GiB",
"failure threshold": "1.0 GiB",
"warning threshold": "5.0 GiB",
"worktree available": "485.5 GiB"
},
"remediation": null,
"durationMs": 0
},
"system.environment": {
"id": "system.environment",
"category": "system",
"status": "ok",
"summary": "OS language de-DE",
"details": {
"EDITOR": "not set",
"LANG": "de_DE.UTF-8",
"VISUAL": "not set",
"os": "Linux Mint 21.3.0 (virginia) [64-bit]",
"os language": "de-DE",
"os type": "Linux Mint",
"os version": "21.3.0"
},
"remediation": null,
"durationMs": 34
},
"terminal.env": {
"id": "terminal.env",
"category": "terminal",
"status": "ok",
"summary": "terminal metadata was detected",
"details": {
"SSH_CLIENT": "present",
"SSH_CONNECTION": "present",
"SSH_TTY": "present",
"TERM": "xterm-256color",
"color output": "enabled",
"effective locale": "de_DE.UTF-8",
"stderr is terminal": "true",
"stdin is terminal": "true",
"stdout is terminal": "true",
"terminal": "unknown",
"terminal size": "121x68"
},
"remediation": null,
"durationMs": 0
},
"terminal.title": {
"id": "terminal.title",
"category": "title",
"status": "ok",
"summary": "terminal title default",
"details": {
"terminal title activity": "true",
"terminal title items": "activity, project-name",
"terminal title project source": "cwd",
"terminal title project value": "marco",
"terminal title source": "default"
},
"remediation": null,
"durationMs": 0
},
"updates.status": {
"id": "updates.status",
"category": "updates",
"status": "ok",
"summary": "update configuration is locally consistent",
"details": {
"cached latest version": "0.150.1",
"check for update on startup": "true",
"last checked at": "2026-08-28T17:20:09.713700193Z",
"latest version": "0.150.1",
"latest version status": "current version is not older",
"npm update target": "/usr/lib/node_modules/@openai/codex",
"update action": "npm install -g @openai/codex",
"version cache": "/home/marco/.codex/version.json"
},
"remediation": null,
"durationMs": 152
}
}
}
What issue are you seeing?
Codex CLI fails to start a Streamable HTTP MCP server configured with bearer_token_env_var, claiming that the environment variable is not set even though it is present in the parent shell.
Error on Codex startup:
MCP client for n8n failed to start: MCP startup failed: Environment variable N8N_MCP_TOKEN for MCP server 'n8n' is not set
However:
echo "${N8N_MCP_TOKEN:+TOKEN_IS_SET}"
returns:
TOKEN_IS_SET
and:
env | grep '^N8N_MCP_TOKEN='
confirms the variable is present.
codex mcp list shows the server as enabled with Bearer token auth, and codex mcp get n8n correctly reports:
transport: streamable_http
bearer_token_env_var: N8N_MCP_TOKEN
This reproduces on Codex CLI 0.147.0 and 0.150.1.
What steps can reproduce the bug?
- Export a valid bearer token:
export N8N_MCP_TOKEN=''
- Configure a remote Streamable HTTP MCP server:
codex mcp add n8n
--url 'https://example.com/mcp-server/http'
--bearer-token-env-var N8N_MCP_TOKEN
- Verify the configuration:
codex mcp list
This shows:
Bearer Token Env Var: N8N_MCP_TOKEN
Auth: Bearer token
- Verify the environment variable exists:
echo "${N8N_MCP_TOKEN:+TOKEN_IS_SET}"
env | grep '^N8N_MCP_TOKEN='
- Start Codex:
codex
- Codex immediately reports:
MCP client for n8n failed to start: MCP startup failed: Environment variable N8N_MCP_TOKEN for MCP server 'n8n' is not set
codex doctor --summaryreports MCP configuration as healthy, andcodex mcp get n8nconfirms bearer_token_env_var is configured correctly.
Reproduced on Codex CLI 0.147.0 and 0.150.1.
What is the expected behavior?
Codex should inherit N8N_MCP_TOKEN from the parent shell, resolve bearer_token_env_var successfully, and send the value as the Authorization: Bearer header when connecting to the configured Streamable HTTP MCP server.
The MCP client should start normally instead of reporting that the environment variable is unset.
Additional information
Platform:
Linux 6.5.0-14-generic x86_64 x86_64
Linux Mint 21.3 / Ubuntu 22.04 base
Codex CLI 0.150.1
Also reproduced with Codex CLI 0.147.0
Installed globally via npm
ChatGPT Plus authentication
The MCP server is a standards-compliant Streamable HTTP MCP endpoint using Bearer authentication. The server works independently; the failure happens before Codex attempts the authenticated MCP connection.
codex doctor --json reports:
- config.load: ok
- auth.credentials: ok
- mcp.config: ok
- configured servers: 1
- streamable_http servers: 1
- installation: ok
- network/provider reachability: ok
No proxy environment variables are configured.
This appears to be a regression or runtime environment propagation issue specifically affecting bearer_token_env_var resolution for Streamable HTTP MCP servers.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the Streamable HTTP MCP setup with bearer_token_env_var defined in the parent shell, then trace where the environment variable is read and reported as unset. Done means the configured inherited variable is recognized and used for authentication without changing the reported MCP configuration behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- authentication, cli, networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 54/100