Skip to main content

Model Context Protocol

11 min read

What You’ll Learn

This chapter is all about the Model Context Protocol (MCP), the standard for connecting Claude Code to external tools, databases, and APIs. By the end, you’ll know how MCP servers work, which of the three transport modes to pick for your situation, how to add and configure servers at different scopes, how to share server configs with your team through .mcp.json, and how to troubleshoot connection issues when things go sideways.

What MCP Enables

Model Context Protocol (MCP) is the open standard that connects Claude Code to external tools, databases, APIs, ticketing systems, and documentation, beyond the local filesystem.

MCP lets Claude Code reach beyond your local filesystem. On its own, Claude Code can read files, run shell commands, and search your codebase. Add MCP into the mix, and it can also query a database, create tickets in your project management tool, search a knowledge base, interact with cloud services, or call pretty much any API you connect.

MCP servers expose tools that Claude Code calls just like its built in ones. Connect a PostgreSQL MCP server and Claude Code gains a query tool for running SQL. Hook up a Jira MCP server and it picks up tools for creating and updating tickets. From Claude Code’s perspective, MCP tools work identically to its native file and shell tools. It decides when to use them based on what you’re asking for.

One important distinction: you don’t build MCP servers yourself. Instead, you install and connect existing servers that other developers and organizations have published. This chapter focuses on connecting and configuring servers, not developing them.

Architecture Overview

MCP follows a client server architecture. Claude Code acts as the MCP client, connecting to one or more MCP servers that each provide a set of tools. These servers can run locally on your machine as child processes, or remotely on another host over the network.

MCP architecture: server topology with stdio (local) and HTTP (remote) transports

The diagram above shows how everything fits together. Local servers connect via stdio (standard input/output) and run as child processes of Claude Code. Remote servers connect via HTTP over the network and can live anywhere: on a team server, in the cloud, or behind your corporate firewall. Each server exposes tools that show up in Claude Code’s tool palette right alongside its built in capabilities.

You can connect multiple servers at the same time, and Claude Code handles the connections and routes tool calls to the right server automatically. A typical project might have a local database server (stdio), a remote documentation search server (HTTP), and a cloud API integration (HTTP) all running simultaneously.

Transport Modes

MCP supports three transport protocols, and each one determines how Claude Code talks to the server.

stdio (default for local servers)

With stdio, the server runs as a child process on your machine, and Claude Code communicates with it through stdin and stdout. It’s the simplest transport: no networking, no authentication, no port configuration. Most MCP servers you install locally use stdio by default.

Adding a local stdio server
Adding a local stdio server
# stdio transport (default, no --transport flag needed)
claude mcp add my-tools -- npx @my-org/mcp-tools

The server starts as a child process when Claude Code launches.

Use stdio when the server runs locally, you installed it via npm or downloaded a binary, and only you need access. The server process starts when Claude Code launches and stops when the session ends. No ports get opened and no network traffic leaves your machine.

With HTTP, the server runs on a remote host and communicates via the Streamable HTTP protocol. It supports authentication headers, works across network boundaries, and handles reconnection gracefully. If the server isn’t running locally, HTTP is the way to go.

Adding a remote HTTP server
Adding a remote HTTP server
# HTTP transport for a remote server
claude mcp add docs-server --transport http --url https://mcp.example.com/docs

Reach for HTTP when the server lives on another machine, runs in the cloud, or is shared across a team. It also supports OAuth authentication flows for servers that require user authorization.

HTTP server with API key authentication
HTTP server with API key authentication
# HTTP with custom headers for API key auth
claude mcp add analytics --transport http --url https://mcp.example.com/analytics --header "X-API-Key: your-api-key-here"

SSE (deprecated)

Server Sent Events was the original remote transport for MCP. SSE is explicitly deprecated in favor of HTTP. It still works, but it’ll be removed in a future release. If you’ve got existing SSE server configurations, it’s time to migrate them to HTTP.

SSE transport (deprecated)
SSE transport (deprecated)
# DEPRECATED: use HTTP instead
claude mcp add legacy-server --transport sse --url https://old-server.example.com/events

Migrate existing SSE configurations to HTTP transport.

Don’t use SSE for new servers. If a server only supports SSE, check whether an updated version supports HTTP. If not, SSE will continue to work for now, but plan your migration sooner rather than later.

Adding MCP Servers

The claude mcp add command registers a new MCP server. The basic syntax is: server name, optional flags, a double dash separator, and then the command to start the server.

General syntax
General syntax
claude mcp add <name> [flags] -- <command> [args...]

Here are some common variations.

