ClaudeHowSupport Us

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.