Where Claude Code’s MCP config lives, how the three scopes resolve, the full claude mcp add syntax, and how to fix the common failures — plus how to put a policy gate in front of every tool call.
QUICK ANSWERQuick answer: project-shared servers go in .mcp.json at the project root; personal servers live in ~/.claude.json. Top-level key is mcpServers.
| Scope | Path | Notes |
|---|---|---|
| Local (default) | ~/.claude.json | Private to you, loads in the current project only. Nested under projects → <path> → mcpServers. |
| Project | .mcp.json | In the project root. Commit it to share servers with the team. Requires one-time approval per user. |
| User | ~/.claude.json | Private to you, loads in every project. |
Precedence when names collide: local > project > user — entries are not merged; the highest-precedence server wins. Older docs called local “project” and user “global”.
All scopes use the same shape: a top-level mcpServers object, one entry per server. Local servers declare a command; remote servers declare a type and url.
| Key | What it does |
|---|---|
type | stdio, http (alias streamable-http), sse (deprecated), or ws. |
command | Executable for a stdio server. Use a full path if it isn’t on PATH. |
args | Array of arguments passed to the command. |
env | Environment variables for the server process. |
url | Endpoint for an HTTP, SSE or WebSocket server. |
headers | HTTP headers sent with every request — where static auth tokens go. |
oauth | OAuth client config: clientId, clientSecret, callbackPort, scopes. |
timeout | Per-tool-call limit in milliseconds. |
{
"mcpServers": {
"airtable": {
"command": "npx",
"args": ["-y", "airtable-mcp-server"],
"env": {
"AIRTABLE_API_KEY": "${AIRTABLE_API_KEY}"
}
}
}
} REMOTE SERVER (HTTP):
{
"mcpServers": {
"stripe": {
"type": "http",
"url": "https://mcp.stripe.com",
"headers": {
"Authorization": "Bearer <token>"
}
}
}
} .mcp.json supports env-var expansion — ${VAR} and ${VAR:-default} — in command, args, env, url and headers. A missing variable with no default fails the whole config parse.
| Transport | Status | How to declare it |
|---|---|---|
| stdio | Supported | Declare command + args, or --transport stdio on the CLI. Local child process. |
| Streamable HTTP | Supported | "type": "http" or --transport http. Recommended for remote servers; supports OAuth and auto-reconnects. |
| SSE | Deprecated | "type": "sse" still works but use HTTP instead. |
| WebSocket | Supported | "type": "ws" — JSON config only, header auth, no OAuth. |
Flags (--transport, --env, --scope, --header) come before the server name; -- separates the name from a stdio command.
# Remote HTTP server, available in all your projects claude mcp add --transport http --scope user stripe https://mcp.stripe.com \ --header "Authorization: Bearer <token>" # Local stdio server with an env var claude mcp add --transport stdio --env AIRTABLE_API_KEY=<key> airtable \ -- npx -y airtable-mcp-server
Add an entry under mcpServers in .mcp.json (shared with the team) or ~/.claude.json (personal). claude mcp add-json <name> '<json>' does the same from the command line.
claude mcp add-from-claude-desktop imports servers interactively (macOS and WSL). Manage everything with claude mcp list, claude mcp get <name> and claude mcp remove <name>.
/mcp inside Claude Code — it shows each server’s connection status and tool count, and flags servers exposing zero tools. It is also where OAuth logins are triggered.claude mcp list from the shell — project-scoped servers awaiting approval show ⏸ Pending approval.The command must be a full path if it isn’t on PATH. which npx gives you the absolute path to use.
Servers from a committed .mcp.json need one-time approval per user. If you rejected the prompt, reset with claude mcp reset-project-choices.
A ${VAR} reference with no value and no default fails the parse. Set the variable or use ${VAR:-default}.
Raise the startup limit with the MCP_TIMEOUT env var (e.g. MCP_TIMEOUT=10000 claude). The per-server timeout field governs individual tool calls.
If a static headers.Authorization token is rejected, Claude Code reports failure without falling back to OAuth — fix or remove the token. “Does not support dynamic client registration” means you need to supply --client-id and --client-secret.
A standard MCP server in your Claude Code config. Every tool call hits the upstream directly, with no policy gate.
{
"mcpServers": {
"stripe": {
"command": "npx",
"args": ["-y", "@stripe/mcp-server"],
"env": {
"STRIPE_SECRET_KEY": "sk_live_..."
}
}
}
} Register the server in PolicyLayer, mint a grant, point Claude Code at the proxy URL. PolicyLayer evaluates every call against the grant’s attached policy before it reaches Stripe — and the live key leaves your config.
{
"mcpServers": {
"stripe": {
"type": "http",
"url": "https://proxy.policylayer.com/mcp/<server-uuid>/",
"headers": {
"Authorization": "Bearer <grant-token>"
}
}
}
} CLI ALTERNATIVE:
claude mcp add --transport http stripe \ https://proxy.policylayer.com/mcp/<server-uuid>/ \ --header "Authorization: Bearer <grant-token>"
The <server-uuid> appears on each server's detail page. The <grant-token> shows once at mint time. See the Quick start for the full setup walk-through — and if you operate under SOC 2, HIPAA, GDPR or similar, the compliance hub maps how gateway-mediated MCP traffic evidences each framework.
Allow list_customers. Allow create_charge, but deny any charge over 50000 cents. Deny everything else.
{
"version": "1",
"default": "deny",
"tools": {
"list_customers": {},
"create_charge": {
"deny_if": [
{
"conditions": [
{ "path": "args.amount", "op": "gt", "value": 50000 }
]
}
]
}
}
} See Writing policies for the policy format, operators, and quota shapes.
Team-shared servers go in .mcp.json at the project root. Personal servers (local and user scope) live in ~/.claude.json. The claude mcp add command writes to these files for you — use --scope to pick which.
Local (the default) is private to you and loads in the current project only. Project scope lives in .mcp.json and is shared with everyone who clones the repo. User scope is private to you but loads in every project. On a name collision, local beats project beats user.
Run claude mcp add --transport http <name> <url>, with --header for token auth. Streamable HTTP is the recommended remote transport; SSE is deprecated. OAuth-protected servers complete login via the /mcp command.
Type /mcp inside Claude Code. It lists every configured server with its connection status and tool count, and lets you authenticate OAuth servers. From the shell, claude mcp list shows the same inventory.
Claude Code prompts for approval, and enterprise deployments can pin allowed servers via managed settings. For deterministic per-tool rules — argument conditions, rate limits, spend caps, audit logs — route the server through a policy gateway like PolicyLayer.
Route your MCP traffic through PolicyLayer. Every tool call is checked against your policy before it runs: allow, deny, or require approval. Per-identity grants. Full audit log. Live in minutes.
Instant setup, no code required.
46,500+ MCP servers and 515,000+ tools scanned and risk-classified.