Common server addition patterns
Common server addition patterns
# Basic local server
claude mcp add postgres -- npx @mcp/postgres postgresql://localhost/mydb
# With environment variables
claude mcp add github --env GITHUB_TOKEN=ghp_xxxxxxxxxxxx -- npx @mcp/github
# Scoped to project (saved in .mcp.json)
claude mcp add project-db --scope project -- npx @mcp/postgres postgresql://localhost/projectdb
# Remote HTTP server with authentication
claude mcp add company-api --transport http --url https://mcp.company.com/api --header "Authorization: Bearer TOKEN_HERE"
# Multiple environment variables
claude mcp add analytics --env API_KEY=xxx --env REGION=us-east-1 -- npx @mcp/analytics

Once you’ve added a server, Claude Code starts it automatically on the next session launch. You can verify the connection with /mcp from within an active session.

Server Scopes

MCP server configurations live at one of three scopes, and the scope determines who can see and use the server.

Local (default) stores the config in ~/.claude.json. The server is available only to you on this machine. Pick this scope for personal tools, local databases, or servers you’re experimenting with.

Project stores the config in .mcp.json at your project root. This file is meant to be committed to Git and shared with your team, so everyone who clones the repo gets the same MCP server configuration. It’s the right choice for team databases, shared documentation servers, or project-specific tools.

User stores the config in your user settings. The server is available to you across all projects on this machine. Use this for personal productivity tools you rely on everywhere.

Setting server scope
Setting server scope
# Local scope (default)
claude mcp add my-tool -- npx @my/tool
# Project scope (creates/updates .mcp.json)
claude mcp add team-db --scope project -- npx @mcp/postgres $DB_URL
# User scope
claude mcp add my-notes --scope user -- npx @mcp/notes

.mcp.json Format

The .mcp.json file at your project root defines project scoped MCP servers. It’s a JSON file with a mcpServers object where each key is a server name and each value contains that server’s configuration.

.mcp.json
.mcp.json
{
"mcpServers": {
"database": {
"command": "npx",
"args": ["@mcp/postgres", "postgresql://localhost/mydb"],
"env": {
"DB_PASSWORD": "${DB_PASSWORD}"
}
},
"docs": {
"command": "npx",
"args": ["@mcp/docs-search", "--index", "./docs"]
},
"cloud-api": {
"type": "http",
"url": "https://mcp.example.com/api",
"headers": {
"Authorization": "Bearer ${API_TOKEN}"
}
}
}
}

Commit this file to Git for team-wide MCP server configuration.

Notice the ${DB_PASSWORD} and ${API_TOKEN} syntax. Environment variables referenced with ${VAR} get expanded at runtime from the developer’s local environment. This means you can safely commit the config file to Git without exposing secrets; each team member just sets the required environment variables locally.

For stdio servers, you’ll specify command and args. For HTTP servers, use type: "http" and url. Both support an env object for passing environment variables to the server process and a headers object for HTTP authentication.

When a team member clones the repo and fires up Claude Code, all project scoped servers defined in .mcp.json start automatically. Each developer only needs to set the required environment variables (like DB_PASSWORD and API_TOKEN in the example above) in their local shell environment.

OAuth Authentication

Some remote MCP servers require OAuth authentication, and Claude Code handles the flow automatically.

Checking MCP server status
Checking MCP server status
/mcp

Shows connected servers, their status, and whether authentication is needed.

When you add a server that requires OAuth, Claude Code opens your browser for the authorization flow the first time you connect. After you authorize, tokens are stored locally and refreshed automatically. You don’t need to manage tokens yourself.

If a token expires and the automatic refresh fails, Claude Code will prompt you to reauthorize through the browser flow. This typically only happens if the server’s OAuth configuration changes or if the refresh token itself expires.

OAuth tokens are stored locally alongside your Claude Code configuration. They’re never committed to Git or shared with team members. Each developer goes through their own authorization flow the first time they connect to an OAuth-protected server.

When your MCP setup includes lots of servers with lots of tools, loading all of them into Claude Code’s context at once eats up a significant chunk of tokens. Tool search solves this by dynamically loading tools only when Claude Code actually needs them.

It kicks in automatically when context usage exceeds roughly 10% of the available window. At that point, Claude Code unloads MCP tools it isn’t actively using and maintains a search index instead. When a later prompt needs a tool that was unloaded, Claude Code searches the index and reloads the relevant tools transparently.

This is entirely automatic. You don’t need to configure or trigger tool search yourself. From your perspective, tools simply show up when Claude Code needs them.

If you want to control this behavior, the ENABLE_TOOL_SEARCH environment variable lets you toggle tool search on or off.

Controlling tool search
Controlling tool search
# Disable tool search (keep all tools loaded)
ENABLE_TOOL_SEARCH=false claude
# Force tool search on (useful for debugging)
ENABLE_TOOL_SEARCH=true claude

Most users never need to set this. The default auto-detection works well.

MCP Resources

Beyond tools, MCP servers can also expose resources. While tools are actions Claude Code can perform (run a query, create a ticket), resources are data sources it can reference (a database table, an API endpoint, a documentation page).

You reference MCP resources using @ mentions in your prompts.

Referencing an MCP resource
Referencing an MCP resource
Tell me about the schema of @database/users

