LIVE|CLI v0.144.0·model GPT-5.6 Sol·verified 2026-07-09
Codex Insider
The unofficial wire for OpenAI Codex.
config.toml recipe

Connect an MCP server

Published Jul 15, 2026 · Verified against the official config docs

What it does

Add a server under [mcp_servers.<id>] in ~/.codex/config.toml. Local (stdio) servers get command plus args; remote servers get url with OAuth or a bearer token. Codex wants TOML, while Claude Desktop and Cursor hand you JSON, so you translate the shape by hand or let codex mcp add write it. This page covers both transports end to end, plus startup timeouts, tool allow/deny lists, and per-tool approval.

Values

Two shapes, one per transport. A stdio entry runs a local process; an HTTP entry hits a remote URL. An entry gets one or the other, never both.

Most people land here porting a config from Claude Desktop or Cursor, which use JSON. Codex uses TOML. Here’s the translation:

Claude Desktop / Cursor JSON Codex config.toml
"mcpServers": { "ctx7": { … } } [mcp_servers.ctx7]
"command": "npx" command = "npx"
"args": ["-y", "pkg"] args = ["-y", "pkg"]
"env": { "K": "v" } [mcp_servers.ctx7.env] then K = "v"
"url": "https://…" url = "https://…"

The reliability and tool-control keys, with the documented defaults:

Key Default What it does
enabled true Park a server without deleting the block
required false Fail Codex startup if the server won’t init
startup_timeout_sec 10 Launch window (startup_timeout_ms = same in ms)
tool_timeout_sec 60 Per-tool execution window
enabled_tools / disabled_tools unset Allow list, then deny list applied on top
default_tools_approval_mode unset auto, prompt, writes, or approve

Remote auth keys: auth (oauth or chatgpt, default oauth), bearer_token_env_var, http_headers, env_http_headers, scopes, oauth_resource. OAuth callback plumbing lives at the top level, not per-server: mcp_oauth_callback_port, mcp_oauth_callback_url, and mcp_oauth_credentials_store (auto / file / keyring, default auto).

# Local (stdio) server
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
startup_timeout_sec = 30

[mcp_servers.context7.env]
API_KEY = "..."

# Remote (streamable HTTP) server
[mcp_servers.acme]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "ACME_TOKEN"
default_tools_approval_mode = "writes"

When to change it

  1. Local package server. Run codex mcp add context7 -- npx -y @upstash/context7-mcp, or write the block by hand. Restart Codex, then codex mcp list to confirm it initialized.
  2. Remote server with OAuth. Set url, run codex mcp login <id>. Codex discovers the OAuth metadata, opens a browser, and catches the callback locally.
  3. Remote server with a token. Use url plus bearer_token_env_var so the secret stays in your environment and the config file stays committable.
  4. Clamp a chatty server. Set default_tools_approval_mode = "writes" and drop tools you never call into disabled_tools.

Gotchas

A cold npx has to download the package before it answers the handshake, which blows the 10s default and throws a startup error. Raise startup_timeout_sec. See the handshake fix page.

#6020 reports every configured server failing the handshake at once on 0.53.0 (open, no maintainer response). If one entry is malformed, the whole set can go down together, so bisect by disabling servers one at a time.

A correct block still may not surface in the VS Code extension. #6465 is open with no fix; the servers run fine from the CLI.

disabled_tools is applied after enabled_tools, so a tool named in both is denied.

Sources