Connect AI clients

How to add MCP servers to Claude Code

Claude Code talks to MCP servers you register with one command. This walks through a remote server, a local one, the three scopes and the credential handling that keeps keys out of your repository.

By
Dan Flanagan
Updated
October 12, 2026
Tested with
Claude Code 2.1.296 on macOS 26.6
Reading time
6 min

By the end of this you will have Claude Code connected to two MCP servers: one remote server it reaches over HTTP, and one local server it starts as a process on your machine. You will also know which file each server lands in, how to give a server an API key without pasting it into a file you commit, and how to check what Claude Code actually loaded.

Everything goes through claude mcp, the subcommand Claude Code uses to manage servers. You can edit the config files by hand too, and I will show what they look like, but the CLI writes the right shape for you.

Prerequisites

  • Claude Code installed. Check the version with claude --version. The steps here were run on 2.1.296.
  • Node.js 20 or later, for the local server example, which runs through npx.
  • A terminal open in the project you want the servers for. Two of the three scopes are tied to the directory you run the command in.

Step 1: Add a remote server over HTTP

A remote server is one that someone else runs at a URL. You give Claude Code the transport, a name and the URL:

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

DeepWiki is a public server that answers questions about GitHub repositories, which makes it a handy first test because it needs no key. Claude Code prints a line confirming the server was added and which config it went into.

The name (deepwiki here) is what Claude Code calls the server in lists and tool names. Pick something short you will recognise.

Use http for remote servers. The older SSE transport is deprecated, and since 2.1.265 Claude Code tries HTTP first and falls back to SSE on its own if a server only speaks the old protocol.

Step 2: Add a local server that runs as a process

A local server, also called stdio, is a program Claude Code starts on your machine and talks to over standard input and output. Everything after -- is the command to run:

bash
claude mcp add everything -- npx -y @modelcontextprotocol/server-everything

server-everything is the reference server from the MCP project. It exposes a set of test tools, so it is useful for checking that the plumbing works before you add something real.

The -- matters. Without it, Claude Code would try to read the server's own flags (-y here) as its options. Anything before -- is for Claude Code, anything after is the server's command line.

If the server needs environment variables, pass them with -e:

bash
claude mcp add my-server -e API_KEY=xxx -- npx my-mcp-server

That works, and it also writes the key into a config file in plain text. Step 4 covers how to avoid that.

Step 3: Pick the scope

Every server is stored in one of three scopes. You choose with --scope (or -s), and the default is local:

ScopeLoads inShared with your teamStored in
localThis project onlyNo~/.claude.json
projectThis project onlyYes, through version control.mcp.json in the project root
userAll your projectsNo~/.claude.json

Use local for servers only you need in one repository, user for servers you want everywhere, and project for servers the whole team should get when they clone the repo.

Here is what --scope project wrote when I added both servers above that way. I passed a test variable with -e DEMO_KEY=abc123 on the second one, so you can see where env lands:

json
{
  "mcpServers": {
    "deepwiki": {
      "type": "http",
      "url": "https://mcp.deepwiki.com/mcp"
    },
    "everything": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-everything"],
      "env": {
        "DEMO_KEY": "abc123"
      }
    }
  }
}

Two things to know about project scope. First, Claude Code asks before it uses a server from a .mcp.json it has not seen, so cloning a repository cannot start processes on your machine without you saying yes. Until you approve, claude mcp list shows the server as ⏸ Pending approval. If you change your mind later, claude mcp reset-project-choices clears those decisions. Second, that prompt only appears in interactive sessions: runs with claude -p load project servers without asking.

If the same name is defined in more than one scope, Claude Code uses one definition and does not merge them. Local wins over project, and project wins over user.

Step 4: Give the server credentials without committing them

Most real servers need a key. There are three ways to hand one over, and the right one depends on the server.

A header, for remote servers that take an API key. Pass it with -H:

bash
claude mcp add --transport http my-api https://example.com/mcp \
  --header "Authorization: Bearer $MY_API_KEY"

Your shell expands $MY_API_KEY before Claude Code sees it, so the literal key still ends up in the config. That is fine for local and user scope, which live in your home directory. It is not fine for .mcp.json.

Environment variable references, for .mcp.json. In a project file, write a reference and let Claude Code expand it when it starts:

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

${VAR} is replaced with the variable's value, and ${VAR:-default} falls back to the default if it is unset. Expansion works in command, args, env, url and headers. Each teammate sets MY_API_KEY in their own shell, and the file you commit has no secret in it.

OAuth, for servers that support it. Add the server with no header, start a session, and run /mcp. Servers that need a login show up there, and Claude Code walks you through the browser flow and stores the token for you.

Step 5: Check what loaded

From the terminal, list everything Claude Code knows about across all scopes. It health-checks each server as it goes:

bash
claude mcp list

Each line shows the name, the URL or command, and a status: ✔ Connected, ! Needs authentication, ✘ Failed to connect, or ⏸ Pending approval for project servers you have not approved yet. For one server in detail:

bash
claude mcp get deepwiki
text
deepwiki:
  Scope: Project config (shared via .mcp.json)
  Status: ⏸ Pending approval (run `claude` to approve)
  Type: http
  URL: https://mcp.deepwiki.com/mcp

To remove this server, run: claude mcp remove deepwiki -s project

Now start a new session with claude and run /mcp. It shows each server's status and how many tools it brought, lets you log in to OAuth servers, and lets you switch a server off without deleting its config.

Start a new session after adding a server. Claude Code reads its server list when a session starts. A session that was already open will not see the new tools, and resuming an old session keeps the list it had.

To remove a server, name its scope:

bash
claude mcp remove deepwiki -s project

If a server takes a long time to start, MCP_TIMEOUT=10000 claude gives it ten seconds. If a tool returns more output than Claude Code allows, MAX_MCP_OUTPUT_TOKENS raises the cap from its default of 25,000 tokens.

Step 6: Put the servers behind Statio

Everything above has the same weakness. Each server gets one credential, Claude Code sees every tool the server offers, and nothing records which calls were made. Every MCP client starts out this way.

With Statio, you install servers once in the dashboard (from the catalog or your own), add the upstream key there, and grant tools one at a time. Claude Code then talks to the Statio desktop app's local proxy instead of to each server, and the proxy attaches your sign-in to every request. The desktop app or mcphub config claude-code writes this for you. By hand it is the same command as Step 1, pointed at the proxy:

bash
claude mcp add --transport http github http://127.0.0.1:7777/github/mcp

No header and no key: the GitHub token lives in Statio, encrypted, and never reaches your laptop. If Claude Code calls a tool you were not granted, the gateway refuses it and the refusal shows up in the audit log next to the calls that went through.

For an agent rather than a person, such as Claude Code running in CI, create the agent under Settings → Agents in Statio, sign it in with mcphub agent login, and run mcphub serve. It serves the same local proxy, signed in as the agent, with only the tools you granted that agent. The client docs have the details.

Conclusion

You added a remote server and a local one, chose where each is stored, passed credentials without putting them in a committed file, and checked what Claude Code loaded with claude mcp list and /mcp.

Where to go next: