iTranslated by AI
Configuring Project-Specific MCP in openai/codex
I'm looking into codex to try out gpt-5-codex.
Note: I've found two methods, but they are hacky approaches that feel like a temporary workaround during a transitional phase.
Motivation
While Claude Code allowed for independent MCP settings per project, currently codex only provides a way to configure MCP globally.
For example, I don't want code analysis tools like lsmcp or serena to be running constantly; I want them to be project-specific MCP processes.
Since this isn't in the documentation, I searched for a configuration method by reading the codex source code directly.
(Admittedly, since both lsmcp and serena analyze code based on the current directory, they do function simply by being left running.)
Method 1: CODEX_HOME=$PWD/.codex
You can change the loading directory by specifying the CODEX_HOME= environment variable.
By specifying it directly, you can load project-specific MCP settings.
Configure .codex/config.toml as follows:
model = "gpt-5-codex"
[mcp_servers.playwright]
command = "npx"
args = ["-y", "@playwright/mcp"]
Start it in this state:
CODEX_HOME=$PWD/.codex codex
A drawback is that .codex/ also stores authentication information and other data, so it cannot be committed to the repository.
$ ls ~/.codex/
auth.json history.jsonl log version.json
config.toml internal_storage.json sessions
Even if you add !/.codex/config.toml to .gitignore, OpenAI might change what gets written there at any time, so it's likely to cause issues eventually.
Therefore, this should only be treated as an internal debugging method; for daily use, the following method seems safer.
Method 2: --config='...'
Based on the implementation, codex has a feature to load TOML directly using --config='key=val'.
I thought I could use this to overwrite just the mcp_servers= setting.
# Verify with codex mcp list
$ codex -c 'mcp_servers={"playwright"={"command"="npx",args=["-y", "@playwright/mcp@latest"]}}' mcp list
Name Command Args Env
playwright npx -y @playwright/mcp@latest -
# Start with this configuration
$ codex -c 'mcp_servers={"playwright"={"command"="npx",args=["-y", "@playwright/mcp@latest"]}}'
▌ Open https://example.com with playwright-mcp
tool running...
playwright.browser_navigate({"url":"https://example.com"})
If you want to load it dynamically by placing .mcp.json in your current directory:
$ codex -c "mcp_servers=$(jq .mcpServers .mcp.json -cM | sed 's/\":/\"=/g')" mcp list
You can set this as a bash/zsh alias:
# ~/.bashrc
alias codex-mcp='codex -c "mcp_servers=$(jq .mcpServers .mcp.json -cM | sed 's/\":/\"=/g')"'
Note that this relies on a strong assumption that .mcp.json exists, and it uses sed to forcibly convert JSON to TOML.
Reference (pretty much the source):
Addendum: For serena
The JSON => TOML conversion was too crude and failed to work with serena, so I'll provide a fix for just this part (since I feel like many people might use it).
https:// was being converted to https=//.
# without sed
codex -c 'mcp_servers.serena={command="uvx",args=["--from", "git+https://github.com/oraios/serena", "serena", "start-mcp-server", "--context", "codex", "--enable-web-dashboard=false"]}'
# .zshrc
alias codex-serena='codex -c "mcp_servers.serena={command=\"uvx\",args=[\"--from\", \"git+https://github.com/oraios/serena\", \"serena\", \"start-mcp-server\", \"--context\", \"codex\", \"--enable-web-dashboard=false\"]}"'
Wrap-up
In any case, these are tips that will likely be rendered obsolete by a better method in the future.
Discussion