One MCP Config for Claude Code, Cursor, and Codex
The short answer: one MCP config can be your source of truth, but it should not be one raw file copied into Claude Code, Cursor, and Codex. MCP standardizes the protocol. It does not standardize every host's local configuration schema.
For a platform engineer, that distinction saves pain. Claude Code and Cursor both use JSON with mcpServers, but their fields and scope behavior differ. Codex uses TOML under [mcp_servers.<name>]. Secrets, auth helpers, tool allowlists, project trust, and precedence rules also differ.
The practical pattern is one canonical internal manifest, reviewed like infrastructure code, then generated into each tool's native config.
Why direct reuse fails
Claude Code project MCP servers live in .mcp.json. Cursor project servers live in .cursor/mcp.json, with global config at ~/.cursor/mcp.json. Codex uses ~/.codex/config.toml for user config and .codex/config.toml for trusted project config.
The schema mismatch is not cosmetic:
| Tool | Project config | Shape | Important difference |
|---|---|---|---|
| Claude Code | .mcp.json |
JSON mcpServers |
Remote URL servers need explicit type. |
| Cursor | .cursor/mcp.json |
JSON mcpServers |
Project config wins over global on duplicate server names. |
| Codex | .codex/config.toml |
TOML [mcp_servers.name] |
Auth and secret fields use Codex-specific names. |
Claude Code also warns that a JSON entry with url but no type is a configuration error because it is treated as stdio. Cursor examples commonly infer more from url. Codex cannot consume either JSON file directly.
So yes, standardize MCP. Do not standardize by pretending these three files are identical.
Use one MCP config as a canonical manifest
The source-of-truth file should describe your intent, not one vendor's syntax. Keep it boring and explicit.
A useful manifest captures:
- server name
- description and owner
- transport: stdio or Streamable HTTP
- command, args, and working directory for stdio
- URL for remote servers
- environment variable names, not secret values
- header names and token env var names
- tool allowlists or disabled tools where supported
- scope: repo, user, team, or managed
- rollout tag or version
The generators then emit native files. Claude gets .mcp.json or the appropriate user/local config. Cursor gets .cursor/mcp.json or ~/.cursor/mcp.json. Codex gets TOML.
This source-of-truth pattern also gives you a code review point. Adding a database MCP server, changing a GitHub token scope, or pointing to a new internal URL should be reviewed the way you review CI or deployment config.
What maps cleanly
Most basic fields map well:
| Canonical field | Claude Code | Cursor | Codex |
|---|---|---|---|
| Server name | mcpServers.<name> |
mcpServers.<name> |
[mcp_servers.<name>] |
| Stdio command | command |
command |
command |
| Arguments | args |
args |
args |
| Environment | env |
env or envFile for stdio |
env or env_vars |
| Remote URL | type plus url |
url |
url |
The sharp edges are auth helpers, OAuth fields, headers, tool allowlists, timeout behavior, managed settings, and trust prompts. Generate these per host. Do not flatten them into the lowest common denominator unless your organization intentionally wants fewer features.
Secrets do not belong in repo config
MCP config files become secret-sprawl magnets. Token Security reported that 20% of endpoints with Claude Code or Cursor installed in its customer data had hardcoded secrets in MCP config files. Treat that as vendor telemetry, not a universal benchmark, but the risk is obvious after one team starts copying JSON snippets into dotfiles.
Commit names, commands, URLs where appropriate, and environment variable references. Do not commit bearer tokens, PATs, session tokens, database URLs with credentials, or private headers.
Use host-native secret patterns:
- Claude Code supports
env,headers, OAuth fields, andheadersHelper. - Cursor supports interpolation in fields and
envFilefor stdio servers. - Codex supports fields such as
bearer_token_env_var,env_vars, andenv_http_headers.
For repo-level config, prefer environment variable names and onboarding checks. For user-level generated config, secret manager integration or local environment files may be acceptable if they are outside version control.
Repo-level versus user-level config
Repo-level config gives consistency. User-level config protects local secrets and machine-specific paths. Most teams need both.
Put stable, non-secret expectations in the repo:
- server names
- approved commands or remote URLs
- required env var names
- tool allowlists where they are not secret
- documentation links and ownership
Keep these user-local or managed:
- tokens and private headers
- machine-specific binary paths
- developer-local env files
- internal topology you do not want in every clone
- enterprise-enforced allowlists
Cursor explicitly merges global and project MCP files, with project config taking priority on duplicate server names. Codex has a documented precedence chain that includes trusted project config before user config. Claude Code separates project scope, local scope, and user/global storage. Your generator should know those precedence rules instead of leaving each developer to rediscover them.
Security checks for the generated files
Generated configs should be checked before they land.
- Validate JSON and TOML syntax.
- Reject literal tokens and private keys.
- Ensure remote Claude entries include
type. - Normalize server names across hosts.
- Check command and URL identities against an allowlist.
- Require owners for internal MCP servers.
- Run a smoke test in each client after generation.
For remote Streamable HTTP servers, follow the MCP transport security guidance: validate Origin, bind local servers to localhost, and use proper authentication. An MCP server can expose powerful tools. Treat it like an integration boundary, not a harmless config snippet.
A practical rollout
Start with the servers developers already use: GitHub, Linear or Jira, docs search, design tools, and one internal service. Inventory the current Claude, Cursor, and Codex configs. You will probably find different server names, different token variable names, and different transport choices for the same integration.
Then do this:
- Create a canonical manifest with server owner, transport, command or URL, env var names, and allowed tools.
- Generate Claude Code, Cursor, and Codex native configs.
- Keep secret values out of generated repo files.
- Add CI validation and secret scanning for committed config.
- Document one verification step per tool.
- Use managed or enterprise allowlists where available.
- Track drift by comparing generated files to the manifest.
The win is not fewer characters of config. The win is that MCP servers become reviewable infrastructure. Developers get the same tool names and expected capabilities across Claude Code, Cursor, and Codex, while secrets and host-specific quirks stay where they belong.