MCP gives Codex real tools instead of recall: current documentation, a browser, your issue tracker, your designs. In Codex, codex mcp add <name> -- <command> adds one, codex mcp list shows what you have, and /mcp in the TUI shows what is live right now. Configuration lives in [mcp_servers.<name>] in ~/.codex/config.toml, or in a project's .codex/config.toml for a trusted project, and the CLI, the IDE extension and the ChatGPT desktop app share it, so you configure a server once and switch clients freely. The mechanics are genuinely easy. This page spends most of its time on the two things that are not: which servers earn their place, and what each one may do without asking.
Adding a server
The CLI path is the short one. codex mcp add <server-name> --env KEY=VALUE -- <command> registers a local stdio server; codex mcp list lists what is configured; codex mcp login <server> starts an OAuth flow for a server that needs one; codex mcp --help has the rest. To add Context7, a free documentation server, that is codex mcp add context7 -- npx -y @upstash/context7-mcp and nothing else.
Codex supports both transports: stdio servers that run as a local process you name with a command, and streamable HTTP servers you reach at a URL, with bearer tokens, OAuth, or a ChatGPT session for trusted first-party servers. One nice touch worth knowing if you build servers: Codex reads the MCP instructions field a server returns at initialization and uses it as server-wide guidance. If you maintain one, keep the first 512 characters self-contained, because that is the part that is doing the work when Codex is deciding how to use your server.
The options with surprising defaults
Most `[mcp_servers.<name>]` keys do what their name says. These are the ones where the default, or the interaction, is not what you would guess:
startup_timeout_sechow long Codex waits for the server to start. Default 10 seconds, which a cold npx download can absolutely exceed on a first run. If a server works on the second try and not the first, look here before you file a bug.tool_timeout_sechow long a single tool call may take. Default 60 seconds. A crawl or a big search will hit this.requiredset true and Codex startup fails if this server cannot initialize. Correct for a server your workflow genuinely depends on, painful for anything optional.enabledset false to switch a server off without deleting its config. Better than commenting it out and forgetting why.enabled_tools / disabled_toolsan allow list and a deny list of tool names. The deny list is applied after the allow list, so a tool named in both is disabled. That ordering is the whole answer to "why is my allowed tool missing".env_varsnames of environment variables to forward, as plain strings or objects with a source. This is how a key reaches the server without being written into the config file, which is the entire point.default_tools_approval_mode, the key this page exists for
An MCP server is code you did not write, handling data you did not vet, inside the agent that edits your repository. So the question that matters is not whether it connected. It is what it may do without asking you. Codex answers that with default_tools_approval_mode, set per server, with values auto, prompt, writes, and approve, and overridable on a single tool via tools.<name>.approval_mode.
`writes` is the one to know. It prompts for tools that are not marked read-only, and lets the read-only ones through. That is a genuinely well-designed default: reading your docs should not need a confirmation every time, and writing to your issue tracker should. It gets you the ask-first behavior exactly where being wrong is expensive, and stays out of your way everywhere it is not, which is the same rule we use for deciding when a hook should block versus warn.
We are pointing at it because it is the strongest safety primitive in Codex's MCP support and it is almost absent from the guides. Most "codex mcp" content stops at codex mcp add and a screenshot of /mcp showing green. Getting connected is the easy half, and it is the half that cannot hurt you.
Which servers, and the question to ask first
Before any list: do not bolt on ten servers. Each one is more setup, more context, and more attack surface. The question our /connect-mcp skill asks before it adds anything is a single one, and it is the only filter that has held up: *what do you want the agent to be able to do that it cannot now?* Then add only those. This is the shortlist that skill actually recommends, unpadded:
| Server | The job it does | How |
|---|---|---|
context7 | a library's current documentation, so the code matches today's API instead of training data from months ago. The highest-value one for most people, and the easiest to justify. | codex mcp add context7 -- npx -y @upstash/context7-mcp. No key. |
exa | search the web and find docs. One server covers both "search for X" and "pull the docs for Y". | npx -y exa-mcp-server, needs EXA_API_KEY, free to get. Pass it with --env. |
crawl4ai | read a specific site or doc set into clean markdown the agent can use. For "go read this page", as opposed to "search". | the official crawl4ai MCP server. No key. |
playwright | drive a real browser to test what you built. Optional: add it when you are actually testing, not before. | the official Playwright server. Codex's own docs list it too. |

