MCP

Claude Code MCP servers: how to add one and which scope to pick

Add an MCP server to Claude Code with claude mcp add, then choose local, project or user scope. Commands, the .mcp.json format and which scope wins.

Claude Code can read your files and run your shell, but it can't see your issue tracker, your database or a browser until you connect them. MCP (Model Context Protocol) servers are how you connect them. Adding one takes a single command. The choice that needs thought is the scope, which decides who gets the server and in which projects.

Two kinds of server

An MCP server either runs somewhere else and you reach it over HTTP, or it runs on your machine as a local process that Claude Code starts and talks to over stdio.

A remote server needs a name and a URL:

bash
claude mcp add --transport http notion https://mcp.notion.com/mcp

A local server needs a name and the command that starts it. Everything after -- is passed to the server untouched:

bash
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
  -- npx -y airtable-mcp-server

Two details in that second command are easy to get wrong:

  • Without the --, Claude Code tries to parse the server's own flags as its options and fails.
  • --env accepts several KEY=value pairs, so if the server name comes straight after it, the CLI reads the name as another pair. Put another option, such as --transport stdio, between them.

If you leave out --transport, the CLI assumes stdio. There is also an SSE transport, but the docs mark it deprecated: use HTTP where the server offers it.

If a server's documentation gives you a JSON block instead of a command, use claude mcp add-json:

bash
claude mcp add-json my-server '{"type":"http","url":"https://api.example.com/mcp"}'

A JSON entry with a url must also have a type. Without one, Claude Code reads the entry as a stdio server and reports an error.

The three scopes

Every server you add lands in one of three scopes. You set it with --scope (or -s), and the default is local.

Scope Loads in Shared with others Stored in
local (default) The current project only No ~/.claude.json, under that project's path
project The current project only Yes, through git .mcp.json at the project root
user Every project on your machine No ~/.claude.json

The names are confusing here. MCP's "local" scope lives in ~/.claude.json in your home directory, not in the project's .claude/settings.local.json. Nothing about a local-scoped server is written into the repository.

Which scope to choose

Pick by asking two questions: does this server belong to the project or to you, and does it carry a credential?

  • Use local for a server you are trying out, a personal tool in one repository, or anything that needs your own API key.
  • Use project when everyone working on the repository needs the same server, such as the database or staging API the codebase depends on. Commit .mcp.json.
  • Use user for tools you want everywhere, whatever the project: a browser automation server, a GitHub server, a documentation lookup.

I keep all six of my servers at user scope, because they are tools I use across every repository rather than parts of any one project. Two of them are heavy, so I don't let each session start its own copy. Each of those entries runs a small wrapper that starts one shared server process per git checkout for every session working in it, and stops it after 30 idle minutes. Claude Code doesn't do that sharing for you. Each session starts its own stdio processes.

Sharing a server with .mcp.json

Adding a server with --scope project creates or updates .mcp.json at the project root. You can also write it by hand:

json
{
  "mcpServers": {
    "api-server": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.example.com}/mcp",
      "headers": {
        "Authorization": "Bearer ${API_KEY}"
      }
    }
  }
}

Keep secrets out of the file with environment variables. ${VAR} expands to the variable, and ${VAR:-default} falls back to the default when it isn't set. Expansion works in command, args, env, url and headers. If a variable is unset and has no default, the server still loads with the literal ${VAR} text, and claude mcp list shows a warning.

Because a cloned repository could name any server, Claude Code asks you to approve project-scoped servers before an interactive session uses them. Until you do, claude mcp list shows them as pending approval. If you change your mind later, claude mcp reset-project-choices clears those decisions. claude -p runs and Agent SDK sessions can't show that prompt, so they load project servers without asking.

When the same name is in two scopes

Claude Code connects to a server once, using the definition from the highest-ranked source. It takes the whole entry from that source, and doesn't merge fields across scopes. The order, highest first:

  1. Local scope
  2. Project scope
  3. User scope
  4. Plugin-provided servers
  5. claude.ai connectors

So a local entry overrides the team's .mcp.json entry of the same name, which is handy for pointing a shared server at your own test instance. If two scopes define the same name with different endpoints, claude mcp list and /mcp warn you about the conflict.

Check and manage what you added

bash
claude mcp list                         # every server, with a health status
claude mcp get notion                   # details for one server
claude mcp remove notion --scope local  # remove it from one scope

Inside a session, /mcp shows the same status, signs you in to servers that use OAuth, and lets you switch a server off for the current project without deleting its configuration. If a server shows ! Needs authentication, run /mcp or claude mcp login <name> from your shell.

How many servers is too many?

As far as context goes, more than most people expect. Tool search is on by default: at the start of a session Claude only gets each server's tool names and instructions, and loads a tool's full definition when it needs it. In my sessions the tools from my servers arrive as a list of names, and a full definition loads only when a task needs that tool. A server you rarely use costs little, and Claude Code sets no fixed cap on tools per server.

Tool output is a different budget. Claude Code warns when one MCP tool result passes 10,000 tokens and caps it at 25,000 by default. If a server needs to return more, raise the cap with the MAX_MCP_OUTPUT_TOKENS environment variable.

To run your own check before or after an MCP call, use hooks: MCP tools are named mcp__<server>__<tool>, and a hook matcher can target them. For instructions that apply on every turn, put them in memory, and for a repeatable procedure that uses a server's tools, write a skill.

Questions

Where does Claude Code store MCP servers?

Claude Code keeps local- and user-scoped servers in ~/.claude.json in your home directory. Local ones sit under the project's path, and user ones apply everywhere. Project-scoped servers live in .mcp.json at the root of the repository.

How do I share an MCP server with my team?

Add it with --scope project, or write the entry into .mcp.json by hand, and commit the file. Use ${VAR} references for keys so each person supplies their own. Each teammate approves the server the first time they open a session in the project.

Why doesn't my MCP server show up?

Run claude mcp list from the project directory. A local-scoped server only appears in the project you added it from, a project server waits for approval, and a stdio server added without -- before its command won't start. /mcp in a session shows each server's status and lets you reconnect.

Sources

Field notes

Get the next guide by email.

Practical notes on getting more out of Claude Code: skills, hooks, MCP and agent workflows, plus what changes in each Overclaud release. Free, by email.

No spam. Unsubscribe any time. Privacy.