Sitemap

Connect MCP to Codex CLI Without Guesswork

7 min readSep 15, 2026

--

Press enter or click to view image in full size
Codex CLI connecting to an MCP server through configuration, startup, transport, authentication, and tool exposure

You add one MCP server to Codex, start a session, and the tool still isn’t there.

The config file looks plausible. The server command works in your terminal. The URL opens in a browser. Yet Codex either doesn’t connect, connects without tools, or waits long enough to make you question the entire setup.

I treat that as a layered integration problem, not a config-file mystery. Codex has to load the right configuration, start or reach the server, complete the transport and authentication flow, pass the relevant permission checks, and finally expose the tools to the session. If you’re changing all of them at once, you’re debugging noise.

If you’re staring at config.toml wondering which line to change first, start with the first failure you can actually observe. Not the most suspicious-looking line.

Press enter or click to view image in full size
Codex MCP commands for adding, inspecting, listing, authenticating, and removing server entries

Confirm what Codex can connect to today

The current Codex CLI has a stable codex mcp command for managing MCP server entries. The official command reference lists add, get, list, login, logout, and remove. Codex CLI command reference

That gives you a useful first test:

codex mcp list

Then inspect one entry:

codex mcp get <name>

If the server isn’t listed, don’t debug OAuth. The session can’t use a server that isn’t in the configuration layer you’re actually running.

Separate Codex as MCP client from Codex as MCP server

This distinction causes more confusion than it should.

For the workflow in this guide, Codex is the MCP client. It connects to another MCP server and calls that server’s tools.

Older guides can muddy this by describing Codex itself as an MCP server. The current official CLI reference says the codex mcp-server command and standalone codex-mcp-server binary have been removed.

So if a setup guide tells you to start codex mcp-server, stop there. That's stale guidance for the current CLI.

Not the same feature.

Check whether the config should be global or project-scoped

Codex reads user configuration from ~/.codex/config.toml. A project can also have .codex/config.toml, and project-scoped configuration is loaded only for trusted projects. The documented layering puts project configuration above user profile and user configuration, while CLI overrides are also applied as a higher-precedence layer.

That creates a simple decision rule:

If the MCP server should follow you across projects, start with ~/.codex/config.toml. If it belongs to one repository, use that project's .codex/config.toml.

If a project entry isn’t loading, check trust before editing TOML again. An untrusted project skips project-scoped .codex/ configuration.

Add the smallest server that can prove discovery

I prefer a boring first server. You don’t need your production ticketing system, a complicated OAuth provider, and six custom headers to prove that MCP works.

The official configuration reference exposes separate fields for stdio commands and Streamable HTTP URLs. It also supports enabled, enabled_tools, disabled_tools, environment variables, HTTP headers, OAuth settings, startup timeouts, and per-tool approval modes.

Start with one server and as few moving parts as possible.

Use a stdio example when local startup is the unknown

For a local server, the configuration shape is roughly:

[mcp_servers.my-tool]
command = "your-server-command"
args = ["your", "arguments"]
[mcp_servers.my-tool.env]
API_KEY = "value"

The CLI can also register a stdio server directly:

codex mcp add my-tool -- your-server-command your-arguments

The current command reference describes add <name> -- <command...> for a stdio launcher and supports --env KEY=VALUE.

Your first question is simple: can Codex launch the process?

If the executable isn’t available in the environment Codex inherits, the server won’t reach the MCP handshake. Running the command successfully in a separate shell doesn’t prove that Codex sees the same executable path.

Use an absolute executable path when necessary.

For example:

which uvx

Then, if required:

command = "/absolute/path/to/uvx"

Green. Move on.

Use HTTP when remote auth or headers are the unknown

For a Streamable HTTP server, the configuration is different:

[mcp_servers.remote-tool]
url = "https://service.example.com/mcp/"
bearer_token_env_var = "MCP_TOKEN"

Or add the server from the CLI:

codex mcp add remote-tool --url https://service.example.com/mcp/

The important detail is that bearer_token_env_var names an environment variable. It isn't the bearer token itself. The official configuration reference describes it as the environment variable used to source the bearer token.

So this:

bearer_token_env_var = "MCP_TOKEN"

requires MCP_TOKEN to exist where Codex can access it.

If the server supports OAuth, use:

codex mcp login remote-tool

The current CLI reference lists login <name> specifically for OAuth authentication to Streamable HTTP servers.

Don’t add a bearer token just because the server is remote. Use the authentication mechanism the server actually supports.

Press enter or click to view image in full size
A simplified comparison of stdio and Streamable HTTP MCP server configuration in Codex CLI

