built by the makers of Gamut
Client configuration

mcp.json, settings.json, config.toml: which file your client reads.

Updated November 7, 2026

MCP has no standard client config file. Every client decides where it keeps its server list and what that list looks like. Many use the same mcpServers object as Claude Desktop's config, so a lot of files look alike without being interchangeable. A block that works in one client can be valid JSON in another and still be ignored. This page explains the files themselves: what mcp.json is, which file each client reads, how scopes and precedence work, and where settings.json and config.toml fit. If you just want a copy-ready DialMCP block, use MCP server configuration examples.

We checked each client's docs on November 7, 2026 and tested three of them first-hand: Claude Code 2.1.311, Gemini CLI 0.67.0 and Codex CLI 0.167.0. The test results below come from those versions.

What mcp.json is

"mcp.json" is a habit, not a spec. It names a JSON file holding one object, usually mcpServers, that maps a server name you choose to the details your client needs to reach it. A server entry takes one of two shapes:

{
  "mcpServers": {
    "local-example": {
      "command": "npx",
      "args": ["-y", "some-mcp-server"],
      "env": { "API_KEY": "..." }
    },
    "dialmcp": {
      "type": "http",
      "url": "https://mcp.dialmcp.com/mcp"
    }
  }
}

Everything else varies by client: the root key, whether type is required, which extra fields exist, and how environment variables are written.

Is there an official mcp.json schema? Not yet. SEP-2633, "Standard Client-Side Configuration Format - mcp.json", is an open draft pull request on the MCP spec repository. It was last updated on October 21, 2026, and has not been accepted. Its own problem statement is the reason this page exists: "Today every MCP client invents its own format for server configuration." The registry's server.json is a different thing. It describes a server for publishing and discovery (MCP Registry explained), and no client reads it to connect.

Which file each client reads

ClientFile(s)Root keyRemote entry
Claude Code.mcp.json (project), ~/.claude.json (local and user)mcpServersurl + "type": "http" (required)
Claude Desktopclaude_desktop_config.jsonmcpServersIntended for local servers; add remote servers as connectors
Cursor.cursor/mcp.json, ~/.cursor/mcp.jsonmcpServersurl
VS Code (portable).mcp.json, ~/.copilot/mcp-config.jsonmcpServersurl + "type": "http"
VS Code (older format).vscode/mcp.json, profile mcp.jsonserversurl + "type": "http"
Gemini CLI.gemini/settings.json, ~/.gemini/settings.jsonmcpServershttpUrl in the docs; the CLI writes url + type
Codex~/.codex/config.toml, .codex/config.toml[mcp_servers.<name>] (TOML)url
Kiro.kiro/settings/mcp.json, ~/.kiro/settings/mcp.jsonmcpServersurl
ZedZed's settings filecontext_serversurl
Devin Desktop (formerly Windsurf)~/.config/devin/mcp_config.json; Devin Local also reads .devin/mcp_config.jsonmcpServersserverUrl or url

Three patterns cover most mistakes. The name mcp.json means something different in Cursor, VS Code and Kiro. A file called settings.json defines servers in Gemini CLI, and Zed keeps them in its settings file, but Claude Code and current VS Code don't define servers there. Codex is the one major client that uses TOML. Devin Desktop's Cascade agent opens ~/.config/devin/mcp_config.json (Windows: %AppData%/devin/mcp_config.json); the older ~/.codeium/windsurf/mcp_config.json is now only read by the editor's MCP discovery. Agent setup is on Windsurf MCP setup, and Claude Desktop's file, key by key, in claude_desktop_config.json explained.

.mcp.json in Claude Code

Claude Code has three scopes, and they live in two files. We added the same server once per scope in a scratch project and recorded where each one was written:

If CLAUDE_CONFIG_DIR is set, Claude Code reads .claude.json from that directory instead. Its docs also list paths it does not read, including ~/.claude/mcp.json and ~/.claude/.mcp.json, which are common guesses.

Four rules from the docs. Our test confirmed the type rule, local over project, the approval step and variable defaults:

claude mcp add-json <name> '<json>' takes the object that goes inside mcpServers, not the wrapper. Setup, permissions and tool approval are covered in Claude Code MCP setup.

