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.
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:
claude mcp add --transport http deepwiki https://mcp.deepwiki.com/mcpDeepWiki 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:
claude mcp add everything -- npx -y @modelcontextprotocol/server-everythingserver-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:
claude mcp add my-server -e API_KEY=xxx -- npx my-mcp-serverThat 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:
| 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 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:
{
"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:
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:
{
"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 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:
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
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:
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 now have a remote server and a local one, with keys kept out of anything you commit.
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.