Expand description
Build MCP server configuration for a single run, without touching the user’s persistent config.
McpAddCommand and friends mutate
$CODEX_HOME/config.toml. That is the wrong tool for a host running many
isolated invocations: a cancelled run leaves residue, and two overlapping
runs race each other.
§Why overrides rather than a config file
claude-wrapper’s equivalent writes a JSON file and passes it to
--mcp-config. Codex has no such flag. Checked against 0.145.0: the only
config-bearing options on codex exec are -c/--config, --profile,
which layers $CODEX_HOME/<name>.config.toml, and --ignore-user-config.
Nothing consumes a standalone server-config file.
So the per-run mechanism here is -c overrides, which suits the purpose
better than a file would: nothing is written, nothing is left behind when a
run is cancelled, and concurrent runs cannot collide.
For the cases that do want a file, McpConfigBuilder::to_toml and
McpConfigBuilder::write_profile produce a profile that --profile
layers.
§Verified forms
Each of these was accepted by codex exec --strict-config, which rejects
a malformed server outright (a table with no transport fails with
invalid transport):
mcp_servers.<name>.command="npx"
mcp_servers.<name>.args=["-y","server"]
mcp_servers.<name>.env={API_KEY="x"}
mcp_servers.<name>.url="https://example.com/mcp"
mcp_servers.<name>.bearer_token_env_var="TOKEN"
mcp_servers.<name>.env_http_headers={X-Identity="IDENTITY_TOKEN"}
mcp_servers.<name>.required=true§Example
use codex_wrapper::{ExecCommand, McpConfigBuilder};
let mcp = McpConfigBuilder::new()
.stdio_server("files", "npx")
.http_server("docs", "https://example.com/mcp");
let mut cmd = ExecCommand::new("summarize the docs");
for override_ in mcp.config_overrides() {
cmd = cmd.config(override_);
}Structs§
- McpConfig
Builder - A set of MCP servers for one run.
- McpServer
Config - One MCP server’s configuration.