# Share MCP servers with your team

Add your servers at project scope so Claude Code writes them into a `.mcp.json` file at the
repository root, then commit that file. Every teammate who clones the repo gets
the same set of tools. One file, one shared toolset. Keep API keys and tokens out
of it by referencing environment variables instead of pasting the literal values.

If you have not connected a server yet, read [MCP fundamentals](/guides/mcp-fundamentals)
and [MCP configuration](/guides/mcp-configuration) first. This guide is about the
team part: one shared definition, no leaked secrets.

## What are the MCP scopes, and which one is shared with the team?

When you run `claude mcp add`, Claude Code stores the server at one of three
scopes. The scope decides where the config lives and who else sees it.

| Scope | Loads in | Shared with team | Stored in |
| --- | --- | --- | --- |
| Local | Current project only | No | `~/.claude.json` |
| Project | Current project only | Yes, via version control | `.mcp.json` in project root |
| User | All your projects | No | `~/.claude.json` |

Local scope is the default. It stays private to you.Because local is the default, running `claude mcp add` without `--scope project` writes the server to your private `~/.claude.json`, so nothing lands in `.mcp.json` and teammates never see it. Run `claude mcp list` after adding to confirm it shows as project-scoped before you tell the team to pull. User scope follows you
across every project on your machine. Only project scope writes to a file inside
the repository, and that file is the one you commit. So pick project scope
whenever the whole team needs the same server.

## How do I add a server at project scope?

Pass `--scope project` (or the short `-s project`) to `claude mcp add`. Claude
Code creates or updates `.mcp.json` at the repository root for you.

For a remote HTTP server:

```bash
claude mcp add --transport http --scope project linear https://mcp.linear.app/mcp
```

For a local stdio server, put the command after a `--` separator. Everything
after the `--` is the command Claude Code runs, untouched:

```bash
claude mcp add --scope project --transport stdio db -- npx @acme/db-mcp-server
```

The `--` matters. It tells the CLI where its own flags stop and the server
command begins. Drop it and the CLI tries to read the command as one of its own
options.

## What goes into .mcp.json?

The command above writes a standardised shape. A project-scoped `.mcp.json`
holds an `mcpServers` object keyed by server name:

```json
{
  "mcpServers": {
    "linear": {
      "type": "http",
      "url": "https://mcp.linear.app/mcp"
    },
    "db": {
      "command": "npx",
      "args": ["@acme/db-mcp-server"],
      "env": {}
    }
  }
}
```

You can edit this file by hand too. The `type` field accepts `http` (or
`streamable-http` as an alias), and stdio servers use `command`, `args`, and
`env`. Commit the file like any other config:

```bash
git add .mcp.json
git commit -m "Add Linear and database MCP servers for the team"
```

Now a teammate runs `git pull`, opens Claude Code in the repo, and the servers
are already defined. No copying a command off a wiki. No guessing a URL.

## Why does Claude Code ask teammates to approve shared servers?

Claude Code does not silently trust a `.mcp.json` that arrives from version
control. A committed file is something other people can change. So the first time
a teammate opens the project, Claude Code prompts them to approve the
project-scoped servers before it uses any of them.

Until they approve, the servers show as pending. You can see this state from the
command line:

```bash
claude mcp list
```

A server awaiting approval appears as `⏸ Pending approval`. Running `claude`
interactively brings up the prompt to review and approve. If someone needs to
redo their decision later, this resets the stored choices for the project:

```bash
claude mcp reset-project-choices
```

This is why project scope is safe to share. The config travels with the repo,
but each person consents before the servers run on their machine.

## How do I keep secrets out of the committed file?

