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 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:
claude mcp add --transport http deepwiki https://mcp.deepwiki.com/mcpDeepWiki 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:
claude mcp add everything -- npx -y @modelcontextprotocol/server-everythingserver-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:
claude mcp add my-server -e API_KEY=xxx -- npx my-mcp-serverThat 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:
| Scope | Loads in | Shared with your team | Stored in |
|---|---|---|---|
local | This project only | No | ~/.claude.json |
project | This project only | Yes, through version control | .mcp.json in the project root |
user | All your projects | No | ~/.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:
{
"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:
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:
{
"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:
claude mcp listEach 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:
claude mcp get deepwikideepwiki:
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 projectNow 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:
claude mcp remove deepwiki -s projectIf 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:
claude mcp add --transport http github http://127.0.0.1:7777/github/mcpNo 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:
- Set up MCP servers in Cursor uses the same servers in a different client.
- Build an MCP server in Python or in TypeScript if the server you need does not exist yet.
- Turn an OpenAPI spec into an MCP server if you already have an API.
- Give an AI agent read-only GitHub access for the first server most teams connect.