codex mcp add cannot persist env_vars for stdio servers, forcing secrets into config.toml as plaintext
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.4k
- PR merge metrics
- PR metrics pending
Description
What variant of Codex are you using?
CLI
What feature would you like to see?
Summary
config.toml documents mcp_servers.<id>.env_vars as a way to whitelist environment variable names that get forwarded from Codex's own process environment into a stdio MCP server's spawned process, without storing the value itself in config.toml. This is exactly what's needed when a client-setup script exports a secret (e.g. a bearer token) into the operator's shell rc file ahead of time and wants Codex to merely forward it by name.
However, codex mcp add provides no way to persist a non-empty env_vars for a stdio server. The only mechanism it exposes is --env KEY=VALUE, which resolves and writes the literal value into config.toml.
Problem
-
AddMcpStdioArgs(codex-rs/cli/src/mcp_cmd.rs) only definescommandandenv(KEY=VALUE) — there is no flag for a variable name whitelist. -
run_add's stdio branch hardcodes the field when constructing the config entry:McpServerTransportConfig::Stdio { command: command_bin, args: command_args, env: env_map, env_vars: Vec::new(), // always empty, regardless of CLI input cwd: None, },so there is no code path through
addthat can ever produce a non-emptyenv_vars. -
Trying to work around it with the generic
-cconfig-override flag fails outright:$ codex mcp add my-server \ -c 'mcp_servers.my-server.env_vars=["MY_BEARER_TOKEN"]' \ -- mcp-remote https://example.com/mcp --transport http-only \ --header "Authorization:Bearer \${MY_BEARER_TOKEN}" Error: failed to load configuration Caused by: invalid transport in `mcp_servers.my-server`This happens because
Config::load_with_cli_overrides(overrides)merges the-coverride onto the on-disk config and validates the result beforerun_add's own logic (which would supplycommand/argsfrom the-- <command>argument) ever runs. A brand-new server name with onlyenv_varsset via-cand nocommand/urlyet is an invalid entry at that validation step, so the whole invocation aborts beforeaddgets a chance to write anything — even though the missingcommandwas right there in the same command line. A second invocation on an already-existing valid entry doesn't error, but also silently drops theenv_varsoverride —add's write path only serializes what it explicitly knows about (command/args/env), not whatever-cmerged in for validation purposes.
Expected Behavior
codex mcp add (or a related subcommand) should offer a supported way to persist env_vars for a stdio server, e.g. a repeatable --env-var NAME flag (distinct from --env KEY=VALUE) that whitelists a variable name without ever touching its value.
Actual Behavior
The only way to give a stdio MCP server access to a secret is --env KEY=VALUE, which bakes the resolved value into config.toml as plaintext, even when the exact mechanism to avoid that (env_vars) already exists and is honored at spawn time (verified in codex-rs/rmcp-client/src/utils.rs's create_env_for_mcp_server, which reads named env_vars via env::var_os from Codex's own process environment) — it's just unreachable through add.
Why this matters
Any stdio-transport MCP server that needs a bearer token / API key — a common pattern for wrapping a remote server through a local stdio proxy (e.g. mcp-remote) for TLS-trust reasons — ends up with that secret permanently duplicated in plaintext in config.toml, even when the operator's shell already exports it as an environment variable, which is exactly the scenario env_vars was designed for per the config reference docs.
Related
This looks like the same root cause as #24401 (no supported way to configure env_vars/partial env overrides for an MCP server from outside the plugin manifest itself) — that one hits it through plugin-provided servers, this one hits it through codex mcp add. Fixing the underlying "no path to writing/merging env_vars" gap would likely resolve both.
Environment
- Codex CLI version:
codex-cli 0.153.4 - Platform: Linux
- MCP transport: stdio (
-- <command>)
Additional information
No response
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 in codex-rs/cli/src/mcp_cmd.rs by reading AddMcpStdioArgs and run_add, then inspect Config::load_with_cli_overrides and rmcp-client/src/utils.rs:create_env_for_mcp_server. Done means codex mcp add can persist named stdio env_vars without writing their values to config.toml, while preserving the existing --env behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Feature
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100