The committed `.mcp.json` is readable by everyone with repo access, and it lives
in git history forever. Never put a literal API key, token, or password in it.
A pasted secret in a tracked file is a leaked secret.The trap is fixing this too late: people paste a real key, commit, then swap in `${VAR}` in a later commit and assume they are safe. The old value still sits in git history for anyone who runs `git log -p .mcp.json`, so a follow-up edit does not undo the leak. Treat any key that ever touched a commit as compromised, rotate it, and only then rewrite history if you must. For the wider question of
[what to allow and what to block](/guides/mcp-security-basics) when you share
servers, read the MCP security basics.

Claude Code expands environment variables inside `.mcp.json`, so you commit a
reference and each person supplies the actual value from their own environment.

Two forms are supported:

- `${VAR}` expands to the value of the environment variable `VAR`.
- `${VAR:-default}` expands to `VAR` if it is set, otherwise uses `default`.

Expansion works in the `command`, `args`, `env`, `url`, and `headers` fields.
That covers both a bearer token on a remote server and a key passed to a local
server's environment:

```json
{
  "mcpServers": {
    "api-server": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.example.com}/mcp",
      "headers": {
        "Authorization": "Bearer ${API_KEY}"
      }
    },
    "db": {
      "command": "npx",
      "args": ["@acme/db-mcp-server"],
      "env": {
        "DATABASE_URL": "${DATABASE_URL}"
      }
    }
  }
}
```

The file names `API_KEY` and `DATABASE_URL`, but the values stay on each machine.
The `${API_BASE_URL:-...}` default lets one teammate point at a staging host
without editing the shared file.

If a referenced variable has no value and no default, Claude Code fails to parse
the config rather than connecting with a blank credential. That failure is the
correct outcome. It tells the teammate to set the variable.

## Where teammates set the values

The shared file declares which variables exist. Each person sets them once,
locally, in whatever way suits their shell or secret store. A direct export
works for a quick start:

```bash
export API_KEY="sk-the-real-value"
export DATABASE_URL="postgres://localhost:5432/app"
```

For something durable, teams keep these in a `.env` file that is listed in
`.gitignore`, or in a secret manager that injects them into the shell. The rule
is the same either way. The value never enters a tracked file. Add the patterns
that hold secrets to `.gitignore` so they cannot be committed by accident:

```bash
echo ".env" >> .gitignore
echo ".env.local" >> .gitignore
```

A short note in your `docs/onboarding.md` listing the variables each server
needs saves every new hire from reverse-engineering the config.

## Inspect and remove shared servers

These commands work the same for project-scoped servers as for any other:

```bash
claude mcp list
claude mcp get linear
claude mcp remove linear
```

`claude mcp get linear` prints the resolved config for one server, which is the
quick way to confirm a variable expanded the way you expected. `claude mcp
remove linear` deletes it from `.mcp.json`, and you commit that removal so it
leaves everyone's setup at the same time.

## Precedence when scopes collide

A teammate might already have a personal server with the same name as one in the
committed file. Claude Code connects to each server once, using the definition
from the highest-precedence source. It does not merge fields across scopes; the
winning entry is used whole. The order is:

1. Local scope
2. Project scope
3. User scope

So a personal local-scoped `linear` overrides the shared project-scoped `linear`
for that one person. This is useful when someone needs to point at a fork or a
local build while the team stays on the shared definition. It also explains a
common puzzle. When a teammate reports that their server behaves differently,
check whether they have a local or user entry shadowing the shared one.

## A checklist for a clean shared setup

- [ ] Add team servers with `--scope project` so they land in `.mcp.json`.
- [ ] Commit `.mcp.json` to version control.
- [ ] Reference every secret with `${VAR}`, never a literal value.
- [ ] Add `.env` and similar secret files to `.gitignore`.
- [ ] Document which environment variables each server needs.
- [ ] Confirm a fresh clone prompts for approval and connects after the
      variables are set.

Get these right and onboarding a teammate to your tools is one `git pull`, a few
exported variables, and one approval prompt. The next stop is wiring those
servers into repeatable workflows: see [Claude Code workflows](/guides/claude-code-workflows).
