Codex MCP Servers skill for Codex
Connect tools to Codex, scoped and debuggable. Codex checks that an MCP server runs on its own, adds it with codex mcp add or a [mcp_servers] table, wires credentials through environment variables or OAuth login, and trims the exposed tools with allow lists and per-tool approval modes. A symptom table covers missing servers, startup timeouts, PATH problems, auth failures and tool output that floods the context.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- codex-mcp-servers Installs to ~/.agents/skills/codex-mcp-servers/ for every project on this machine.
curl -fsSL codexskills.dev/cli.mjs -o codex-skills.mjsnode codex-skills.mjs install codex-mcp-servers The CLI also searches, updates and removes skills. Run it with no arguments to pick from a list. Needs Node 20.12+.
curl -fsSL codexskills.dev/install.sh \ | sh -s -- --project codex-mcp-servers Installs to .agents/skills/codex-mcp-servers/ in the current repository. Commit it and everyone who runs Codex there gets it.
curl -fsSLO codexskills.dev/downloads/codex-mcp-servers.zipunzip -o codex-mcp-servers.zip -d ~/.agents/skills/ The archive holds the skill folder with its generated agents/openai.yaml. Unzip into .agents/skills/ to scope it to a repo.
& ([scriptblock]::Create((irm codexskills.dev/install.ps1))) codex-mcp-servers PowerShell 5.1 or 7. Installs to %USERPROFILE%\.agents\skills\. Add -Project for the current repo.
104-line POSIX script. No sudo, no telemetry. Read install.sh
Use it in Codex
Start a prompt with $codex-mcp-servers, or pick it from /skills.
You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.
What Codex reads before loading it
Adds, scopes and debugs MCP servers for Codex with codex mcp add and [mcp_servers.NAME] tables in config.toml, covering stdio and streamable HTTP transports, env and env_vars forwarding, bearer tokens and OAuth login, enabled_tools and disabled_tools, per-tool approval modes, timeouts, required servers and plugin-provided servers. Use when a user wants to connect Codex to an MCP server such as GitHub, Sentry, Figma, Playwright or internal tools, when an MCP server does not appear in /mcp, times out or fails auth, or when tool output floods the context.
Use it when
- Connecting Codex to an existing MCP server
- An MCP server times out, fails auth or is missing from /mcp
- Too many MCP tools or large tool outputs crowd the context
- Sharing MCP servers with a team through project config
Use something else when
- You are writing the MCP server itself: use mcp-server-builder
- You want to ship the server to others inside a plugin: use codex-plugin-packaging
How to check the result
Restart Codex, run /mcp verbose to see the server connected with the expected tools, then make one harmless tool call; in CI mark the server required and confirm codex exec fails when it cannot start.
The mistake it prevents
Expecting a token exported in your shell to reach a stdio server automatically instead of forwarding it with env_vars or env.
A server is set up well when it starts within its timeout on every machine that uses the
config, exposes only the tools the work needs, asks for approval on anything that writes,
keeps secrets in environment variables or the OAuth store rather than in TOML, and shows
up in /mcp with its tools listed.
Where the config lives
- User:
~/.codex/config.toml(whatcodex mcp addwrites). - Project:
.codex/config.toml, loaded only when the project is trusted. Good for servers the whole team needs; never put secrets there. - Plugins can bundle servers; their launch command comes from the plugin, but you can
still set policy under
[plugins."<plugin>@<marketplace>".mcp_servers.<server>]. - The CLI, IDE extension and desktop app share this configuration.
Workflow
- [ ] 1. Confirm the server runs on its own
- [ ] 2. Add it (CLI for simple cases, TOML for control)
- [ ] 3. Wire credentials through env vars or OAuth
- [ ] 4. Restrict tools and set approval modes
- [ ] 5. Verify in /mcp and with one real call
1. Run it standalone first
npx -y @playwright/mcp@latest --help # stdio: does the command even start?
curl -sI https://mcp.example.com/mcp # HTTP: reachable from this machine?
npx @modelcontextprotocol/inspector npx -y @playwright/mcp@latest # list and call tools interactively
If it fails here, Codex cannot fix it. Note the runtime it needs (node, uv, docker) and whether that binary is on the PATH Codex sees.
2. Add it
CLI:
codex mcp add context7 -- npx -y @upstash/context7-mcp
codex mcp add internal-api --env API_BASE=https://api.internal.example -- uv run --directory /opt/tools/api-mcp server.py
codex mcp add sentry --url https://mcp.sentry.dev/mcp
codex mcp add example --url https://mcp.example.com --bearer-token-env-var EXAMPLE_TOKEN
codex mcp list # add --json for scripts
codex mcp get sentry --json
codex mcp remove context7
TOML for full control:
[mcp_servers.tracker]
url = "https://mcp.tracker.example.com/mcp"
bearer_token_env_var = "TRACKER_TOKEN" # value read from the environment at startup
enabled_tools = ["get_ticket", "search_tickets", "add_comment"] # exact names from /mcp verbose
default_tools_approval_mode = "writes" # prompt for tools not marked read-only
startup_timeout_sec = 20
tool_timeout_sec = 90
[mcp_servers.tracker.tools.add_comment]
approval_mode = "prompt"
[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp@latest"]
env_vars = ["PLAYWRIGHT_BROWSERS_PATH"] # forward selected variables from Codex's env
tool_timeout_sec = 120
required = false
[mcp_servers.playwright.tools.browser_snapshot]
output_token_limit = 8000 # cap one noisy tool's output
[mcp_servers.legacy-tool]
command = "/opt/tools/legacy-mcp"
enabled = false # keep config, do not start
Key reference:
| Key | Transport | Meaning |
|---|---|---|
command, args, cwd | stdio | How to launch the process |
env | stdio | Fixed variables set for the server |
env_vars | stdio | Names of variables to forward from Codex’s environment |
url | HTTP | Streamable HTTP endpoint |
bearer_token_env_var | HTTP | Env var holding a bearer token |
http_headers, env_http_headers | HTTP | Static headers; headers from env vars |
http_headers_helper | HTTP | Local command printing a JSON object of headers (short-lived tokens) |
auth = "oauth" (default) | HTTP | Use stored OAuth credentials from codex mcp login |
scopes, oauth_resource, [mcp_servers.x.oauth] | HTTP | OAuth scopes, resource, pre-registered client |
enabled_tools, disabled_tools | both | Allow list, then deny list |
default_tools_approval_mode, tools.<t>.approval_mode | both | auto, prompt, writes, approve |
tools.<t>.output_token_limit | both | Per-tool output budget |
startup_timeout_sec (default 10), tool_timeout_sec (default 60) | both | Timeouts |
required | both | Fail startup (and codex exec) if this server cannot initialize |
enabled | both | Off without deleting |
3. Credentials
- Token-based HTTP:
bearer_token_env_varand export the variable in the shell or launcher that starts Codex. The token never lands in the file. - OAuth:
codex mcp login <name>(add--scopes a,bto override scopes). In the TUI,/mcp login <name>. Pre-registered clients:codex mcp add NAME --url URL --oauth-client-id ID [--oauth-client-secret "$SECRET"], then register the exact callback URL Codex prints. The secret is saved intoconfig.toml, so keep that file private. codex mcp logout <name>clears stored OAuth credentials.
4. Restrict tools
Large servers expose dozens of tools; each tool definition costs context on every turn
and widens what a prompt injection can reach. Allow-list the tools the workflow uses,
set default_tools_approval_mode = "writes" or "prompt" for anything that changes
external state, and reserve "approve" (auto-approve) for read-only tools you trust.
Codex always prompts for tools annotated as destructive unless they also claim read-only.
5. Verify
- Restart Codex (config is read at startup), run
/mcpand/mcp verbose: the server is listed, connected, with the expected tools. - Ask for one harmless call: “Use the tracker MCP server to fetch ticket 1 and print its title.”
- For CI, set
required = trueon servers the job needs and runcodex exec --json "..."; a server that cannot start now fails the run.
Debugging table
| Symptom | Likely cause | Fix |
|---|---|---|
Not listed in /mcp | Typo in table name, project not trusted, enabled = false | codex mcp list; /debug-config |
| “startup timed out” | Slow npx download or cold start | Raise startup_timeout_sec; preinstall the package; pin a version |
command not found | Codex was launched with a minimal PATH (IDE, desktop app, CI) | Use an absolute path to the binary |
| Auth errors on stdio server | Token in your shell not forwarded | Add the name to env_vars or set it under env |
| 401/403 on HTTP | Token var unset, wrong scopes | echo $VAR; codex mcp login NAME --scopes ... |
| OAuth redirect fails | Callback not registered exactly | Register the URL codex mcp add printed; set mcp_oauth_callback_port if a fixed port is required |
| Tools listed but never used | Vague tool descriptions or too many tools | Mention the server by name in the prompt; trim enabled_tools |
| Context fills with tool output | Large snapshots, logs, pages | tools.<t>.output_token_limit; ask for narrower queries |
| stdio server crashes on start | Server prints logs to stdout | Server must log to stderr; fix the server |
| Codex starts before optional servers | Grace period | mcp_optional_startup_grace_ms (default 1000; 0 waits for each startup timeout) |
Set log_dir (or run codex -c log_dir=./.codex-log) to get codex-tui.log with
server startup errors.
Gotchas
- MCP traffic is not filtered by the sandbox network proxy. A server with network access is its own egress path; restrict it at the server or with tool allow lists.
- Prefer pinned versions (
@playwright/[email protected]) over@latestfor team configs. codex mcp-server(running Codex itself as an MCP server) was removed; usecodex app-serverfor embedding Codex.- MCP elicitation requests are auto-cancelled in
codex exec. - Never paste tokens into
http_headersin a committed project config. - Building or changing the server itself is a different job: use
mcp-server-builder.
Output contract
**Added:** tracker (HTTP, bearer via TRACKER_TOKEN), playwright (stdio, npx pinned)
**Scope:** user config | project .codex/config.toml (trusted)
**Tools exposed:** tracker 3 of 40 (writes prompt), playwright all (snapshot capped at 8k tokens)
**Verified:** /mcp shows both connected; tracker get_ticket call returned ticket 1 What the zip contains
SKILL.md plus the interface file below. Nothing runs on install.
agents/openai.yaml
Gives the Codex app a display name, a one-line description and a starter prompt for this skill.
interface:
display_name: "Codex MCP Servers"
short_description: "Connect tools to Codex, scoped and debuggable"
default_prompt: "$codex-mcp-servers Connect Codex to our Sentry MCP server and only allow read tools" About this skill
Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.