openai / openai/codex

codex mcp add cannot persist env_vars for stdio servers, forcing secrets into config.toml as plaintext

Open
#43,669 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

CLI config enhancement mcp
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

  1. AddMcpStdioArgs (codex-rs/cli/src/mcp_cmd.rs) only defines command and env (KEY=VALUE) — there is no flag for a variable name whitelist.

  2. 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 add that can ever produce a non-empty env_vars.

  3. Trying to work around it with the generic -c config-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 -c override onto the on-disk config and validates the result before run_add's own logic (which would supply command/args from the -- <command> argument) ever runs. A brand-new server name with only env_vars set via -c and no command/url yet is an invalid entry at that validation step, so the whole invocation aborts before add gets a chance to write anything — even though the missing command was right there in the same command line. A second invocation on an already-existing valid entry doesn't error, but also silently drops the env_vars override — add's write path only serializes what it explicitly knows about (command/args/env), not whatever -c merged 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.