Skip to main content

Module mcp_config

Module mcp_config 

Source
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§

McpConfigBuilder
A set of MCP servers for one run.
McpServerConfig
One MCP server’s configuration.