How to Connect an MCP Server to Codex
Codex stores MCP servers in ~/.codex/config.toml, each under its own [mcp_servers.<name>] table. For a local server, run codex mcp add <name> -- <command>. For a remote server, run codex mcp add <name> --url <url>. If the remote server needs sign-in, run codex mcp login <name> next. The Codex CLI, the IDE extension and the ChatGPT desktop app all read the same config, so a server you add once works in all three.
What you'll have at the end
Codex lists your server in /mcp inside the terminal UI, and it can call the server's tools in a session. A local server ends up in config.toml looking like this:
[mcp_servers.bookmarks]
command = "uv"
args = ["--directory", "/ABSOLUTE/PATH/TO/bookmarks", "run", "bookmarks.py"]
The server in that example is the bookmarks server from How to build an MCP server. Replace the path with the folder where you built yours.
Before you start
- Codex: the Codex CLI, the IDE extension, or the ChatGPT desktop app. Install options and sign-in are on the Codex CLI page.
- A server to connect: a local server you can start from a terminal, or a remote server that uses Streamable HTTP. The examples use
uvfor a Python server, and the same steps work for a Node.js server. - A terminal for the
codex mcpcommands. The IDE and app steps are shown with each command.
1. Find your config file
Codex reads MCP servers from two places:
| Where | File | Applies to |
|---|---|---|
| macOS and Linux | ~/.codex/config.toml | Every project |
| Windows | %USERPROFILE%\.codex\config.toml | Every project |
| Inside a project | .codex/config.toml in the project folder | That project, only when Codex trusts it |
If you set the CODEX_HOME environment variable, Codex uses that folder instead of ~/.codex. codex mcp add and codex mcp remove edit the user file, so use them for servers you want everywhere. Edit a project file by hand when the whole team should share the server.
2. Add a local (stdio) server
A local server runs on your computer. Codex starts it as a child process and exchanges messages with it over standard input and output. Add it with codex mcp add, and put the command to run after --:
codex mcp add bookmarks -- uv --directory /ABSOLUTE/PATH/TO/bookmarks run bookmarks.py
Replace /ABSOLUTE/PATH/TO/bookmarks with the full path to your project folder. Codex saves the name, command and arguments under [mcp_servers.bookmarks], as shown in the config above.
Two options cover most other cases:
--env KEY=VALUEsets a variable for the server process. Use it for values that aren't secret.env_varsinconfig.tomlforwards a variable from your own environment to the server. The value stays out of the file, so use this for tokens.
A local server must keep standard output clean, because Codex reads protocol messages from it. How to build an MCP server explains how to log to stderr instead.
3. Add a remote server
A remote server runs somewhere else and speaks Streamable HTTP. Add it with --url:
codex mcp add example --url https://mcp.example.com/mcp
The equivalent config.toml entry is:
[mcp_servers.example]
url = "https://mcp.example.com/mcp"
If the server takes a bearer token instead of OAuth, pass the name of an environment variable that holds the token. Codex reads the token from that variable, so the token itself stays out of the file:
codex mcp add example --url https://mcp.example.com/mcp --bearer-token-env-var EXAMPLE_MCP_TOKEN
For more on the two transports, see Local vs remote MCP servers.
4. Sign in with OAuth
Many remote servers ask you to sign in with OAuth. Start the sign-in with:
codex mcp login example
In the ChatGPT desktop app, open Settings and select MCP servers, then select Authenticate next to the server. In the IDE extension, open the gear menu, select MCP servers, then select Authenticate. Either way, you approve access in your browser and Codex stores the resulting credentials. Codex stores OAuth credentials automatically, so you don't need to add a token to the config.
These options change how the login runs:
| Option | What it does |
|---|---|
--no-browser | Prints the authorization URL instead of opening a browser. |
--scopes read,write | Requests specific OAuth scopes. Use the scope names the server documents. |
--oauth-client-registration | Picks auto, cimd or dcr for this login only. The default is auto. |
If your server needs a client ID you registered in advance, pass it when you add the server:
codex mcp add example --url https://mcp.example.com/mcp --oauth-client-id my-client
Codex then prints a line that starts with OAuth callback URL:. Register that exact URL with your provider, and copy it from the output. Codex can add a server-specific ID to the path, so don't type it from memory. To sign out, run codex mcp logout example. For what sign-in looks like from your side, see What happens when an MCP server asks you to sign in.
5. Check it worked
List the servers Codex knows about, and show one of them:
codex mcp list
codex mcp get example
Then open Codex and type /mcp in the terminal UI. Your server should appear with its tools. Ask Codex for something only that server can do, such as "search the docs for ...", and check that it calls the tool.
To remove a server, run codex mcp remove example. To keep its settings but stop using it, set enabled = false under its table instead.
6. Limit tools and set timeouts (optional)
A server with many tools fills up the model's context, and some tools should always ask first. Codex can allow only some tools, deny others, and choose when to ask for approval:
[mcp_servers.example]
url = "https://mcp.example.com/mcp"
startup_timeout_sec = 20
tool_timeout_sec = 45
enabled_tools = ["search_docs", "get_page"]
default_tools_approval_mode = "prompt"
[mcp_servers.example.tools.get_page]
approval_mode = "approve"
enabled_toolsis an allow list. Only the named tools are exposed.disabled_toolsis a deny list, applied afterenabled_tools.default_tools_approval_modesets the approval behavior for every tool on the server. The values areauto,prompt,writesandapprove.writesprompts for tools that aren't marked read-only.tools.<tool-name>.approval_modeoverrides the default for one tool.startup_timeout_secis how long Codex waits for the server to start. The default is 10 seconds.tool_timeout_secis how long one tool call may run. The default is 60 seconds.
How many tools is too many covers how to choose what to expose.
Common problems
The server doesn't appear in /mcp.
Check the table header is exactly [mcp_servers.<name>] and that the file has no TOML syntax errors, such as a missing quote or bracket. Then run codex mcp list to confirm the server appears in the list Codex reads from your config.
A server in a project doesn't load.
Codex loads .codex/config.toml only for trusted projects. Move the server to ~/.codex/config.toml to use it in every project.
The server starts too slowly and times out.
Codex waits 10 seconds for a server to start by default. Raise startup_timeout_sec for that server.
Sign-in fails with a redirect error.
Your provider has to accept the callback URL that Codex prints when you add a server with --oauth-client-id. Register that exact URL, including the path, in the provider's settings.
The command can't be found.
Give the full path to the program in command, for example the output of which uv on macOS or Linux.
For more errors and fixes, see Fix MCP connection errors.
FAQ
Where does Codex store MCP server settings?
Codex stores them in config.toml under a [mcp_servers.<name>] table. The user file is ~/.codex/config.toml on macOS and Linux, and %USERPROFILE%\.codex\config.toml on Windows. A project can also have .codex/config.toml, which Codex loads only for trusted projects.
Does Codex support remote MCP servers?
Yes. Add a remote server with a url in its config table, or with codex mcp add and the --url option. Codex connects to it over Streamable HTTP. You can send a bearer token from an environment variable, or sign in with OAuth.
Can Codex sign in to an MCP server with OAuth?
Yes. Run codex mcp login with the server name, or select Authenticate for the server in the ChatGPT desktop app or the IDE extension. Codex stores the credentials after sign-in, so you do not need to put a token in the config file.
Do the Codex CLI, IDE extension and desktop app share MCP servers?
Yes. All three read the same config.toml, so a server you add in one shows up in the others. Codex lists the active servers in /mcp in the terminal UI.
- MCP clients comparedWhich AI apps run local servers, which take remote ones, and which support OAuth.
- Connect MCP servers to Claude CodeAdd servers with claude mcp add, choose a scope and use .mcp.json.
- Connect MCP servers to CursorSet up mcp.json for global and project servers in Cursor.
- What happens when a server asks you to sign inThe OAuth sign-in from your side, and how to re-authorize or revoke access.
- Fix MCP connection errorsReal error messages, their causes and how to fix them.