Read the first failure by layer

Once the basic entry exists, resist the urge to change three settings at once.

Get Felix Anderson’s stories in your inbox

Join Medium for free to get updates from this writer.

I use this order:

  1. Configuration — Did Codex load the intended server entry?
  2. Startup — Can the local process launch, or can Codex reach the HTTP endpoint?
  3. Transport — Does the MCP connection establish successfully?
  4. Authentication — Are the required credentials present and accepted?
  5. Permissions — Is the tool allowed to run?
  6. Tool exposure — Does the session actually see the tool?

That order is deliberate. A permission change can’t repair a server that never started.

Server startup and discovery failures

For stdio, inspect the executable, arguments, working directory, and environment first. The official config reference exposes command, args, cwd, and env specifically for MCP stdio servers.

If the server starts slowly, don’t immediately assume the transport is broken. Codex’s documented default MCP startup timeout is 10 seconds; startup_timeout_sec can override it.

That gives you a clean experiment:

[mcp_servers.slow-tool]
command = "your-command"
startup_timeout_sec = 30

If increasing the timeout changes the result, you’ve learned something. If it doesn’t, put the timeout back and investigate the next layer.

For HTTP, start with reachability and URL correctness. Then check the authentication mechanism.

Not yet? Good. Don’t touch permissions.

Transport, authentication, and permission failures

Transport errors and authentication errors can look similar from the outside because both prevent useful tool calls.

For HTTP, check the URL first. Then verify the token environment variable or run the OAuth login flow. Codex also exposes HTTP header configuration and OAuth-related settings for MCP servers.

Authentication succeeding doesn’t automatically mean every tool can run.

The current config reference supports a server-level default_tools_approval_mode with auto, prompt, writes, or approve, plus per-tool approval overrides. It also supports enabled_tools and disabled_tools.

So there are two different questions:

Can Codex see this tool?

and

Can Codex call this tool under the current approval rules?

Treat them separately.

Inspect tool exposure before changing the config

Once the server connects, open a Codex session and run:

/mcp

The current CLI documentation describes /mcp as the session command for listing configured MCP tools, with verbose available for server details.

This is one of the most useful checkpoints in the entire process.

If the server isn’t shown, you’re still debugging configuration or connection.

If the server is shown but no tools appear, look at the server’s returned tool list and its authentication state.

If the tools appear but calls fail, investigate permissions, tool-specific approval, server-side errors, or timeout behavior.

Codex’s current configuration reference sets the default MCP tool-call timeout at 60 seconds, with tool_timeout_sec available for overrides.

A timeout is a different failure from discovery. Keep it that way.

Press enter or click to view image in full size
AI-generated illustrative Codex terminal mockup showing how MCP servers and their exposed tools might appear

Decide what belongs in user, project, or plugin scope

Scope should follow ownership.

A personal utility that you use across repositories belongs naturally in user configuration. A repository-specific MCP server belongs in project configuration, provided the project is trusted.

Plugins add another layer. The current configuration reference includes plugin-specific MCP server settings, including whether a bundled server is enabled, which tools are allowed, and default approval behavior.

My rule is straightforward:

If changing the server should affect every Codex project, use user scope. If the server exists because of one repository, use project scope. If the server is part of a packaged extension, keep its configuration with the plugin unless you have a reason to override it.

Don’t solve a scope problem by copying the same MCP entry into every file you can find. That makes the next failure harder to explain.

Leave the reader with a repeatable debug checklis

When MCP breaks, I don’t start by rewriting config.toml. I start by locating the first layer that fails.

  1. Run codex mcp list and confirm the server entry exists.
  2. Run codex mcp get <name> and inspect what Codex actually has configured.
  3. Confirm whether the entry belongs in user or trusted project scope.
  4. For stdio, verify the executable, arguments, working directory, and environment.
  5. For HTTP, verify the endpoint before debugging authentication.
  6. If OAuth is required, use codex mcp login <name>.
  7. Start a session and run /mcp.
  8. Separate “server isn’t visible” from “tool is visible but the call is denied.”
  9. Only then change approval, tool allowlists, or timeout settings.
  10. Re-run the same check after each change.

I would keep that sequence next to the terminal. It turns MCP debugging from configuration archaeology into a small set of observable decisions.

The useful result isn’t merely “the server connects.” It’s knowing which layer made it fail when it doesn’t. Once you have that boundary, the next configuration change has a reason behind it.

And that’s the part worth keeping.

--

--

Felix Anderson
Felix Anderson

I build full-stack AI products that work beyond the demo. Clean architecture, decisive execution, and no unnecessary complexity.