Claude Code MCP scopes: local vs project vs user
Three scopes, one question: who else gets this server?
Every MCP server you add to Claude Code lives in one of three scopes, chosen with --scope when you
add it. The scope decides where the configuration is written, who else ends up with the server, and
which copy wins when two scopes define the same name. Picking the wrong one is how a teammate's
session silently lacks a tool the project depends on — or how an access token ends up in a commit.
local: private, this project only
local is the default. The server is available only to you and only in the current project, and
its configuration is written to your own ~/.claude.json, under that project's entry. Use it for
servers that are personal to your setup, or for trying a server out before deciding whether the team
should have it.
claude mcp add --transport http notion https://mcp.notion.com/mcp
project: shared through the repository
project writes the server to a .mcp.json file at the project root, which is meant to be checked
in, so everyone who works in the repository gets the same server. Because a file in a repository
can come from anyone, Claude Code asks each person to approve project-scoped servers before using
them in an interactive session; until they do, the server shows as pending approval in
claude mcp list. claude mcp reset-project-choices clears those decisions if someone approved or
rejected one by mistake.
claude mcp add --scope project --transport http docs https://mcp.example.com/mcp
user: yours, everywhere
user makes the server available to you in every project, stored in the top level of
~/.claude.json rather than under a project. It suits general-purpose tools you want in every
repository — a notes service, a search tool — and keeps them out of any project's shared config.
Which copy wins
When the same server name is defined in more than one place, Claude Code uses the first it loads in this order: local, then project, then user, then servers that come from plugins, then connectors added on claude.ai. That makes local scope a safe way to override a shared project server on your own machine — pointing it at a staging endpoint, say — without editing the file your team shares.
Sharing a server without committing a secret
The awkward case is a project server that needs a credential. Don't put the credential in
.mcp.json. The file supports environment-variable expansion: write ${VAR}, or ${VAR:-default}
for a fallback, in the command, args, env, url and headers fields, and each person supplies
the value from their own environment.
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${INTERNAL_API_TOKEN}" }
}
}
}
If a variable is unset and has no default, the server still loads, but claude mcp list warns about
the missing variable and the literal ${VAR} text is used as-is — usually the reason a shared server
authenticates for one teammate and fails for another. One deliberate exception catches people out:
for remote servers, Claude Code reads certain credential variables as empty rather than expanding
them — its own API credentials, cloud provider tokens, and variables such as NPM_TOKEN or
HTTPS_PROXY — so a header built from one of those arrives blank. Give the server its own variable
name.
Project servers in scripts and CI
The approval prompt for project-scoped servers only happens in interactive sessions. In
non-interactive runs — claude -p or the Agent SDK — and in bypass-permissions mode, it is skipped,
so a .mcp.json that arrives in a pull request can load servers in an unattended pipeline without
anyone approving them. To control that, list servers to refuse in the disabledMcpjsonServers
setting, run with --strict-mcp-config, or exclude project settings with --setting-sources.
For a project server that is a script committed to the repository, write its path with
${CLAUDE_PROJECT_DIR}, which Claude Code sets to a stable project root, so the command resolves
the same way wherever each teammate cloned the repository. And for credentials that expire too
quickly to live in an environment variable, a remote server's headersHelper can name a command
that prints fresh headers on demand — but Claude Code runs it as an arbitrary shell command, so for a
project-scoped or local-scoped server it waits until you have accepted the trust dialog for that
project directory.
A quick decision rule
Personal or experimental: local. Something the whole team's workflow depends on: project, with credentials passed through environment variables. A tool you want in every repository: user. For the commands that add, list and remove servers, see how to add an MCP server to Claude Code.
Verified 2026-09-30 against ClaudeHow facts module (src/data/facts/) — see /about/#accuracy.