close
For the complete documentation index, see llms.txt. Markdown versions of documentation pages are available by appending .md to the page URL.
Primary navigation

Model Context Protocol

Give Codex access to third-party tools and context

Model Context Protocol (MCP) connects models to tools and context. Use it to give ChatGPT or Codex access to third-party documentation, or to let it interact with developer tools like your browser or Figma.

ChatGPT web can use remote MCP-backed tools supplied by plugins. Local Codex clients can also connect directly to MCP servers and share their configuration.

The ChatGPT desktop app, Codex CLI, and IDE extension support MCP servers and share MCP configuration for the same Codex host.

The supported server features below apply to MCP servers configured on a Codex host. Hosted plugin tools can have different capabilities.

Supported MCP features

  • STDIO servers: Servers that run as a local process (started by a command).
    • Environment variables
  • Streamable HTTP servers: Servers that you access at an address.
    • Bearer token authentication
    • OAuth authentication, including Client ID Metadata Documents (CIMD) and Dynamic Client Registration (DCR)
    • ChatGPT session authentication for trusted first-party servers
  • Server instructions: Codex reads the MCP instructions field returned during initialization and uses it as server-wide guidance alongside the server’s tools.

If you build or maintain an MCP server for Codex, use instructions for cross-tool workflows, constraints, and rate limits that apply across the server. Keep the first 512 characters self-contained so the most important guidance is available when Codex is deciding how to use the server.

Connect Codex to an MCP server

Codex stores MCP configuration in config.toml alongside other Codex configuration settings. By default this is ~/.codex/config.toml, but you can also scope MCP servers to a project with .codex/config.toml (trusted projects only).

The ChatGPT desktop app, Codex CLI, and IDE extension share this configuration. Once you configure your MCP servers, you can switch among those clients without redoing setup.

Configure in the ChatGPT desktop app

  1. Open Settings, then select MCP servers.
  2. Select Add server.
  3. Enter a name, choose STDIO or Streamable HTTP, and provide the server’s command or URL.
  4. Save the server, then select Restart.

The server list shows which servers are enabled and which require OAuth. Select Authenticate when an OAuth server requires sign-in. In the composer, type /mcp to view connected servers.

Configure with config.toml

For more fine-grained control, edit ~/.codex/config.toml or a project-scoped .codex/config.toml. See the configuration reference for a searchable list of every supported MCP option.

Configure each MCP server with a [mcp_servers.<server-name>] table in the configuration file.

STDIO servers

  • command (required): The command that starts the server.
  • args (optional): Arguments to pass to the server.
  • env (optional): Environment variables to set for the server.
  • env_vars (optional): Environment variables to allow and forward.
  • cwd (optional): Working directory to start the server from.
  • experimental_environment (optional): Set to remote to start the stdio server through a remote executor environment when one is available.

env_vars can contain plain variable names or objects with a source:

env_vars = ["LOCAL_TOKEN", { name = "REMOTE_TOKEN", source = "remote" }]

String entries and source = "local" read from Codex’s local environment. source = "remote" reads from the remote executor environment and requires remote MCP stdio.

Streamable HTTP servers

  • url (required): The server address.
  • auth (optional): Authentication to try after configured bearer tokens and authorization headers. Use oauth (the default) for stored MCP OAuth credentials. Use chatgpt to use the current ChatGPT session for the trusted first-party ChatGPT origin, with stored OAuth as a fallback.
  • bearer_token_env_var (optional): Environment variable name for a bearer token to send in Authorization.
  • http_headers (optional): Map of header names to static values.
  • env_http_headers (optional): Map of header names to environment variable names (values pulled from the environment).

If no credential source resolves, Codex can connect to the server without authentication. Run codex mcp login <server-name> separately to start an MCP OAuth login.

Other configuration options

  • startup_timeout_sec (optional): Timeout (seconds) for the server to start. Default: 10.
  • tool_timeout_sec (optional): Timeout (seconds) for the server to run a tool. Default: 60.
  • enabled (optional): Set false to disable a server without deleting it.
  • required (optional): Set true to make startup fail if this enabled server can’t initialize.
  • enabled_tools (optional): Tool allow list.
  • disabled_tools (optional): Tool deny list (applied after enabled_tools).
  • default_tools_approval_mode (optional): Default approval behavior for tools from this server. Supported values are auto, prompt, writes, and approve. The writes mode prompts for tools that aren’t marked read-only.
  • tools.<tool>.approval_mode (optional): Per-tool approval behavior override.

