Claude Code talks to your external tools through the Model Context Protocol, and adding a server takes one command: claude mcp add. Run it with --transport http for a cloud service, or with a -- separator and a launch command for a local process. This guide covers both paths, the three scopes that decide who sees the server, and the errors that keep a server from connecting.
Key Takeaways
- The short answer:
claude mcp add --transport http <name> <url>for a remote server, orclaude mcp add <name> -- <command> [args]for a local stdio process. - Scope decides reach.
local(default) is private to you in one project,projectships in a committed.mcp.jsonfor your team, anduserfollows you across every project. - The
--separator is mandatory for stdio servers. Everything after it runs the server; without it Claude Code reads the server's own flags as its own. - Check the result with
claude mcp list, which prints a live health status such as✔ Connectedor✘ Failed to connectnext to each server. - Remote servers that need sign-in use OAuth. Run
/mcpinside a session, orclaude mcp login <name>from your shell.
What You Need Before You Start
A recent Claude Code install (the scope and status behaviour here assumes a current v2.x build) and a terminal in the project you want the server available in.
You also need one thing about the server itself: either a URL for a remote server, or a launch command such as npx -y some-mcp-server for a local one. If you built the server yourself, for example a TypeScript MCP server with the official SDK, that launch command is how Claude Code starts it.
How to Add an MCP Server to Claude Code
Pick the option that matches what you have (a URL or a command), then verify. You can finish from this section alone.
- Add a remote HTTP server. HTTP is the recommended transport for cloud services, per the Claude Code MCP reference. Pass the endpoint URL:
claude mcp add --transport http notion https://mcp.notion.com/mcp - Send an auth header when the server needs a static token. Use
--header(short form-H):
Claude Code saves the config without validating the token, so a bad value is accepted here and surfaces as a failed connection later.claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \ --header "Authorization: Bearer YOUR_GITHUB_PAT" - Add a local stdio server, with the
--separator. Everything after--is the command that starts the server. Pass any environment variables with--env(or-e) before the--:claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \ -- npx -y airtable-mcp-server - Choose a scope if the default is wrong. Add
--scope projectto share the server with your team through a committed file, or--scope userto make it available in all your projects:claude mcp add --transport http shared-server --scope project https://example.com/mcp - Verify the connection. List every server with its health status:
Aclaude mcp list claude mcp get notion✔ Connectedline means the tools are live. Inside a session, run/mcpto see tool counts and reconnect controls. - Sign in if the server requires OAuth. A server that returns
401or403shows as needing authentication. Authorize it from your shell:
Or openclaude mcp login sentry/mcpinside a session and follow the browser flow.
Which Transport Should You Pick?
The transport is how Claude Code and the server exchange messages, and it has to match what the server actually speaks. The MCP specification defines two standard transports, stdio and Streamable HTTP, and notes that Streamable HTTP replaces the older HTTP+SSE transport from protocol version 2024-11-05.
| Transport | Flag | Use when | Notes |
|---|---|---|---|
| stdio | --transport stdio | The server runs as a local process on your machine | Default when you use -- and a command. Direct system access, no network. |
| HTTP (Streamable HTTP) | --transport http | Connecting to a remote or cloud server | Recommended remote transport. Supports OAuth. In JSON the type accepts streamable-http as an alias for http. |
| SSE | --transport sse | A remote server exposes only a legacy SSE endpoint | Deprecated. Use HTTP where the server offers it. |
| WebSocket | JSON only (type: "ws") | The server pushes events over a persistent socket | No --transport ws flag and no OAuth. Header auth only, via claude mcp add-json. |
If you point --transport http at an SSE-only endpoint, or the reverse, the add succeeds but the server fails to connect. Match the flag to the transport the server documents.
How Do Scopes Decide Who Sees the Server?
Scope controls which projects load the server and whether the config is shared. The three scopes match duplicates by name, and Claude Code connects once, using the highest-precedence definition (local over project over user).
| Scope | Flag | Loads in | Shared with team | Stored in |
|---|---|---|---|---|
| Local | --scope local (default) | Current project only | No | ~/.claude.json |
| Project | --scope project | Current project only | Yes, via version control | .mcp.json in project root |
| User | --scope user | All your projects | No | ~/.claude.json |
Use local scope for a personal or experimental server, or one whose credentials you do not want in version control. Use user scope for a utility you reach for in every repo. Use project scope to standardize tools for a team.
What Does the Committed .mcp.json Look Like?
A project-scoped add writes a standardized file at the project root. Commit it so everyone gets the same tools:
{
"mcpServers": {
"shared-server": {
"type": "http",
"url": "https://example.com/mcp"
}
}
}
Two details save teammates a debugging session. First, a JSON entry with a url but no type is read as a stdio server and skipped, so remote entries must set "type": "http" (or "sse" / "ws"). Second, you can keep secrets out of the file with environment variable expansion, which Claude Code supports in url, headers, command, args, and env:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${API_KEY}" }
}
}
}
The ${VAR:-default} form falls back to default when the variable is unset, which keeps a shared config working on a machine that has not set every value.
How Do You Reuse a Config Written for Another Client?
Setup instructions often ship an mcpServers JSON block written for Claude Desktop or Cursor rather than a claude mcp add command. Pass the object inside mcpServers (not the wrapper) to claude mcp add-json:
claude mcp add-json example '{"command":"npx","args":["-y","@example/mcp-server"]}'
Repair a url entry that lacks a type before you paste it, for the same skip-as-stdio reason described above.
Troubleshooting: Why Is the Server Not Connecting?
Most failures fall into a handful of patterns. Read the status line first, because Claude Code names the cause.
- Claude Code parses the server's flags as its own. This is a missing
--. For a stdio server, put the whole launch command after--so flags like--portreach the server, not the CLI. Also place at least one option between--envand the server name, or the CLI reads the name as anotherKEY=valuepair and rejects it. - The status shows
! Needs authentication. The server returned401or403. Runclaude mcp login <name>or open/mcpand re-authenticate. If you set anAuthorizationheader that the server rejects, Claude Code reports a failed connection instead of falling back to OAuth, so drop the header to use the OAuth flow. Adding OAuth to your own remote server is its own task; see adding OAuth 2.1 authorization to a remote MCP server. - The status shows
⏸ Pending approval. Project-scoped servers from.mcp.jsonwait for your approval in an interactive session. Runclaudein the project to review and approve them. - A remote server reports a
urlbut notype. Claude Code printsMCP server "<name>" has a "url" but no "type"; add "type": "http"and skips it. Add the matchingtypeto the JSON entry. - A pasted token carries hidden whitespace. Claude Code warns with a line such as
Leading or trailing whitespace in: headers.Authorizationand uses the value as written. Edit the config to strip the trailing newline. - Adding the same server twice fails. Running
claude mcp addagain with the same name at the same scope returnsMCP server <name> already exists. Remove it first withclaude mcp remove <name>, or edit the existing entry.
When a server fails and you are not sure whether the fault is the wiring or the server itself, test the server on its own before blaming Claude Code. Running it through the standalone tooling in the MCP Inspector tells you quickly whether the server answers tools/list at all.
What to Do Next
Connect a server that earns its place: a read-only database server so Claude can answer questions against production data without write access, or an issue tracker so it can open PRs from tickets. The Claude Code MCP quickstart walks a first connection end to end.
Treat every server as untrusted until you have read what it does. A server that fetches external content can carry prompt-injection payloads into your session, so review the source or the vendor before you grant it tools.