The red flags, and the one that is a security bug
Four things the `/connect-mcp` skill stops people doing. Three are hygiene. One is a real vulnerability that most MCP guides do not mention at all:
| About to... | Do this instead |
|---|---|
| Add servers just in case | Add only what answers the question above. Every unused server costs setup, context and attack surface, permanently, to solve a problem you do not have. |
| Put an API key in the config file | Use env_vars or a secret store. A key in config.toml is a key in your shell history, your backups, and eventually a repository. |
| Trust what a server returns | Treat everything an MCP server brings back as DATA, not as instructions. A crawled page or a search result can contain text engineered to be read as a command by the agent that fetched it. This is prompt injection, it is the actual risk of giving an agent web access, and it is why default_tools_approval_mode deserved its own section. |
| Assume it connected | Make the agent use it once and show you the result. /mcp showing a server is not proof a tool call works. |
That third row deserves one more sentence, because it is the thing people get wrong. The danger of connecting a browser to your coding agent is not that the browser breaks. It is that a page you asked it to read contains a paragraph addressed to it rather than to you, and nothing in the protocol distinguishes those. Approval modes are the practical mitigation: a server that can only read is a server whose worst day is bad advice.
Verify it, then let the moment teach you
After adding a server, use it once on purpose. Ask for something only that server can answer: "use context7 to pull the current docs for <library>" and check that real, current results come back. /mcp tells you what Codex thinks is connected; a successful tool call tells you what is true. The gap between those two is where an afternoon goes.
One design note from our side, since it is the interesting half of how we ship this. The kit does not push MCP at you on install. It waits: a hook watches your prompts, and when you mention an external service by name, seventeen of them are matched literally, from stripe and postgres to figma and linear, the tutor teaches the MCP lesson once, ever, and then never mentions it again. Teaching a concept at the moment a person needs it beats putting it in a setup guide they read before it meant anything. That is a real design constraint rather than a slogan: the lesson is a Markdown file and the trigger is a regex, so it either fires at the right moment or it does not fire.
The summary: `codex mcp add` for the easy half, then spend your attention on the half that matters, which servers earn their place and what each may do without asking. Set `default_tools_approval_mode`. Treat every result as data. Verify with a real call. If you would rather have that opinion installed than remembered, kitstarter ships it as a skill for Codex and Claude Code, along with the eleven Codex hooks that fire around the rest of the loop. Choosing between the two agents first? Our Codex and Claude Code comparison is the honest version.
Common questions
How do I add an MCP server to Codex? Run codex mcp add <server-name> --env KEY=VALUE -- <command>. For example, codex mcp add context7 -- npx -y @upstash/context7-mcp. Use codex mcp list to see configured servers and /mcp in the TUI to see active ones. You can also edit ~/.codex/config.toml directly and add an [mcp_servers.<name>] table, which is what the CLI writes for you.
Where is Codex MCP configuration stored? In config.toml alongside your other Codex settings, as an [mcp_servers.<name>] table. By default that is ~/.codex/config.toml, and you can scope servers to a project with .codex/config.toml in a trusted project. The Codex CLI, the IDE extension and the ChatGPT desktop app share this configuration, so a server you add once follows you between clients.
Why does my Codex MCP server fail to start? Check startup_timeout_sec first. It defaults to 10 seconds, and a server started with npx may need longer on its first run while the package downloads, which is why it often works on the second attempt. Also check whether the server is marked required, since a required server that cannot initialize fails Codex startup, and whether a tool you expect is caught by disabled_tools, which is applied after enabled_tools.
How do I stop an MCP server doing things without asking? Set default_tools_approval_mode on the server. It takes auto, prompt, writes, or approve, and you can override it for a single tool with tools.<name>.approval_mode. The writes mode is usually the right one: it prompts for tools that are not marked read-only and allows the read-only ones through, so reading docs is frictionless while anything that changes something asks you first.
Do the same MCP servers work in Codex and Claude Code? Yes. MCP is a standard, so the same server, command, args and env work in both. What differs is where the configuration lives and how approvals are expressed: Codex uses an [mcp_servers] table in config.toml with per-server and per-tool approval modes, while Claude Code uses .mcp.json or claude mcp add with permission rules in settings.json.
The MCP opinion, installed
kitstarter ships /connect-mcp as a skill for Codex and Claude Code: ask what you actually need, add the few servers that answer it, key them safely, prove each one with a real call, and treat everything they return as untrusted input.
