Migrate MCP Servers from Claude to Codex: A Practical Guide12 min read2,428 words

Migrate MCP Servers from Claude to Codex: A Practical Guide

Move MCP servers from Claude to Codex without rebuilding them. Learn the JSON-to-TOML changes, CLI setup, token handling, and migration checks.

migrate MCP servers to CodexCodex MCP configurationClaude MCP serversMCP config TOMLCodex CLI
Migrate MCP Servers from Claude to Codex: A Practical Guide

Moving MCP Servers from Claude to Codex: A Practical Migration Guide

Moving from Claude Desktop to Codex doesn't mean replacing your MCP servers. In most cases, the server command, package, and capabilities stay the same. What changes is the configuration wrapper: Claude stores server definitions in JSON, while Codex reads TOML. That difference is small enough to handle by hand, but it's also where quoting, environment variables, and remote-server settings can trip you up.

The goal is to move your existing setup without changing more than you have to. This guide walks you through finding your Claude configuration, translating local and remote server entries, adding servers through the Codex CLI, and verifying the new setup works. It also covers the decisions that matter in a real migration: where to keep credentials, when project-level configuration makes sense, and how much testing is enough. If you have one or two servers, a manual conversion is usually the simplest path. If you have more, a repeatable process helps you avoid avoidable mistakes.

What changes when you move MCP servers to Codex?

First, clarify what doesn't change. An MCP server is still the server you installed or run: same package, same command, same arguments, and (when applicable) the same environment variables. Switching clients mostly changes how the server is declared - not what the server actually does. Keeping that distinction in mind is what makes the migration manageable. Avoid upgrading packages or changing server behavior at the same time unless you have a reason; otherwise, failures get harder to diagnose.

Claude Desktop and Cursor use JSON configuration. Codex uses TOML, normally in ~/.codex/config.toml. Codex can also read configuration from .codex/config.toml inside a trusted project. The CLI and IDE extension use the same Codex configuration file, so you don't need separate server lists for those two interfaces.

Find the configuration you are migrating

Claude Desktop's configuration file is typically located at:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Make a copy before you edit or convert it. That gives you a rollback point and something concrete to compare later (server names, arguments, credentials). If you also configured MCP servers in another client, check that file separately - don't assume everything is shared with Claude Desktop.

Choose user-level or project-level configuration

Use the user-level file when the server is part of your general development setup and should be available across projects. A project-level file can be useful when a server is tied to a specific repository or team workflow. The trade-off is portability: project config can travel with the codebase, but it can also create setup expectations for anyone who opens that project. Codex project configuration is tied to project trust, so treat a repository file as a normal configuration, not a workaround around review or trust decisions.

In practice, the migration model is simple: preserve the server definition, translate the fields, and decide where it belongs. That separation keeps a format change from turning into an infrastructure change you didn't mean to make.

How do you convert Claude JSON to Codex TOML?

In Claude's JSON, MCP servers live under the mcpServers object. In Codex, each server becomes its own [mcp_servers.NAME] table. Here's a minimal local server translation.

Claude JSON:

{

"mcpServers": {

"context7": {

"command": "npx",

"args": ["-y", "@upstash/context7-mcp"]

}

}

}

Codex TOML:

[mcp_servers.context7]

command = "npx"

args = ["-y", "@upstash/context7-mcp"]

The server name becomes the table name. command stays a string, and args stays an array of strings. For local stdio servers, the command and arguments are the key pieces: you generally don't need to change the server package just because you changed clients.

Translate fields by type, not by guesswork

A practical conversion checklist:

  • Server name: move it into [mcp_servers.NAME].
  • Command: keep the executable, like npx or a local binary.
  • Arguments: keep their order and exact spelling in a TOML array.
  • Environment variables: represent them as an inline table, like env = { API_KEY = "value" }.
  • Remote endpoint: use url for the server address and http_headers for headers.

TOML isn't JSON with different braces. Pay attention to quoting, array syntax, and whether an inline-table key needs quoting. If a key contains characters that aren't valid in a bare TOML key, quote it. And don't copy a JSON object into TOML and expect it to parse as-is.

For example, a local server that reads an environment variable can look like this:

[mcp_servers.example]

command = "some-command"

args = ["--stdio"]

env = { API_KEY = "set-this-in-your-environment" }

That example shows the structure, not a recommendation to commit real secrets. For credentials, prefer referencing an environment variable or another supported secret-management approach rather than putting a live token in a config file that might get shared or committed.

Convert one server first

If your Claude configuration includes multiple entries, translate one low-risk server and test it before converting the rest. That gives you a quick sanity check that the Codex file is in the right place and the TOML syntax is valid. It also helps you isolate errors: if the first server fails, you know the problem isn't caused by a large batch conversion.

How do you add and secure MCP servers in Codex?

Editing config.toml by hand is helpful when you want to review the full setup or migrate multiple entries at once. For a single local server, the Codex CLI can be faster:

codex mcp add context7 -- npx -y @upstash/context7-mcp

Then list what you've configured:

codex mcp list

The CLI can reduce some manual TOML work, but you still need to check what you're adding. Treat the command, package name, and arguments like any other executable that runs in your dev environment. A command copied from an older config can be stale, and a server that's useful for one project may be unnecessary for another.

Configure remote servers without embedding tokens

Remote MCP servers use a URL. You can set headers with http_headers. For example:

[mcp_servers.example_remote]

url = "https://mcp.example.com"

http_headers = { "X-Client" = "codex" }

If a remote server needs bearer authentication, don't paste the token directly into config.toml. Codex can read it from an environment variable using bearer_token_env_var:

