Home / Integrations / OpenAI Codex

OpenAI Codex MCP setup: the complete config reference

Where Codex’s MCP config lives, the [mcp_servers] TOML format, the codex mcp CLI, and how to fix the common failures — plus how to put a policy gate in front of every tool call.

QUICK ANSWERQuick answer: ~/.codex/config.toml, one [mcp_servers.<name>] table per server. Note the snake_case — mcp_servers, not mcpServers.

Where OpenAI Codex keeps its MCP config.

ScopePathNotes
User ~/.codex/config.toml The primary config. Set CODEX_HOME to relocate the whole .codex directory.
Project .codex/config.toml At the project root — trusted projects only.

The Codex CLI and IDE extension share the same configuration.

The config format, key by key.

One TOML table per server: [mcp_servers.<name>]. The transport is chosen by which keys are present — command means stdio, url means streamable HTTP. Mixing keys from both is rejected.

KeyWhat it does
command Executable for a stdio server (required for stdio).
args Array of arguments passed to the command.
env Inline table of environment variables — Codex controls the child env, so pass secrets explicitly.
url Endpoint for a streamable HTTP server (required for HTTP).
bearer_token_env_var Name of an env var whose value is sent as Authorization: Bearer ….
http_headers Inline table of extra HTTP headers.
enabled Set false to switch a server off without deleting it.
startup_timeout_sec Startup limit in seconds — raise for slow npx cold starts.
tool_timeout_sec Per-tool-call limit in seconds.
enabled_tools / disabled_tools Allowlist / blocklist of tool names exposed to the agent.
~/.codex/config.toml
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
env = { LOCAL_TOKEN = "secret" }
startup_timeout_sec = 20
tool_timeout_sec = 60

REMOTE SERVER (HTTP):

~/.codex/config.toml
[mcp_servers.linear]
url = "https://mcp.linear.app/mcp"
bearer_token_env_var = "LINEAR_TOKEN"

What OpenAI Codex speaks.

TransportStatusHow to declare it
stdio Supported Declare command (+ args, env).
Streamable HTTP Supported Declare url; auth via bearer_token_env_var, http_headers, or OAuth (codex mcp login).
SSE Not supported No dedicated SSE transport — use streamable HTTP for remote servers.

Adding a server, three ways.

01 CLI — codex mcp add

Stdio servers take a ---separated command; HTTP servers take --url.

TERMINAL
# Local stdio server
codex mcp add context7 --env LOCAL_TOKEN=secret -- npx -y @upstash/context7-mcp

# Remote HTTP server with bearer auth
codex mcp add linear --url https://mcp.linear.app/mcp \
  --bearer-token-env-var LINEAR_TOKEN
02 Edit config.toml

Add a [mcp_servers.<name>] table to ~/.codex/config.toml. Manage with codex mcp list, codex mcp get <name> and codex mcp remove <name>.

03 OAuth login

codex mcp login <name> runs the OAuth flow for an HTTP server; codex mcp logout clears it.

Check it's actually connected.

  1. Run codex mcp list — every configured server should appear (add --json for machine output).
  2. codex mcp get <name> shows the resolved config for one server.
  3. Start a Codex session and ask it to call one of the server’s tools to confirm the round trip.

When it doesn't work.

Server silently absent

Check the table name: it must be [mcp_servers.<name>] — snake_case, not mcpServers. A typo means the section is ignored without an error.

Config rejected with “not supported for stdio”

You’ve mixed transports — url, bearer_token_env_var and http_headers can’t sit in a table that also has command. One transport per server.

Server times out on startup

Raise startup_timeout_sec — slow npx cold starts are the usual cause. Long-running tools need tool_timeout_sec instead.

Env vars not reaching the server

Codex controls the child process environment. Pass what the server needs explicitly via env (stdio) or bearer_token_env_var / env_http_headers (HTTP).

TOML parse errors after an edit

Inline tables (env = { KEY = "value" }) must stay on one line, and strings need quotes. A TOML linter catches most of it.

Put a policy gate in front of it.

A standard Stripe MCP wired into Codex. Every call hits Stripe directly with no policy gate.

~/.codex/config.toml
[mcp_servers.stripe]
command = "npx"
args = ["-y", "@stripe/mcp-server"]

[mcp_servers.stripe.env]
STRIPE_SECRET_KEY = "sk_live_..."

Register Stripe in PolicyLayer, mint a grant, point Codex at the proxy URL over streamable HTTP. PolicyLayer evaluates every call against the grant’s policy before it reaches Stripe — and the live key leaves your config.

~/.codex/config.toml
[mcp_servers.stripe]
url = "https://proxy.policylayer.com/mcp/<server-uuid>/"

[mcp_servers.stripe.http_headers]
Authorization = "Bearer <grant-token>"

CLI ALTERNATIVE:

TERMINAL
codex mcp add stripe \
  --url "https://proxy.policylayer.com/mcp/<server-uuid>/" \
  --bearer-token-env-var POLICYLAYER_GRANT

The <server-uuid> appears on each server's detail page. The <grant-token> shows once at mint time. See the Quick start for the full setup walk-through — and if you operate under SOC 2, HIPAA, GDPR or similar, the compliance hub maps how gateway-mediated MCP traffic evidences each framework.

What the gateway adds.

Rate limits
Cap tool calls per minute, hour, or day, per grant or shared across the team.
Access controls
Allow, deny, or conditionally gate any tool against the call's arguments.
Spend caps
Increment a counter by the call's amount; deny when the daily total exceeds your budget.
Audit logs
Every call records the grant, tool, argument keys, and the rule that decided.

A policy in practice.

Allow list_customers. Allow create_charge, but deny any charge over 50000 cents. Deny everything else.

policy.json
{
  "version": "1",
  "default": "deny",
  "tools": {
    "list_customers": {},
    "create_charge": {
      "deny_if": [
        {
          "conditions": [
            { "path": "args.amount", "op": "gt", "value": 50000 }
          ]
        }
      ]
    }
  }
}

See Writing policies for the policy format, operators, and quota shapes.

OpenAI Codex MCP questions.

Where is the Codex MCP config file?+

In ~/.codex/config.toml as [mcp_servers.<name>] TOML tables, or project-scoped in .codex/config.toml for trusted projects. The CODEX_HOME env var relocates the user directory, and codex mcp add writes the table for you.

Does Codex support remote MCP servers?+

Yes — streamable HTTP, declared with a url key. Auth options: bearer_token_env_var for token auth, http_headers for custom headers, or codex mcp login for OAuth.

Why is my MCP server not showing in codex mcp list?+

Usually a section-name typo. The table must be [mcp_servers.<name>] in snake_case; a JSON-style mcpServers key or a misspelt section is ignored without an error.

How do I fix MCP startup timeouts in Codex?+

Raise startup_timeout_sec on the server table — npx-based servers can be slow on first run while the package downloads. tool_timeout_sec separately bounds individual tool calls.

Can I limit which tools a Codex MCP server exposes?+

Yes — enabled_tools allowlists and disabled_tools blocklists tool names per server. For argument-level rules, rate limits and audit logs on top, route the server through a policy gateway like PolicyLayer.

Take your agents live. Without losing control.

Route your MCP traffic through PolicyLayer. Every tool call is checked against your policy before it runs: allow, deny, or require approval. Per-identity grants. Full audit log. Live in minutes.

Instant setup, no code required.

46,500+ MCP servers and 515,000+ tools scanned and risk-classified.

// GET IN TOUCH

Have a question or want to learn more? Send us a message.

Message sent.

We'll get back to you soon.