MCP clients compared: Claude, Cursor, VS Code and Codex
Four MCP clients, four config formats. Here is where each one keeps its settings, what it can connect to, and the stuff that trips people up. Everything below comes from the vendors' own docs, read on November 9, 2026.
If you only read one thing: the JSON shape looks the same across a few clients, but it is not one standard. Cursor and Claude Desktop use mcpServers. VS Code’s own file uses servers. Codex uses TOML. Pasting a config between them without checking is the most common way to get a server that silently does nothing.
At a glance
| Client | Local (stdio) | Remote transports | OAuth for remote | Config lives in |
|---|---|---|---|---|
| Claude Desktop | Yes, via claude_desktop_config.json | Custom connectors: Streamable HTTP; legacy HTTP+SSE is supported but being deprecated | OAuth 2.0, or a fixed request header (beta). Registers via Anthropic’s hosted client ID document, dynamic registration, or your own client ID | Local: claude_desktop_config.json. Remote: Settings > Connectors (not the JSON file, per the MCP docs) |
| Cursor | Yes | SSE and Streamable HTTP | Yes. Authorization code flow with PKCE; optional static client ID in mcp.json | .cursor/mcp.json (project) or ~/.cursor/mcp.json (global) |
| VS Code | Yes | HTTP (tries Streamable HTTP, falls back to SSE) and SSE in the VS Code format; stdio and HTTP in the portable .mcp.json | Yes. Optional oauth.clientId in the VS Code format; browser opens on first connect | .vscode/mcp.json or user mcp.json (servers); .mcp.json or ~/.copilot/mcp-config.json (mcpServers) |
| Codex (CLI, IDE, ChatGPT desktop) | Yes | Streamable HTTP. SSE: not stated in the docs | Yes. Default auth is OAuth; supports client ID metadata documents and dynamic registration | ~/.codex/config.toml or .codex/config.toml in a trusted project |
Claude Desktop
There are two separate paths, and mixing them up wastes an afternoon.
Local servers go in claude_desktop_config.json (Settings, Developer, Edit Config). The MCP docs give the location as ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, %APPDATA%\Claude\claude_desktop_config.json on Windows, and ~/.config/Claude/claude_desktop_config.json on Linux. You have to fully quit and restart the app after editing. The docs example for the filesystem server:
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/username/Desktop"]
}
}
}Remote servers are added as custom connectors in Settings, Connectors, Add custom connector, and you paste the server URL. One thing the Help Center is blunt about: Claude connects to your remote server from Anthropic’s cloud, not from your laptop. A server on localhost, behind a VPN or on a private network will not connect even if you can reach it yourself.
For OAuth, Claude’s docs say it follows the 2025-03-26, 2025-06-18 and 2025-11-25 authorization specs. It can identify itself with a client ID metadata document that Anthropic hosts, register itself by dynamic client registration, or use a client ID you registered and typed into the dialog. The redirect URI for the hosted apps (web, Desktop, mobile) is https://claude.ai/api/mcp/auth_callback, so allow that on your authorization server. If your server wants a fixed API key instead, there is a request-header option that the docs mark as beta. The docs say free plans are limited to one custom connector.
Cursor
Cursor’s docs list three transports: stdio, SSE and Streamable HTTP, with OAuth for the two remote ones. Config goes in .cursor/mcp.json for one project or ~/.cursor/mcp.json for everywhere. A remote server is just a url plus optional headers:
{
"mcpServers": {
"remote-server": {
"url": "https://api.example.com/mcp",
"headers": { "Authorization": "Bearer ${env:MY_SERVICE_TOKEN}" }
}
}
}Variables use ${env:NAME}, and Cursor resolves them in command, args, env, url and headers. envFile only works for stdio servers.
OAuth works out of the box if the server supports it: Cursor reads the server’s protected resource metadata (RFC 9728), uses PKCE, and with dynamic registration registers as a public client. If your provider gives you a fixed client ID (the docs name Figma and Linear as examples that need a whitelisted redirect URL), add an auth block:
{
"mcpServers": {
"oauth-server": {
"url": "https://api.example.com/mcp",
"auth": { "CLIENT_ID": "${env:MCP_CLIENT_ID}", "CLIENT_SECRET": "${env:MCP_CLIENT_SECRET}", "scopes": ["read"] }
}
}
}The redirect URLs to register are https://www.cursor.com/agents/mcp/oauth/callback for web and Cursor Agents, and http://localhost:8787/callback for the desktop app. Cloud Agents keep their own MCP sign-ins on Cursor’s servers, separate from the ones on your machine.
VS Code
VS Code has two config formats and the docs are careful to say they are different. The VS Code format lives in .vscode/mcp.json (or your user profile) with a top-level servers object, supports stdio, HTTP and SSE, and has ${input:...} prompts for secrets. The portable format lives in a workspace-root .mcp.json or ~/.copilot/mcp-config.json with a top-level mcpServers object, and the capability table lists stdio and HTTP for the workspace file. For an HTTP server, the docs say VS Code tries Streamable HTTP first and falls back to SSE.
{
"servers": {
"example": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"oauth": { "clientId": "example-client-id" }
}
}
}{
"mcpServers": {
"example": { "type": "http", "url": "https://mcp.example.com/mcp" }
}
}With oauth set, VS Code runs the flow and opens a browser on the first connection. If the OAuth client is confidential, the secret is not stored in the file: you use the “Set Client Secret” CodeLens above clientId and VS Code keeps it in secret storage. Env var syntax differs by format: ${env:NAME} in the VS Code format, ${NAME} or ${NAME:-default} in the portable one. You can also add a server from the command line with code --add-mcp, and VS Code can import configs from Claude Desktop, Cursor and Windsurf, although those discovery sources are off by default.
Codex (CLI, IDE extension, ChatGPT desktop)
These three share one config. It lives in ~/.codex/config.toml, or .codex/config.toml inside a trusted project. Each server is a [mcp_servers.name] table. The docs list two server types, STDIO and Streamable HTTP; they do not mention SSE, so call that “not stated” rather than “unsupported”.
[mcp_servers.example]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "EXAMPLE_TOKEN"
# or, for an OAuth server, add it without a token and sign in:
# codex mcp add example --url https://mcp.example.com
# codex mcp login exampleFor OAuth, auth = "oauth" is the default for HTTP servers. You sign in with codex mcp login <name>, and on a machine with no browser you add --no-browser, open the printed URL elsewhere, and paste the full redirect URL back. Codex picks client ID metadata documents when the authorization server advertises support, otherwise dynamic registration, and a client ID you pass with --oauth-client-id overrides both. A few options that matter in practice: enabled_tools and disabled_tools for allow and deny lists, startup_timeout_sec (default 10) and tool_timeout_sec (default 60).
Gotchas worth knowing
- Different top-level keys.
mcpServers(Claude Desktop, Cursor, portable VS Code) versusservers(VS Code’s own file) versus TOML tables (Codex). - Different variable syntax.
${env:NAME}in Cursor and the VS Code format,${NAME}in portable VS Code files. Check before you rely on a secret being picked up. - Claude’s custom connectors are called from the cloud. Test that your server is reachable from the public internet, not just from your machine.
- Never commit tokens. VS Code’s docs say it outright: a config file is not a secret store. Use env vars or OAuth.
- Only add servers you trust. A local stdio server runs code on your machine with your permissions. All four clients’ docs say to review the publisher first.
Want to see what a server actually exposes before you wire it into anything? Point the MCP Inspector at it, and use the config generator when you are ready to write the file.
Sources
Docs change often, and we have not run every client ourselves. If a cell says “not stated”, that vendor’s docs did not say, which is not the same as “no”. Check the vendor page before you depend on a detail.
- MCP docs: connect to local servers (Claude Desktop) · read Nov 9, 2026
- MCP docs: connect to remote servers · read Nov 9, 2026
- Claude Help Center: custom connectors using remote MCP · search excerpt read Nov 9, 2026
- Claude docs: build an MCP server for Claude · read Nov 9, 2026
- Claude docs: authentication for connectors · search excerpt read Nov 9, 2026
- Cursor docs: Model Context Protocol (MCP) · read Nov 9, 2026
- VS Code docs: MCP configuration reference · read Nov 9, 2026
- VS Code docs: add MCP servers · page dated 11/4/2026
- OpenAI docs: Model Context Protocol (Codex) · read Nov 9, 2026