The @ syntax tells Claude Code to fetch data from the MCP resource.

Resources are read only references. They give Claude Code additional context for its reasoning without triggering any tool calls. Not every MCP server exposes resources, as it depends on the server implementation. Check the server’s documentation to see what’s available.

The distinction between tools and resources matters because of what happens when you mention them. Referencing a resource with @ fetches data and adds it to context. Calling a tool executes an operation that may have side effects (inserting a database row, creating a ticket, sending a notification). Claude Code handles the distinction automatically. Just describe what you need and it’ll figure out the rest.

Managed MCP

If your organization needs to control which MCP servers developers can connect to, Claude Code supports managed MCP configuration. An administrator distributes a managed-mcp.json file that defines organizational servers and access policies.

managed-mcp.json
managed-mcp.json
{
"mcpServers": {
"company-db": {
"command": "npx",
"args": ["@company/mcp-db"],
"env": {
"DB_HOST": "db.internal.company.com"
}
}
},
"allowedMcpServers": [
"@company/*",
"@mcp/postgres"
],
"deniedMcpServers": [
"@mcp/shell-exec"
]
}

Distributed by administrators. Users cannot remove managed servers.

allowedMcpServers is a whitelist of server packages that developers are permitted to add. When it’s set, developers can only add servers matching these patterns.

deniedMcpServers is a blocklist of server packages that are explicitly forbidden, regardless of the allow list.

Managed servers (those defined in managed-mcp.json) can’t be removed or modified by individual users. They’re always available and always connected. This gives organizations control over which external integrations their developers use while still allowing approved additions.

Troubleshooting

When MCP servers aren’t behaving as expected, start with the /mcp status command inside an active Claude Code session.

Checking MCP status
Checking MCP status
/mcp

This shows each configured server with its current state: connected (running and responding), errored (started but hit a problem), or disconnected (not running). For errored servers, you’ll also see the error message.

Common Issues

Server not starting. Double check that the command path is correct. If the server is an npm package, make sure it’s installed (npx will auto-install, but network issues can prevent this). Also verify that required environment variables are set.

Debugging server startup
Debugging server startup
# Verify the server command works outside Claude Code
npx @mcp/postgres postgresql://localhost/mydb
# Check environment variables
echo $DB_PASSWORD

Output too large. MCP tools have a maximum output size controlled by MAX_MCP_OUTPUT_TOKENS. If a tool returns more data than this limit allows, the output gets truncated. If you’re seeing incomplete results from an MCP tool, try bumping this limit up.

Increasing MCP output limit
Increasing MCP output limit
# Increase the maximum output size for MCP tools
MAX_MCP_OUTPUT_TOKENS=50000 claude

Default is sufficient for most tools. Increase only if you see truncation.

Server timeout. If a server takes too long to respond, Claude Code times out the request. This usually points to a network issue (for HTTP servers) or a slow operation (for database queries). Check your network connectivity and consider whether the operation can be scoped more narrowly.

Authentication failures. For OAuth servers, try reauthenticating by running /mcp and following the auth flow again. For token based auth, verify that the token is still valid and correctly set in your headers or environment variables.

Tool not appearing. If you added a server but its tools don’t show up, check that the server is connected via /mcp. If tool search is active (see the Tool Search section above), the tools may have been unloaded to save context. They’ll appear automatically when Claude Code determines they’re relevant to your prompt. You can also try explicitly mentioning the tool or server name in your prompt to nudge tool search into reloading it.

Configuration not loading. If you added a server via claude mcp add but it doesn’t show up in your next session, verify the scope matches your expectation. A server added with --scope project only appears when Claude Code runs from that project directory. Check ~/.claude.json for local servers and .mcp.json for project servers.

Best Practices

  • Start with stdio for local development. It’s the simplest transport, requires no configuration, and works for the vast majority of use cases. Only move to HTTP when you need remote access or team sharing.

  • Use .mcp.json for team shared servers. Commit the file to Git so every team member gets the same MCP configuration. Use ${VAR} expansion for secrets to keep credentials out of version control.

  • Use environment variable expansion for secrets. Never hardcode API keys, database passwords, or tokens in .mcp.json. Stick with ${VAR} syntax and document which environment variables each team member needs to set.

  • Prefer HTTP over SSE for remote servers. SSE is deprecated and will be removed. All new remote server configurations should use HTTP transport.

  • Keep your MCP server count manageable. Each connected server and its tools eat into context window space. Only connect the servers you’re actively using for a project, and remove the ones you no longer need.

  • Verify connections with /mcp before relying on tools. After adding or modifying server configurations, check that everything is connected before kicking off a task that depends on MCP tools.

  • Scope servers appropriately. Use local scope for personal experimentation, project scope for team infrastructure, and user scope for personal tools you use across all projects.

Further Reading

Next, learn how to create custom skills that extend Claude Code’s capabilities in Custom Skills.