settings.json: two different jobs

Searching "mcp settings.json" gets mixed answers, because several clients use a file with that name for different things.

Claude Code: approvals and policy, not servers

Claude Code keeps server definitions in .mcp.json and ~/.claude.json. Its settings.json files decide what may run:

We put an mcpServers block in both .claude/settings.json and .claude/settings.local.json. Claude Code ignored it: the server wasn't listed and there was no warning. In the same run, "enabledMcpjsonServers": ["envtest"] in settings.local.json approved that one server and left the others pending. Note the naming trap: Claude Code's MCP "local" scope means ~/.claude.json, not .claude/settings.local.json. Administrators are the exception: the managed-only managedMcpServers setting supplies remote servers, and a separate managed-mcp.json file, in the .mcp.json format, can take exclusive control of which servers users can run.

Gemini CLI: settings.json is the server list

Gemini CLI reads mcpServers from ~/.gemini/settings.json and the project's .gemini/settings.json. Project settings override user settings. Two behaviours differ from Claude Code: gemini mcp add defaults to project scope, and it refuses to write project settings in a folder you haven't trusted ("Cannot modify settings in an untrusted workspace"). The docs describe remote servers as httpUrl (Streamable HTTP) or url (SSE), with no type field. Version 0.67.0's own gemini mcp add --transport http wrote this:

{
  "mcpServers": {
    "dialmcp": {
      "url": "https://mcp.dialmcp.com/mcp",
      "type": "http"
    }
  }
}

Gemini adds per-server fields that most others lack, including trust (skip every tool confirmation; the docs say to use it only for servers you control), includeTools / excludeTools and timeout. Its env values accept $VAR and ${VAR}.

VS Code: not settings.json any more

VS Code once read MCP servers from settings.json. Release 1.102 migrated them into the dedicated mcp.json files, and the current MCP reference doesn't list settings.json as a place to define servers. VS Code now has two formats. The portable one is .mcp.json at the workspace root or ~/.copilot/mcp-config.json, with root key mcpServers, and VS Code's docs recommend it for new servers. The older format is .vscode/mcp.json or the profile mcp.json, with root key servers. Only the older format supports inputs prompts, envFile and dev mode. VS Code can also reuse other apps' configs (chat.mcp.discovery.enabled, per source; only the Copilot CLI source is on by default). Details: VS Code MCP setup.

config.toml: Codex

Codex keeps MCP servers in ~/.codex/config.toml, shared by the CLI, the desktop app and the IDE extension. A project can add .codex/config.toml, which Codex reads only in trusted projects. Each server is a TOML table, not a JSON object. Codex CLI 0.167.0 wrote these two entries:

$ codex mcp add dialmcp --url https://mcp.dialmcp.com/mcp
$ codex mcp add localdemo --env API_KEY=xyz -- npx -y some-server

# ~/.codex/config.toml
[mcp_servers.dialmcp]
url = "https://mcp.dialmcp.com/mcp"

[mcp_servers.localdemo]
command = "npx"
args = ["-y", "some-server"]

[mcp_servers.localdemo.env]
API_KEY = "xyz"

There's no type key: a command makes a stdio server and a url a Streamable HTTP server. Codex doesn't document ${VAR} expansion. It names environment variables instead: env_vars forwards variables to a local server, bearer_token_env_var holds a token's variable name, and env_http_headers builds headers from variables. Codex-specific settings include enabled_tools, disabled_tools, startup_timeout_sec (default 10) and tool_timeout_sec (default 60). DialMCP uses OAuth, so leave bearer_token_env_var unset for it. Codex plugins can bundle their own .mcp.json, but servers you add yourself go in config.toml. Full walkthrough: Codex MCP setup.

Environment variables and secrets, by client

Copying a block between clients often breaks on the variable syntax, not on the structure:

ClientSyntaxNotes
Claude Code (.mcp.json)${VAR}, ${VAR:-default}Applies to command, args, env, url and headers
VS Code portable files${NAME}, ${NAME:-default}Bare $NAME stays literal; no ${input:}
VS Code .vscode/mcp.json${env:NAME}, ${input:id}inputs prompts once and stores the value securely
Cursor${env:NAME}Also ${userHome}, ${workspaceFolder}; envFile for stdio
Gemini CLI$VAR, ${VAR}An undefined variable becomes an empty string
CodexNone documentedUse env_vars, bearer_token_env_var, env_http_headers