OAuth client registration and callbacks

When your authorization server requires a pre-registered OAuth client, provide its client ID when adding the MCP server:

codex mcp add example --url https://mcp.example.com --oauth-client-id my-client

Codex displays the complete callback URL to register with your provider:

OAuth callback URL: http://127.0.0.1/callback

Codex saves the callback alongside the client ID in config.toml for later logins:

[mcp_servers.example]
url = "https://mcp.example.com"

[mcp_servers.example.oauth]
client_id = "my-client"
callback_url = "http://127.0.0.1/callback"

Newly added pre-registered clients use a stable callback only when the authorization server advertises authorization_response_iss_parameter_supported: true and provides a metadata issuer. If issuer support isn’t advertised, Codex appends a server-specific callback ID, such as http://127.0.0.1/callback/XuuuHAzzHOni. Existing clients without a saved callback continue using their callback-ID-specific redirect.

During login, callback selection depends on the OAuth configuration and authorization server metadata:

OAuth configurationIssuer supportCallback used
callback_url without client_idSupportedThe configured callback is used for client registration.
callback_url without client_idUnsupportedThe configured callback is used for client registration with the server-specific callback ID appended.
client_id and callback_urlSupportedThe configured callback is reused; the authorization response must contain the matching iss.
client_id and a callback_url ending in the correct callback IDUnsupportedThe configured callback is reused unchanged.
client_id and a callback_url missing the correct callback IDUnsupportedThe configured callback is ignored. Codex uses mcp_oauth_callback_url, or http://127.0.0.1/callback when unset, with the callback ID appended.
client_id without a configured callback_urlSupported or unsupportedCodex uses the global or default callback with the server-specific callback ID appended.

The fallback doesn’t modify the stored callback URL. Codex derives the callback ID from the MCP server URL, including its path and query string. The same selection rules apply to automatic and explicit login.

Set mcp_oauth_callback_url when you need a custom callback path or remote Devbox ingress URL. Newly added pre-registered clients use that URL unchanged when their provider supports issuer identification. Otherwise, they use the configured URL with the server-specific callback ID appended. Always register the exact callback displayed by codex mcp add.

For portless http://127.0.0.1 callbacks, Codex omits the listener port from the URL it displays and stores, then inserts the active listener port during authorization. This substitution doesn’t apply to localhost, IPv6 hosts, HTTPS URLs, or callbacks that already include a port. Authorization servers must accept variable loopback ports under RFC 8252, Section 7.3.

Set mcp_oauth_callback_port to choose a fixed global listener port, or set mcp_servers.<server-name>.oauth.callback_port to override it for one server. An explicit port in the callback URL doesn’t configure the listener. For a direct loopback callback, use portless http://127.0.0.1 or configure the same explicit port for both the callback URL and listener. A proxied callback can intentionally use an external URL port that differs from the local listener port. Local callback URLs bind to the local interface; non-local callback URLs bind to 0.0.0.0.

Codex validates any returned iss before exchanging the authorization code. A mismatched iss always rejects the response. When issuer support is advertised, a missing iss also rejects it. Neither failure exchanges the code or falls back to another callback. A malformed callback URL or issuer support advertised without a metadata issuer also remains a hard failure. See Authenticate users.

If the MCP server advertises scopes_supported, Codex prefers those server-advertised scopes during OAuth login. Otherwise, Codex falls back to the scopes configured in config.toml.

OAuth client registration

Codex supports OAuth Client ID Metadata Documents (CIMD) and Dynamic Client Registration (DCR). By default, Codex automatically chooses CIMD when the authorization server advertises client_id_metadata_document_supported: true, includes none in token_endpoint_auth_methods_supported, and the callback uses a supported loopback URL. Otherwise, Codex uses DCR when available. A configured OAuth client ID always takes precedence and skips client registration.

For CIMD, Codex uses a ChatGPT-hosted metadata document specific to the MCP server:

https://chatgpt.com/oauth/codex/<callback_id>/client.json

