Post

How to Migrate MCP Servers from Cursor to Codex

Migrate MCP servers from Cursor/VSCode to Codex CLI using TOML config and mcp-proxy for streamable HTTP servers.

How to Migrate MCP Servers from Cursor to Codex

Codex CLI shares the same MCP configuration file with its VSCode extension, but uses TOML instead of JSON. Streamable HTTP servers require mcp-proxy as a bridge.

Convert JSON to TOML

Cursor and VSCode use JSON format at ~/.cursor/mcp.json or .vscode/mcp.json. Codex reads from ~/.codex/config.toml.

JSON format (Cursor/VSCode):

1
2
3
4
5
6
7
8
{
  "mcpServers": {
    "memory": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"]
    }
  }
}

TOML format (Codex):

1
2
3
[mcp_servers.memory]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-memory"]

Key differences:

  • mcpServers becomes mcp_servers (underscore, not camelCase)
  • No outer object wrapping
  • Server names use dot notation: [mcp_servers.name]
  • Arrays use square brackets: ["item1", "item2"]
  • Environment variables use inline table syntax: env = { "KEY" = "value" }

Migration Examples

Basic STDIO Server

1
2
3
4
5
6
7
8
9
10
11
[mcp_servers.fetch]
command = "uvx"
args = ["mcp-server-fetch"]

[mcp_servers.memory]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-memory"]

[mcp_servers.time]
command = "uvx"
args = ["mcp-server-time"]

Server with Environment Variables

1
2
3
4
[mcp_servers.zai-mcp-server]
command = "npx"
args = ["-y", "@z_ai/mcp-server"]
env = { "Z_AI_API_KEY" = "your_api_key", "Z_AI_MODE" = "ZAI" }

Disabled Server

1
2
3
4
5
[mcp_servers.XcodeBuildMCP]
command = "npx"
args = ["-y", "xcodebuildmcp@latest"]
env = { "SENTRY_DISABLED" = "true" }
disabled = true

Install mcp-proxy

Streamable HTTP servers won’t work directly in Codex. Install mcp-proxy to bridge STDIO to HTTP.

Using pip:

1
pip install mcp-proxy

Using pipx (isolated):

1
pipx install mcp-proxy

Using uv (fastest):

1
uv tool install mcp-proxy

Verify installation:

1
mcp-proxy --version

Configure Streamable HTTP Servers

Method 1: Single Header Format

1
2
3
4
5
6
7
[mcp_servers.web-search]
command = "mcp-proxy"
args = [
  "--transport=streamablehttp",
  "--header", "Authorization: Bearer your_api_key",
  "https://api.z.ai/api/mcp/web_search_prime/mcp"
]
1
2
3
4
5
6
7
[mcp_servers.web-search]
command = "mcp-proxy"
args = [
  "--transport=streamablehttp",
  "https://api.z.ai/api/mcp/web_search_prime/mcp"
]
env = { "AUTHORIZATION" = "Bearer your_api_key" }

Method 3: Multiple Headers

1
2
3
4
5
6
7
8
[mcp_servers.custom-api]
command = "mcp-proxy"
args = [
  "--transport=streamablehttp",
  "--header", "Authorization: Bearer token123",
  "--header", "X-API-Key: key456",
  "https://api.example.com/mcp"
]

Common Issues

“Tools: (none)” Status

Authentication failed. Check your API key format:

1
2
3
4
5
# Wrong - splits Bearer and key
args = ["--headers", "Authorization", "Bearer", "key"]

# Correct - single string value
args = ["--header", "Authorization: Bearer key"]

Authorization Token Missing

Replace placeholder values with actual credentials:

1
2
3
4
5
# Before
env = { "API_KEY" = "your_api_key" }

# After
env = { "API_KEY" = "sk-proj-abc123xyz..." }

Server Not Loading

Restart VSCode completely after editing config.toml. The extension only reads configuration on startup.

Verify Configuration

List all configured servers:

1
codex mcp list

Expected output:

1
2
3
4
5
6
7
8
9
 memory
   Status: enabled
   Command: npx -y @modelcontextprotocol/server-memory
   Tools: memory_store, memory_retrieve

 web-search
   Status: enabled
   Command: mcp-proxy --transport=streamablehttp https://...
   Tools: web_search, search_results

Check for “Tools: (none)” - indicates connection or auth failure.

Complete Migration Example

Original Cursor config (~/.cursor/mcp.json):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/mehmet/projects"]
    },
    "memory": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-memory"]
    },
    "zai-search": {
      "type": "http",
      "url": "https://api.z.ai/api/mcp/web_search_prime/mcp",
      "headers": {
        "Authorization": "Bearer sk-abc123"
      }
    }
  }
}

Converted Codex config (~/.codex/config.toml):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[mcp_servers.filesystem]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-filesystem", "/Users/mehmet/projects"]

[mcp_servers.memory]
command = "npx"
args = ["-y", "@modelcontextprotocol/server-memory"]

[mcp_servers.zai-search]
command = "mcp-proxy"
args = [
  "--transport=streamablehttp",
  "https://api.z.ai/api/mcp/web_search_prime/mcp"
]
env = { "AUTHORIZATION" = "Bearer sk-abc123" }

Important Notes

  • Codex reads ~/.codex/config.toml for both CLI and VSCode extension
  • STDIO servers migrate directly with syntax changes only
  • HTTP/SSE servers require mcp-proxy installation
  • Environment variables are more secure than hardcoded credentials
  • Restart VSCode after any configuration changes
  • Use codex mcp list to verify all servers load correctly

Configuration file location: ~/.codex/config.toml

☕ Support My Work

If you found this post helpful and want to support more content like this, you can buy me a coffee!

Your support helps me continue creating useful articles and tips for fellow developers. Thank you! 🙏

This post is licensed under CC BY 4.0 by the author.