[mcp_servers.example_remote]

url = "https://mcp.example.com"

bearer_token_env_var = "MCP_ACCESS_TOKEN"

Set MCP_ACCESS_TOKEN in whatever environment launches Codex. The exact steps depend on your shell, OS, and tooling, so confirm the variable is available to the Codex process - not just set in a terminal session you happen to use.

Treat configuration as operational surface area

A server configuration can expose credentials, local files, or tools to an AI workflow. Keep permissions and scope aligned with what the job needs. User-level configuration is convenient, but it also makes the server available broadly. Project-level configuration can keep intent closer to the code, but your team should agree on how project settings are reviewed and trusted. Neither option is automatically "safer" in every scenario.

Keep secrets out of shared config, don't add servers you don't need, and write down any project-specific assumptions. As the number of servers grows, these small controls matter: reviewing one entry is cheap, while an overlooked credential (or overly broad tool) can affect every session that uses the setup.

How do you test the migration and troubleshoot failures?

A successful config edit doesn't guarantee the server actually works. Test in stages so you can tell configuration problems apart from runtime or authentication problems. Start with one server, confirm Codex can see it, and then run a real task that depends on that server. If you migrate several entries at once and something breaks, you'll have more potential causes and less useful feedback.

Use a short verification sequence

  1. Check the file location. Confirm you edited the correct user-level Codex file (or the intended trusted project's .codex/config.toml).
  2. Check the server list. Run codex mcp list and confirm the expected server shows up.
  3. Review the entry. Compare the command and arguments against your original Claude JSON. For remote servers, double-check the URL and authentication settings.
  4. Check the runtime environment. Make sure the executable exists and any required environment variables are available to the Codex process.
  5. Exercise the server. Ask Codex to run a task that clearly requires the server, then confirm the result is relevant and that the server is actually being used.

Diagnose by failure type

If the server doesn't appear in the list, start with the configuration path, table name, and TOML syntax. A misplaced bracket or malformed array can stop Codex from reading the entry correctly. If it shows up but won't start, check whether the command is installed and available in the environment that launches Codex. For npx-based servers, verify the package name and arguments match what you originally used in Claude.

If a remote server can't authenticate, confirm the URL first, then check that the required header or bearer token is present. With bearer_token_env_var, verify the environment variable name exactly matches, and that the variable is available to Codex. Don't "fix" an authentication failure by pasting a production token into a shared config file; you'll swap a debugging problem for a credential-management problem.

If the server starts but the task doesn't use it, separate "available" from "useful." A configured server may be present but not relevant to every request. Test with a task where the server's role is obvious, and make sure the server's tools actually match what you're trying to do. Otherwise, it's easy to mistake a normal model response for a migration failure.

Keep the rollback cheap

During migration, keep the original Claude JSON and change only the Codex configuration. Once the Codex setup is working, you can decide whether to remove or archive the old entries. Keeping a copy isn't forever - it's just a low-effort way to get back to a working baseline while you're validating the new setup.

Is moving your MCP setup worth it?

For most developers who already want to use Codex, moving a few MCP servers is a configuration change, not a rebuild. The server processes stay the same, and the CLI gives you a straightforward way to add local servers. The "cost" is mainly careful translation and a short verification pass. If you only have one or two servers, doing it by hand is often quicker than adding another tool to your workflow.

That calculus changes when you have lots of entries, multiple people involved, or regular updates. A conversion tool can cut down repetitive typing, but conversion isn't validation. You still need to review what got generated, confirm secrets are handled safely, and test that each server works in the environment where it will run. A browser-based converter can help with bulk formatting, but check its privacy behavior before you paste config files that include credentials. Better yet, strip or replace secrets before you convert anything.

A decision rule for manual conversion or automation

Use manual conversion when:

  • You only have a few servers.
  • The entries are simple local commands.
  • You want to inspect every field as you move it.

Consider a converter or scripted process when:

  • You have many entries or you're migrating across machines regularly.
  • A team maintains the configuration.
  • You can review and test the generated TOML before using it.

Don't automate away the review step. The repetitive part is syntax; the consequential part is deciding whether a server should be available, where its credentials come from, and what scope it should have. A tool can help with the first part, but those operational decisions still belong to whoever maintains the setup.

Conclusion

Moving MCP servers from Claude to Codex is mostly a format conversion: map each JSON server entry to a TOML table, preserve the command and arguments, and handle environment variables and remote authentication deliberately. The safest, efficient path is to back up the original config, migrate one server, check it with the Codex CLI, and run a real task before converting the rest. Keep the change narrow, keep secrets out of shared files, and automate only the repetitive syntax - not the review.

Frequently Asked Questions

Usually, no. The server command, package and arguments generally remain unchanged. You are translating the client configuration from Claude's JSON format into Codex's TOML format. Reinstall or update a server only if the command no longer works or you have a separate reason to change its version.
Codex normally reads user-level configuration from `~/.codex/config.toml`. It can also read `.codex/config.toml` inside a trusted project. The CLI and IDE extension use the same file, so you do not need to duplicate the server list for those interfaces.
Yes. Use `codex mcp add NAME -- COMMAND ARGUMENTS` to add a server, then run `codex mcp list` to check the configured servers. The CLI is convenient for simple additions, but you should still review the command and confirm the server works for your use case.
Avoid putting a live bearer token directly in `config.toml`, especially if the file may be shared. Configure `bearer_token_env_var` with the name of an environment variable, then make sure that variable is available to the Codex process. Keep the secret itself outside the shared configuration.

Related articles