The premise behind MCP is straightforward: instead of pasting a GitHub issue into the chat, you tell Claude to go read it. Instead of exporting a database query result and uploading it, Claude runs the query directly. Model Context Protocol (MCP) is the open standard that makes this happen — and Claude Code’s MCP support is one of the more capable implementations of it.
This guide covers everything from transport types to enterprise deployment, based on the official Claude Code documentation (v2.1.121+, May 2026). If you want to get past “I’ve heard of MCP” and into production-grade configurations, this is the reference to work through.
What Are MCP Servers in Claude Code
MCP servers are external processes that expose tools, resources, and prompts to Claude Code via a standardized protocol. When a server is connected, Claude can call its tools during a session the same way it calls built-in tools like Bash or Edit.
The model context protocol itself is transport-agnostic — it specifies what messages look like, not how they travel. Claude Code implements three transport types and handles the lifecycle (connecting, reconnecting, tool discovery) automatically.
What you can actually do with MCP connected:
- “Add the feature described in JIRA issue ENG-4521 and open a PR on GitHub” — Claude reads the issue, writes code, and creates the PR without you copy-pasting anything
- “Check Sentry and Statsig to validate the usage of feature ENG-4521” — Claude queries both services and synthesizes the answer
- “Find emails of 10 random users who used this feature” — Claude queries your PostgreSQL database directly
- “Update our email template based on the new Figma designs in Slack” — Claude reads Slack, pulls the Figma content, makes the edits
These aren’t hypothetical. They are example workflows from Anthropic’s own documentation. MCP turns Claude Code from a code editor assistant into an agent that can move across your entire toolchain.
The MCP Directory
Anthropic maintains a curated Directory at claude.ai/directory with reviewed connectors. Any remote server listed there can be added with claude mcp add — no custom installation required. For server development, the official mcp-server-dev plugin scaffolds a new server inside a Claude Code session:
/plugin install mcp-server-dev@claude-plugins-official
/mcp-server-dev:build-mcp-server
Transport Types: stdio, SSE, and HTTP
Claude Code supports three MCP transport types. Choosing the right one matters for security, reliability, and latency.
stdio (Local Process)
Stdio transport launches the MCP server as a child process. Claude Code communicates with it over stdin/stdout. This is the right choice for tools that need direct system access — filesystem operations, local database connections, custom scripts.
# Add a local stdio server
claude mcp add --transport stdio airtable \
--env AIRTABLE_API_KEY=YOUR_KEY \
-- npx -y airtable-mcp-server
The -- separator is required. Everything before it is a flag to claude mcp add. Everything after it is the command that gets executed as the server process. This prevents conflicts when the server itself accepts flags with the same names.
Claude Code sets CLAUDE_PROJECT_DIR in the spawned server’s environment, pointing to the project root. Your server can use process.env.CLAUDE_PROJECT_DIR (Node) or os.environ["CLAUDE_PROJECT_DIR"] (Python) to resolve project-relative paths reliably. In .mcp.json, reference it as ${CLAUDE_PROJECT_DIR:-.} — the default (.) handles cases where the variable isn’t set.
Stdio servers are local processes and are not automatically reconnected if they crash. You need to restart the session or the server manually.
HTTP / Streamable HTTP (Remote Servers)
HTTP transport is the recommended option for cloud-based services. The MCP spec calls this transport streamable-http. In Claude Code’s CLI, you use --transport http. Both names refer to the same thing — the streamable-http alias exists in .mcp.json for compatibility with server documentation that uses the spec name.
# Connect to a remote HTTP MCP server
claude mcp add --transport http notion https://mcp.notion.com/mcp
# With a Bearer token
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
HTTP servers support automatic reconnection with exponential backoff: up to five attempts, starting at one second and doubling each time. If a server disconnects mid-session, Claude Code reconnects silently. Authentication errors and 404s are not retried because they require a configuration fix, not a retry.
As of v2.1.121, initial connection failures (5xx, connection refused, timeout) also retry up to three times before marking the server as failed.
SSE (Deprecated)
SSE (Server-Sent Events) transport works but is deprecated. Use HTTP where available. If you’re connecting to an older server that only exposes SSE:
claude mcp add --transport sse asana https://mcp.asana.com/sse \
--header "X-API-Key: your-key-here"
SSE supports the same automatic reconnection behavior as HTTP.
Transport Comparison
| Transport | Use case | Reconnects? | Auth support |
|---|---|---|---|
stdio | Local tools, custom scripts, system access | No | Environment variables |
http | Cloud services, APIs, remote databases | Yes | OAuth 2.0, Bearer tokens, custom headers |
sse | Legacy servers only (deprecated) | Yes | Headers |
Adding MCP Servers: The Complete CLI Reference
The primary interface for managing MCP servers is claude mcp. Here is the full command set:
# Add servers
claude mcp add --transport http <name> <url>
claude mcp add --transport http <name> --header "Authorization: Bearer TOKEN" <url>
claude mcp add --transport stdio <name> -- <command> [args...]
claude mcp add --transport stdio --env KEY=value <name> -- <command>
claude mcp add-json <name> '<json-config>'
claude mcp add-from-claude-desktop # macOS and WSL only
# Scope flags (default: local)
claude mcp add --scope local ... # current project, private to you
claude mcp add --scope project ... # current project, shared via .mcp.json
claude mcp add --scope user ... # all your projects, private to you
# OAuth flags
claude mcp add --transport http --client-id your-id --client-secret --callback-port 8080 <name> <url>
# Inspect and manage
claude mcp list
claude mcp get <name>
claude mcp remove <name>
claude mcp reset-project-choices # reset approval prompts for .mcp.json servers
# Inside Claude Code
/mcp # show server status, tool count, authenticate
Important flag ordering rule: All options (--transport, --env, --scope, --header) must come before the server name. The -- separator then separates the server name from the command passed to the MCP server. Getting this wrong is one of the most common configuration mistakes.
Correct:
claude mcp add --transport stdio --env KEY=value myserver -- python server.py --port 8080
Incorrect (will fail or misbehave):
claude mcp add myserver --transport stdio -- python server.py
Importing from Claude Desktop
If you already have MCP servers configured in Claude Desktop, you can import them directly:
claude mcp add-from-claude-desktop
This opens an interactive dialog to select which servers to import. It reads the Claude Desktop config file from its standard location (macOS: ~/Library/Application Support/Claude/claude_desktop_config.json). If a server name already exists, the import appends a numeric suffix (e.g., server_1).
Adding via JSON
For complex configurations or scripted setup:
# HTTP server with auth header
claude mcp add-json github \
'{"type":"http","url":"https://api.githubcopilot.com/mcp/","headers":{"Authorization":"Bearer TOKEN"}}'
# Stdio server with environment variables
claude mcp add-json local-db \
'{"type":"stdio","command":"python","args":["/path/to/server.py"],"env":{"DB_URL":"postgresql://..."}}'
# HTTP server with pre-configured OAuth
claude mcp add-json my-server \
'{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-id","callbackPort":8080}}' \
--client-secret
The JSON must match the MCP server configuration schema. The type field accepts http, streamable-http (alias), sse, or stdio.
Configuration Scopes: Local, Project, and User
One of the more important (and frequently misunderstood) parts of Claude Code’s MCP system is scope. Where a server’s configuration is stored determines who has access to it and which projects load it.
Scope Overview
| Scope | Loads in | Shared with team | Stored in |
|---|---|---|---|
local | Current project only | No | ~/.claude.json |
project | Current project only | Yes, via version control | .mcp.json in project root |
user | All your projects | No | ~/.claude.json |
Local Scope (Default)
The default. A local-scoped server is stored in ~/.claude.json under your current project’s path. It is private to you and only appears in the project where you added it.
claude mcp add --transport http stripe https://mcp.stripe.com
# equivalent to:
claude mcp add --transport http stripe --scope local https://mcp.stripe.com
The resulting entry in ~/.claude.json:
{
"projects": {
"/path/to/your/project": {
"mcpServers": {
"stripe": {
"type": "http",
"url": "https://mcp.stripe.com"
}
}
}
}
}
Use local scope for: personal dev servers, experimental configs, servers with credentials you don’t want anywhere near version control.
Project Scope
Project-scoped servers are stored in .mcp.json at the project root. This file is meant to be committed to version control so everyone on the team gets the same MCP tooling automatically.
claude mcp add --transport http paypal --scope project https://mcp.paypal.com/mcp
The resulting .mcp.json:
{
"mcpServers": {
"paypal": {
"type": "http",
"url": "https://mcp.paypal.com/mcp"
}
}
}
Security note: Claude Code prompts for explicit approval before loading a project-scoped server from .mcp.json. This prevents a malicious .mcp.json committed by someone else from silently connecting arbitrary servers. To reset approval choices: claude mcp reset-project-choices.
Environment Variable Expansion in .mcp.json
.mcp.json supports environment variable expansion, which is how you share the configuration without baking in credentials:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
},
"local-tool": {
"type": "stdio",
"command": "${TOOL_PATH:-/usr/local/bin/my-tool}",
"args": ["--config", "${HOME}/.config/tool.json"]
}
}
}
Supported syntax:
${VAR}— expands to the environment variable’s value${VAR:-default}— expands toVARif set, otherwise usesdefault
If a required variable is unset and has no default, Claude Code will fail to parse the config. Keep secrets in .env or your shell environment; never commit actual credential values to .mcp.json.
User Scope
User-scoped servers load in all your projects and are stored in ~/.claude.json. They’re private to your machine, not shared with your team.
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic
Good candidates for user scope: personal API keys for tools you use everywhere (GitHub, Slack, Notion), debugging tools you always want available, servers that help you navigate unfamiliar codebases.
Scope Precedence
When the same server name appears in multiple scopes, Claude Code connects to it once using the highest-precedence definition (the entire entry, not a merge of fields):
- Local scope
- Project scope
- User scope
- Plugin-provided servers
- Claude.ai connectors
This means a local-scoped server can shadow a project-scoped one. If Claude seems to be using the wrong server configuration, check whether a higher-precedence entry exists with claude mcp get <name>.
Popular MCP Servers: Real Setup Examples
GitHub
GitHub’s MCP server is a remote HTTP server that authenticates with a personal access token. Generate a fine-grained token at github.com/settings/personal-access-tokens with access to the repositories Claude needs, then:
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
--header "Authorization: Bearer YOUR_GITHUB_PAT"
What becomes possible:
Review PR #456 and suggest improvements
Create a new issue for the bug we just found
Show me all open PRs assigned to me
Claude can read issue bodies, comment on PRs, create branches, and push commits — all from a natural language prompt.
PostgreSQL / Databases
For database access, the @bytebase/dbhub package provides a stdio server that supports PostgreSQL, MySQL, and other databases:
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:[email protected]:5432/analytics"
Use a read-only database user in production. Giving Claude write access to a production database requires deliberate intent.
Once connected:
What's our total revenue this month?
Show me the schema for the orders table
Find customers who haven't made a purchase in 90 days
Sentry (Error Monitoring)
Sentry provides a remote HTTP MCP server with OAuth authentication:
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
Then authenticate inside Claude Code:
/mcp
Follow the browser OAuth flow. After authenticating:
What are the most common errors in the last 24 hours?
Show me the stack trace for error ID abc123
Which deployment introduced these new errors?
Filesystem
The filesystem MCP server gives Claude access to a local directory. This is most useful for projects where you want Claude to read reference files it can’t find through normal project context:
claude mcp add --transport stdio filesystem \
-- npx -y @modelcontextprotocol/server-filesystem /path/to/allowed/directory
The path argument restricts Claude to that directory. Without explicit path restriction, the server typically defaults to the current working directory.
Slack
claude mcp add --transport http slack https://mcp.slack.com/mcp
Authenticate via /mcp OAuth flow. You can then restrict scopes to only what you need:
{
"mcpServers": {
"slack": {
"type": "http",
"url": "https://mcp.slack.com/mcp",
"oauth": {
"scopes": "channels:read chat:write search:read"
}
}
}
}
The oauth.scopes field pins the requested scopes during authorization. This is the right way to give Claude minimal Slack access when the server advertises broader capabilities.
Browser Automation (Playwright)
claude mcp add --transport stdio playwright -- npx -y @playwright/mcp@latest
Claude can then write and run browser tests, take screenshots, fill forms, and verify UI state. Particularly useful for end-to-end testing workflows where you describe the test scenario in English and Claude implements it.
MCP Prompts as Slash Commands
MCP servers can expose prompts alongside tools. In Claude Code, these surface as / commands, discoverable by typing / in a session. The naming format is /mcp__servername__promptname.
# List pull requests (no arguments)
/mcp__github__list_prs
# Review a specific PR (with arguments)
/mcp__github__pr_review 456
# Create a JIRA issue with title and priority
/mcp__jira__create_issue "Bug in login flow" high
Arguments are space-separated after the command name and parsed according to the prompt’s defined parameters. The result is injected directly into the conversation, the same as if you’d typed the equivalent prompt text manually. Server and prompt names are normalized so that spaces become underscores.
This is worth knowing because some MCP servers expose most of their useful entry points as prompts rather than as raw tools. A server might expose a code_review prompt that bundles a structured review request, while its underlying tools are lower-level. The /mcp__<server>__<prompt> pattern is how you access those higher-level interfaces.
Dynamic Tool Updates and Reconnection
Claude Code supports list_changed notifications from MCP servers. When a server sends one, Claude Code automatically refreshes the available tools, prompts, and resources from that server without requiring you to disconnect and reconnect. This matters for servers whose tool set changes based on state — for example, a server that exposes different tools depending on which project is loaded or which user is authenticated.
For HTTP and SSE servers, reconnection after a mid-session disconnect uses exponential backoff: up to five attempts, starting at one second and doubling each time. The server shows as “pending” in /mcp during reconnection. After five failed attempts it’s marked as failed, and you can retry manually from the /mcp panel.
Initial connection at session startup now also retries (as of v2.1.121): up to three attempts on transient errors (5xx, connection refused, timeout). Authentication errors and 404s are not retried.
If your workflow requires an MCP server’s tools to be present before the first prompt is built — for example, you’re using alwaysLoad: true to pre-load a tool — Claude Code blocks startup until that server connects (capped at the standard 5-second timeout). Other servers continue connecting in the background.
Security Best Practices
MCP substantially expands Claude’s reach. That requires proportional attention to what you’re connecting and how.
Verify Before Connecting
The official docs say it plainly: verify you trust each server before connecting. Servers that fetch external content (any remote HTTP server) can expose you to prompt injection — crafted content that tries to redirect Claude’s actions.
Use the Anthropic Directory as a starting point. Reviewed connectors there have passed Anthropic’s vetting. For servers outside the Directory, review the server’s source code or at minimum check who maintains it and what it has access to.
Scope Credentials Carefully
Use the narrowest credentials that work for the task:
- GitHub: fine-grained PATs with per-repository access, not a classic token with
repo:* - Databases: read-only users for query/analysis workflows; separate write users only if Claude needs to modify data
- Slack: pin OAuth scopes to
channels:read chat:writerather than accepting every scope the server advertises
For any server that touches production data, prefer read-only access by default and upgrade only when you’ve thought through the blast radius.
Use .mcp.json Carefully
.mcp.json is committed to version control and shared with everyone who clones the repo. This means:
- Never put actual credentials in
.mcp.json. Use${ENV_VAR}expansion and document in your README which variables team members need to set. - The approval prompt exists for a reason. If someone else’s PR modifies
.mcp.json, read it before approving. - For servers with sensitive configurations, use local scope instead.
{
"mcpServers": {
"analytics": {
"type": "http",
"url": "${ANALYTICS_MCP_URL}",
"headers": {
"Authorization": "Bearer ${ANALYTICS_API_KEY}"
}
}
}
}
Team members set ANALYTICS_MCP_URL and ANALYTICS_API_KEY in their environment. The .mcp.json file contains no secrets.
headersHelper for Dynamic Authentication
For Kerberos, short-lived tokens, or internal SSO — any authentication scheme that OAuth doesn’t cover — headersHelper runs an arbitrary command at connection time and merges the output into request headers:
{
"mcpServers": {
"internal-api": {
"type": "http",
"url": "https://mcp.internal.example.com",
"headersHelper": "/opt/bin/get-mcp-auth-headers.sh"
}
}
}
The command must write a JSON object of {"Header-Name": "value"} pairs to stdout within 10 seconds. Claude Code sets CLAUDE_CODE_MCP_SERVER_NAME and CLAUDE_CODE_MCP_SERVER_URL in the helper’s environment, so one script can serve multiple servers.
Note: headersHelper executes arbitrary shell commands. When defined at project or local scope, it only runs after you accept the workspace trust dialog.
Restrict OAuth Scopes
When connecting to remote servers that use OAuth, scope down what you’re authorizing:
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://api.githubcopilot.com/mcp/",
"oauth": {
"scopes": "repo:read pull_requests:write issues:write"
}
}
}
}
oauth.scopes takes precedence over what the server’s authorization server advertises. If a tool later returns a 403 insufficient_scope, widen the scopes — but start narrow.
Enterprise: Managed MCP Configuration
For organizations that need centralized control, Claude Code supports a managed-mcp.json that administrators can deploy. This allows setting an approved server list (allowedMcpServers), a denied list (deniedMcpServers), and fixed configurations that users cannot override. Users see a notice when a server they try to add is blocked by policy. See Managed MCP configuration for the full deployment reference.
Troubleshooting Common Issues
Server Won’t Connect
Start with /mcp inside Claude Code. It shows the status of every configured server, the tool count next to each connected server, and flags any server that advertises tools but exposes none.
Common causes:
Server not in PATH: For stdio servers, the command must be executable. If you installed a package globally but it’s not available in Claude Code’s environment, specify the full path:
claude mcp add --transport stdio mytool -- /usr/local/bin/mytool-server
Missing environment variables: For servers that need API keys, pass them explicitly:
claude mcp add --transport stdio airtable --env AIRTABLE_API_KEY=YOUR_KEY -- npx -y airtable-mcp-server
Startup timeout: Default connection timeout is 5 seconds. For slow-starting servers:
MCP_TIMEOUT=30000 claude # 30-second startup timeout
HTTP server 5xx on initial connection: Claude Code v2.1.121+ retries up to three times on transient errors (5xx, connection refused, timeout). If the server is consistently unreachable, check the URL and network.
Authentication Problems
For OAuth-authenticated remote servers, the /mcp panel shows which servers need authentication. Use /mcp to trigger the browser OAuth flow.
If the browser redirect fails after authenticating, copy the full callback URL from your browser’s address bar and paste it into the URL prompt that appears in Claude Code.
If the authentication token expires or becomes invalid:
- Open
/mcp - Select the server
- Choose “Clear authentication” and re-authenticate
Tools Not Appearing
Claude Code uses Tool Search by default — MCP tools are deferred and only load when Claude searches for them. This is intentional and keeps context usage low. From Claude’s perspective, tools work exactly the same; it just uses a search step to discover them.
If you need specific tools to always be present in context (without a search step), set alwaysLoad: true in the server’s configuration:
{
"mcpServers": {
"core-tools": {
"type": "http",
"url": "https://mcp.example.com/mcp",
"alwaysLoad": true
}
}
}
alwaysLoad requires Claude Code v2.1.121+. Use it sparingly — each always-loaded tool consumes context that would otherwise be available for conversation.
To disable Tool Search entirely:
ENABLE_TOOL_SEARCH=false claude
Or in settings.json:
{
"env": {
"ENABLE_TOOL_SEARCH": "false"
}
}
Large Output Warnings
If an MCP tool returns very large results (> 10,000 tokens), Claude Code displays a warning. The default maximum is 25,000 tokens. Raise it if you’re querying large datasets:
export MAX_MCP_OUTPUT_TOKENS=50000
claude
Or set it per-session in settings.json. If you control the server, you can annotate individual tools to raise their limit without requiring users to change the environment variable:
{
"name": "get_schema",
"description": "Returns the full database schema",
"_meta": {
"anthropic/maxResultSizeChars": 200000
}
}
Server Name Conflict
The name workspace is reserved by Claude Code. If you have a server configured with that name, Claude Code will skip it with a warning at startup. Rename it:
claude mcp remove workspace
claude mcp add --transport http my-workspace https://...
Duplicate Servers from Claude.ai
If you’re logged in with a Claude.ai account, connectors you’ve configured there appear automatically in Claude Code. If a locally configured server and a Claude.ai connector point at the same URL, Claude Code uses the local server (higher precedence) and marks the connector as hidden in /mcp. To use the connector instead, remove the local server:
claude mcp remove <name>
FAQ
Can I use MCP servers without an Anthropic API key?
Yes. MCP servers work with any authentication method Claude Code supports — Anthropic API key, Claude.ai subscription (/login), Bedrock, or Vertex AI. Tool Search (deferred tool loading) is disabled by default on Vertex AI due to tool_reference block support differences; you can enable it explicitly with ENABLE_TOOL_SEARCH=true if your Vertex setup supports it (Sonnet 4.5+ or Opus 4.5+).
What’s the difference between local scope and project scope?
Both load only in the current project. The difference is storage and sharing. Local scope stores the config in ~/.claude.json and is private to you. Project scope stores it in .mcp.json in the project directory, which is committed to version control and shared with the team. Use local scope for personal credentials and experiments; use project scope for team-shared tooling where credentials come from environment variables.
How do I know which MCP tools are available in a session?
Type /mcp inside Claude Code for a summary of connected servers and tool counts. Type / to see MCP prompts alongside built-in commands. With Tool Search enabled (the default), Claude discovers individual tools as needed — you don’t need to enumerate them manually.
Is it safe to commit .mcp.json to a public repository?
Only if it contains no secrets. Use environment variable expansion (${API_KEY}) for all credentials and document required variables in your README. The file itself should contain only server URLs, command paths, and variable references. Claude Code will fail to parse it if a required variable is unset, which is safer than silently using wrong credentials.
Can Claude Code itself be used as an MCP server?
Yes. claude mcp serve starts Claude Code in stdio MCP server mode, exposing tools like View, Edit, Bash, and LS. You can connect it to Claude Desktop or any other MCP client:
{
"mcpServers": {
"claude-code": {
"type": "stdio",
"command": "/full/path/to/claude",
"args": ["mcp", "serve"],
"env": {}
}
}
}
Use which claude to get the full path. The claude command may not be in PATH when Claude Desktop launches.
What happens when a remote server disconnects mid-session?
HTTP and SSE servers reconnect automatically with exponential backoff: up to five retries, starting at one second and doubling. The server appears as “pending” in /mcp during reconnection. After five failed attempts, it’s marked as failed — you can retry manually from /mcp. Stdio servers are local processes and are not auto-reconnected.
How do MCP servers interact with Claude Code’s permission system?
MCP tool calls are subject to the same permission system as built-in tools. You can deny specific MCP tools in settings.json:
{
"permissions": {
"deny": ["mcp__github__delete_repository"]
}
}
The format is mcp__<server-name>__<tool-name>. You can also allow tools to skip the confirmation prompt:
{
"permissions": {
"allow": ["mcp__postgres__query"]
}
}
For project-scoped servers in .mcp.json, Claude Code requires explicit approval before loading the server the first time — a separate layer of protection against malicious repository configurations.
MCP is the right abstraction for connecting Claude Code to real systems. The transport layer (stdio vs. HTTP) and scope system (local vs. project vs. user) give you precise control over what Claude can access and who shares that access. The patterns above — scoped credentials, environment variable expansion in .mcp.json, headersHelper for custom auth — are the ones that survive contact with production.
For the broader context of how MCP fits into Claude Code’s overall configuration model, see our guides on AGENTS.md vs CLAUDE.md, Claude Code Hooks, and the best Claude Code skills for 2026.
Keep MCP Credentials Out of Your Config Files
Every MCP server that talks to a real service needs a token or API key. The wrong place for those is .mcp.json — it gets committed, shared, and leaked. 1Password CLI’s op run resolves secrets from your vault at startup and injects them as environment variables, so your config file holds only a reference (${GITHUB_TOKEN}) and the actual value never touches the filesystem. Works with every transport type covered above.