Connect AI clients

How to add MCP servers to Claude Code

Adding an MCP server to Claude Code takes one command. The parts worth getting right are where the server gets saved and where its key ends up.

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

New to MCP? What is an MCP server? covers the basics first.

You'll add a remote server and a local one with claude mcp, the subcommand Claude Code uses to manage servers. You can edit the config files by hand, 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 someone else runs at a URL. Give Claude Code the transport, a name and the URL:

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

DeepWiki answers questions about GitHub repositories and needs no key, so it's a good first test. Claude Code prints a line saying which config the server 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 MCP project's reference server. Its test tools are handy for checking the setup before you add a real server.

The -- matters. Without it, Claude Code would try to read the server's own flags (-y here) as its options.

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 also writes the key into a config file in plain text. Step 4 avoids 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 project for servers the whole team should get when they clone the repo. For servers only you need, local keeps them to one repository and user loads them everywhere.

This is the .mcp.json that --scope project wrote when I added both servers above. 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"
      }
    }
  }
}

Claude Code asks before it uses a server from a .mcp.json it hasn't seen, so cloning a repository can't start processes on your machine without you saying yes. Until you approve, claude mcp list shows the server as ⏸ Pending approval, and claude mcp reset-project-choices clears past decisions. The 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, and how you pass it 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's acceptable in local and user scope, which live in your home directory, but not in a .mcp.json you commit.

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 tool count. You can also log in to OAuth servers there, or 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

Set up this way, Claude Code sees every tool each server offers, and nothing records which calls it made. Every MCP client starts out that 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 now have a remote server and a local one, with keys kept out of anything you commit.

Where to go next: