MCP in Claude Code: local, project and user scopes plus .mcp.json for teams
TL;DR
Scope decides where an MCP server is stored and who sees it: local for you in one project, project for the team via .mcp.json, user for all your projects. Secrets always go through environment variables; read project servers before approving them.
You add an MCP server to Claude Code, then open another project and it's gone. A colleague clones the repo and gets asked "do you trust this server?". Or worse: an API key sits in a file committed to Git. All of this comes from not understanding MCP scopes in Claude Code: where a server is stored, who sees it, and which config wins on a name clash.
Adding servers: the two main kinds
# Remote server over HTTP (recommended)
claude mcp add --transport http github https://api.example.com/mcp \
--header "Authorization: Bearer $TOKEN"
# Local stdio server: everything after -- is the server's command
claude mcp add --transport stdio airtable --env AIRTABLE_API_KEY=xxx \
-- npx -y airtable-mcp-server
The -- matters: it stops Claude Code from treating the server's flags as its own. Short forms: -t (transport), -H (header), -s (scope), -e (env). The SSE transport is deprecated.
Three scopes
| Scope | Applies to | Shared | Stored in |
|---|---|---|---|
local (default) | Current project only | No | ~/.claude.json (under the project path) |
project | Current project | Yes, via Git | .mcp.json at the repo root |
user | All your projects | No | ~/.claude.json |
On a name clash, precedence is: organisation managed → local → project → user → plugin servers → claude.ai connectors. The entry from the highest source is used whole, with no field merging.
.mcp.json for the team, without leaking secrets
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${API_KEY}" }
}
}
}
${VAR}and${VAR:-default}work incommand,args,env,urlandheaders. Each person sets the variables in their own environment; the committed file holds no secrets.- An empty variable still counts as "set", so the default isn't used.
- To prevent leaks, credential variables such as
ANTHROPIC_API_KEYexpand to empty inside a remote server'surl/headers.
Approving project servers
In interactive sessions, Claude Code asks before using servers from .mcp.json; a cloned repo can't approve its own servers. Reset choices with claude mcp reset-project-choices. Note: in claude -p and the Agent SDK, project servers load without asking; to block them use --strict-mcp-config or disabledMcpjsonServers.
Handy management commands
claude mcp list # list + health
claude mcp get github # details for one server
claude mcp remove github # remove (doesn't revoke tokens!)
claude mcp logout github # revoke OAuth tokens
/mcp # in session: status, OAuth sign-in
Risks and caveats
- Large outputs eat context: Claude Code warns when a tool result exceeds 10,000 tokens; the default limit is 25,000 (change it with
MAX_MCP_OUTPUT_TOKENS). removedoesn't revoke tokens: runlogoutfirst if you want issued tokens invalidated.- Project servers from unfamiliar repos: read
.mcp.jsonbefore approving, especially stdio commands, since they run on your machine. - Same name in several scopes: a local entry silently beats the project one, a classic "why does my machine differ from yours".
How to apply it
- Dev: Keep personal servers (notes, calendar) at user scope and experiments at local scope.
- Tech Lead: Commit
.mcp.jsonwith environment variables for secrets and document which variables to set in the README. - PM/Admin: Use managed MCP to standardise the servers allowed across the organisation.
Sources & references
- Connect Claude Code to tools via MCP — Claude Code Docs