Connecting Claude to MCP
The full claude mcp add reference — transports, scopes, authentication, config files — plus Claude Desktop and the Claude API's MCP connector
Connecting Claude to MCP
TL;DR
Claude connects to MCP servers through three distinct surfaces: Claude Code's claude mcp add CLI for terminal-based work, Claude Desktop's config file for the consumer app, and the Claude API's MCP connector for your own application code. Each fits a different situation — this page is the practical reference for all three.
| Property | Value |
|---|---|
| Level | Intermediate |
| Reading time | ~22 minutes |
| Prerequisites | Building Servers & Clients |
| You will understand | The full claude mcp add command surface, and when to reach for each connection method |
Three Surfaces, Three Situations
| Surface | Use when |
|---|---|
Claude Code (claude mcp add) | You're coding in a terminal and want tools available to your agent there |
| Claude Desktop (config file) | You want tools available in the consumer chat app |
| Claude API — MCP connector | Your own application should talk to a remote MCP server directly from a Messages API call, without hosting a client yourself |
The rest of this page works through each in the depth you need to actually use it.
Claude Code: claude mcp add
The base command:
claude mcp add [options] <name> <url-or-command>All four transports
# HTTP — the recommended default for remote servers
claude mcp add --transport http notion https://mcp.notion.com/mcp
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
# SSE — for servers that only offer the older streaming-specific endpoint
claude mcp add --transport sse asana https://mcp.asana.com/sse \
--header "X-API-Key: your-key-here"
# Stdio — local processes. Use `--` to separate Claude's own options
# from the server command; everything after it is passed through untouched.
claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY --transport stdio airtable \
-- npx -y airtable-mcp-server
# WebSocket — only available via add-json, no --transport flag for it
claude mcp add-json events-server \
'{"type":"ws","url":"wss://mcp.example.com/socket","headers":{"Authorization":"Bearer YOUR_TOKEN"}}'The -- separator matters for stdio servers. Everything before it is a claude mcp add option; everything after is handed to the server command as-is. Drop it and Claude may try to interpret the server's own flags as its own.
Scopes: who loads the server, and from where
| Scope | Loads in | Shared with team | Stored in |
|---|---|---|---|
| Local (default) | Current project only | No | ~/.claude.json |
| Project | Current project only | Yes, via .mcp.json | .mcp.json in the project root |
| User | All your projects | No | ~/.claude.json |
claude mcp add --transport http stripe https://mcp.stripe.com
# local scope (default) — just this project, just you
claude mcp add --transport http shared-server --scope project https://example.com/mcp
# project scope — committed to .mcp.json, shared with your whole team
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic
# user scope — available across every project you work inConfig file formats
// .mcp.json (project scope — checked into version control)
{
"mcpServers": {
"shared-server": { "type": "http", "url": "https://example.com/mcp" }
}
}// ~/.claude.json (local/user scope — per-machine, not committed)
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"stripe": { "type": "http", "url": "https://mcp.stripe.com" }
}
}
}
}Authentication, every way it's supported
# OAuth via the interactive /mcp panel
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
# then, inside Claude Code: /mcp → authenticate via browser
# Command-line OAuth
claude mcp login sentry
claude mcp logout sentry # clear stored credentials
# Pre-configured OAuth client credentials
claude mcp add --transport http \
--client-id your-client-id --client-secret --callback-port 8080 \
my-server https://mcp.example.com/mcp
# Static headers — for servers using a simple bearer token or API key
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"For headers that need to be computed rather than static (a token that expires and needs refreshing, for instance), .mcp.json supports a headersHelper script:
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.example.com",
"headersHelper": "/opt/bin/get-mcp-auth-headers.sh"
}
}
}Claude Code runs that script and uses its output as the request headers — useful for internal APIs with their own token-refresh logic.
Environment variable expansion
.mcp.json supports ${VAR} and ${VAR:-default} syntax, so secrets and per-machine values don't need to be hardcoded into a file you might commit:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": { "Authorization": "Bearer ${API_KEY}" }
}
}
}Adding from raw JSON
add-json is the escape hatch for anything the flag-based add command doesn't cover directly — the WebSocket example earlier used it, and it works for any transport:
claude mcp add-json weather-api \
'{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'
claude mcp add-json local-weather \
'{"type":"stdio","command":"/path/to/weather-cli","args":["--api-key","abc123"]}'Managing what's connected
claude mcp list # every configured server
claude mcp get <name> # details for one
claude mcp remove <name> # disconnect it
claude mcp reset-project-choices # reset per-project approval prompts
/mcp # check live status, inside Claude CodeOperational details worth knowing
| Behavior | Detail |
|---|---|
| Dynamic tool updates | Servers can push list_changed notifications — tools update without a reconnect |
| Reconnection | Remote servers (HTTP/SSE/WebSocket) reconnect automatically with exponential backoff; stdio servers do not auto-reconnect |
| Tool output limit | 25,000 tokens by default per tool call, configurable via MAX_MCP_OUTPUT_TOKENS |
| Idle timeout | 5 minutes for HTTP/SSE/WebSocket, 30 minutes for stdio — both configurable via CLAUDE_CODE_MCP_TOOL_IDLE_TIMEOUT |
The 25,000-token output cap is a real production consideration, not a default to raise reflexively. A tool that regularly returns more than that is usually a sign it should paginate or summarize server-side, not that the limit should simply be turned up — see Production & Operations.
Claude Desktop
Claude Desktop reads its own MCP server configuration from a config file, structured similarly to .mcp.json — servers are launched as subprocesses for stdio configurations, or connected to directly for remote HTTP servers. It's the right surface when the goal is tools available in the everyday consumer chat app rather than in a coding workflow.
The Claude API's MCP Connector
For your own application code — not Claude Code, not Claude Desktop — the Messages API can talk to a remote MCP server directly, without you writing a client-side connection loop yourself.
response = client.beta.messages.create(
model="claude-opus-5",
max_tokens=4096,
betas=["mcp-client-2025-11-20"],
mcp_servers=[{"type": "url", "url": "https://mcp.example.com", "name": "example"}],
tools=[{"type": "mcp_toolset", "mcp_server_name": "example"}],
messages=[{"role": "user", "content": "..."}],
)Both halves are required. Declaring mcp_servers alone is rejected as a validation error — you must also declare a tools entry of type mcp_toolset whose mcp_server_name exactly matches the name you gave the server. One without the other doesn't fail silently; the request itself is invalid.
This is the right surface when you're building an application that should reach an MCP server as part of its own backend logic — a workflow, a service, anything that isn't a person typing into Claude Code or Claude Desktop directly.
Concept Checks
Check yourself
You need a server available to your whole team, committed to version control. Which scope, and why?
Project scope, using claude mcp add --scope project. It stores the configuration in .mcp.json in the project root — a file meant to be committed and shared — rather than in ~/.claude.json, which is per-machine and not shared with anyone else on the team.
A stdio-based MCP server's connection drops. What happens, and why does it differ from a remote server?
It does not automatically reconnect — stdio servers require manual intervention or a restart. Remote servers (HTTP, SSE, WebSocket) reconnect automatically with exponential backoff, because they're independent network services designed to be reached repeatedly, whereas a stdio server's lifecycle is tied to the subprocess that spawned it.
Why does the Claude API's MCP connector reject a request that only declares `mcp_servers` without a matching `tools` entry?
Because declaring the server alone doesn't tell Claude it should actually be used as a source of callable tools — the mcp_toolset tool entry is what exposes the server's tools to the model during the request. Without it, the server reference has nothing wired to it, so the API treats the combination as incomplete rather than silently ignoring the unused server declaration.
Key Concepts Recap
| Concept | One-line summary |
|---|---|
| Three connection surfaces | Claude Code (CLI), Claude Desktop (config file), Claude API (MCP connector) |
claude mcp add | The base command, supporting http/sse/stdio transports plus WebSocket via add-json |
| Scopes | Local (default, just you), Project (shared via .mcp.json), User (all your projects) |
| Auth methods | OAuth via /mcp, claude mcp login, pre-configured credentials, static or dynamic headers |
| Env var expansion | ${VAR} / ${VAR:-default} syntax in .mcp.json |
| Output cap | 25,000 tokens default per tool call, MAX_MCP_OUTPUT_TOKENS to adjust |
| Reconnection | Automatic with backoff for remote transports; manual for stdio |
| MCP connector | Needs both mcp_servers and a matching mcp_toolset tool entry |
Next
Beyond the core protocol, MCP defines optional additions worth knowing about: Extensions.
Building Servers & Clients
A worked Python MCP server with tools and a resource, tested with the MCP Inspector, plus what building a client actually involves
Extensions
Tasks, MCP Apps, and the authorization extensions — optional, opt-in additions to the core protocol, and how negotiation actually works