Whatever the syntax, keep real keys out of any file you commit. .mcp.json, .cursor/mcp.json and .vscode/mcp.json are made to be shared through git, so reference a variable there instead of pasting a key. For more on what an MCP config can expose, see MCP security. OAuth servers sidestep the problem: DialMCP's entry holds only a URL, and the token lives in the client's credential store after sign-in.

Moving a server between files

A short checklist for moving a server entry between clients:

  1. Rename the root key. mcpServers for most files, servers for .vscode/mcp.json, context_servers for Zed, and a [mcp_servers.name] table for Codex.
  2. Fix the remote field. Add "type": "http" for Claude Code and VS Code. Devin Desktop accepts serverUrl or url. Codex and Cursor entries use url with no type field.
  3. Rewrite variables using the table above.
  4. Drop client-only fields. inputs, trust, enabled_tools and alwaysLoad each mean something to one client only.
  5. Check that it loaded. A wrong root key is still valid JSON, so the file can look fine while nothing loads. In our Claude Code test, an mcpServers block in settings.json was ignored without a warning. claude mcp list, gemini mcp list, codex mcp list and VS Code's MCP: List Servers all show what was actually loaded.

For DialMCP the block is the same everywhere: one URL, https://mcp.dialmcp.com/mcp, with no key and no headers. The ready-made versions for each file are on MCP server configuration examples. Per-client sign-in and troubleshooting are on client setup, and the stdio bridge for local-only clients is in Install DialMCP.

FAQ

What is mcp.json?

mcp.json is the common name for a JSON file that lists the MCP servers a client should connect to, usually under an mcpServers object that maps each server name to a command (local stdio) or a URL (remote). It is a convention, not part of the MCP spec. Claude Code reads .mcp.json, Cursor reads .cursor/mcp.json, VS Code reads .vscode/mcp.json or a workspace .mcp.json, and Kiro reads .kiro/settings/mcp.json.

Where is mcp.json located?

It depends on the client. Claude Code: .mcp.json at the project root, with local and user servers in ~/.claude.json. Cursor: .cursor/mcp.json in the project or ~/.cursor/mcp.json. VS Code: .mcp.json at the workspace root or ~/.copilot/mcp-config.json ($COPILOT_HOME/mcp-config.json if set), or the older .vscode/mcp.json. Codex uses ~/.codex/config.toml and Gemini CLI uses ~/.gemini/settings.json instead of an mcp.json file.

Is there an official mcp.json schema?

No. As of November 7, 2026, SEP-2633, a proposed standard client-side mcp.json format, is an open draft on the MCP spec repository and has not been accepted. The MCP Registry's server.json schema describes servers for publishing and discovery, not client configuration.

Does Claude Code read MCP servers from settings.json?

No, not for servers you define yourself. Claude Code reads server definitions from .mcp.json and ~/.claude.json. Its settings.json files hold approval and policy keys such as enableAllProjectMcpServers, enabledMcpjsonServers and deniedMcpServers. The exception is the managed-only managedMcpServers setting used by administrators. In our test with Claude Code 2.1.311, an mcpServers block placed in .claude/settings.json was ignored without a warning.

What is the difference between .mcp.json and .vscode/mcp.json?

In VS Code, .mcp.json at the workspace root is the portable format with root key mcpServers, which VS Code's docs recommend for new servers. .vscode/mcp.json is the older VS Code format with root key servers; it alone supports inputs prompts, envFile and dev mode. A block under the wrong root key isn't read as a server list, so check what loaded with MCP: List Servers.

How do I add an MCP server to Codex config.toml?

Run codex mcp add NAME --url URL for a remote server, or codex mcp add NAME -- COMMAND ARGS for a local one, or write a [mcp_servers.NAME] table in ~/.codex/config.toml with url, or command and args. Codex has no type key and does not document ${VAR} expansion; use env_vars or bearer_token_env_var for secrets.

Back to the docs hub.