Codex derives <callback_id> from the MCP server URL and includes it in the loopback redirect URI, such as http://127.0.0.1:<port>/callback/<callback_id>. The metadata document registers the matching loopback URI without a port. Authorization servers must accept the port selected at login while matching the host and path exactly, as required by RFC 8252. Custom callback hosts, paths, or query parameters require DCR or a configured OAuth client ID.

Support for a stable, shared CIMD document is in development and coming soon:

https://chatgpt.com/oauth/codex/client.json

Codex will use the stable document with the shared /callback path when the authorization server advertises authorization_response_iss_parameter_supported: true, provides a valid issuer in its metadata, and includes a matching iss in authorization responses. Servers without issuer-bound responses will continue using the callback-specific document.

To choose a registration method for one CLI login, use --oauth-client-registration:

codex mcp login <server-name> --oauth-client-registration cimd
codex mcp login <server-name> --oauth-client-registration dcr

The default is auto. Registration choices apply only to the current login and aren’t stored in config.toml.

config.toml examples

[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
env_vars = ["LOCAL_TOKEN"]

[mcp_servers.context7.env]
MY_ENV_VAR = "MY_ENV_VALUE"
# Optional MCP OAuth callback overrides (used by `codex mcp login`)
mcp_oauth_callback_port = 5555
mcp_oauth_callback_url = "https://devbox.example.internal/callback"
[mcp_servers.figma]
url = "https://mcp.figma.com/mcp"
bearer_token_env_var = "FIGMA_OAUTH_TOKEN"
http_headers = { "X-Figma-Region" = "us-east-1" }
[mcp_servers.chrome_devtools]
url = "http://localhost:3000/mcp"
enabled_tools = ["open", "screenshot"]
disabled_tools = ["screenshot"] # applied after enabled_tools
default_tools_approval_mode = "prompt"
startup_timeout_sec = 20
tool_timeout_sec = 45
enabled = true

[mcp_servers.chrome_devtools.tools.open]
approval_mode = "approve"

Plugin-provided MCP servers

Installed plugins can bundle MCP servers in their plugin manifest. Those servers are launched from the plugin, so user config doesn’t set their transport command. User config can still control on/off state and tool policy under plugins.<plugin>.mcp_servers.<server>.

[plugins."sample@test".mcp_servers.sample]
enabled = true
default_tools_approval_mode = "prompt"
enabled_tools = ["read", "search"]

[plugins."sample@test".mcp_servers.sample.tools.search]
approval_mode = "approve"

Plugin-provided HTTP MCP servers can also declare OAuth settings in .mcp.json. Plugin manifests use the camelCase field names clientId, callbackUrl, and callbackPort:

{
  "mcpServers": {
    "sample": {
      "type": "http",
      "url": "https://mcp.example.com/mcp",
      "oauth": {
        "clientId": "my-pre-registered-client",
        "callbackUrl": "http://127.0.0.1/callback/registered"
      }
    }
  }
}

Plugin-provided MCP servers follow the same callback-selection rules as other MCP servers. If a plugin provides a clientId, its provider doesn’t support issuer-bound callbacks, and callbackUrl lacks the server-specific callback ID, Codex ignores that URL for the login and uses mcp_oauth_callback_url, or http://127.0.0.1/callback when unset, with the callback ID appended. The configured callbackUrl remains unchanged.

A plugin’s oauth.callbackPort overrides the global mcp_oauth_callback_port; if neither is set, Codex chooses an ephemeral port. The port embedded in callbackUrl doesn’t select the listener port. For a direct loopback callback with a fixed port, configure both values to match:

{
  "callbackUrl": "http://127.0.0.1:4321/callback/registered",
  "callbackPort": 4321
}

For remote ingress or another proxy, the callback URL port and local listener port can intentionally differ when the proxy forwards to the configured listener.

Examples of useful MCP servers

The list of MCP servers keeps growing. Here are a few common ones:

  • OpenAI Docs MCP: Search and read OpenAI developer docs.
  • Context7: Connect to up-to-date developer documentation.
  • Figma Local and Remote: Access your Figma designs.
  • Playwright: Control and inspect a browser using Playwright.
  • Chrome Developer Tools: Control and inspect Chrome.
  • Sentry: Access Sentry logs.
  • GitHub: Manage GitHub beyond what git supports (for example, pull requests and issues).