On this page
Lesson 10 of 30

Lesson 09: MCP Servers

What Is MCP?

MCP (Model Context Protocol) is an open standard that lets Claude connect to external tools, data sources, and services. Think of MCP servers as plugins that extend what Claude Code can do beyond its built-in capabilities.

Without MCP, Claude can:

  • Read and write files in your project
  • Run shell commands
  • Search your codebase

With MCP, Claude can also:

  • Query your actual database with natural language
  • Create GitHub issues and pull requests
  • Monitor errors in Sentry
  • Read your Slack messages and send drafts
  • Access your Jira, Linear, or Asana tickets
  • Integrate with Figma designs
  • Connect to hundreds of other tools and APIs
You ←→ Claude Code (MCP Client) ←→ MCP Server ←→ External Service

An MCP server exposes tools (functions Claude can call) and optional resources (data Claude can read). Claude sees MCP tools alongside its built-in tools and decides when to use them based on your requests.


Adding MCP Servers with the CLI

The claude mcp add command is the primary way to connect MCP servers. There are three transport types depending on where the server runs.

HTTP is the recommended transport for cloud-based MCP servers. Most hosted services use this:

Bash
# Basic syntax
claude mcp add --transport http <name> <url>

# Connect to Notion
claude mcp add --transport http notion https://mcp.notion.com/mcp

# Connect to Sentry for error monitoring
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

# Connect to GitHub
claude mcp add --transport http github https://api.githubcopilot.com/mcp/

# With a Bearer token for authentication
claude mcp add --transport http secure-api https://api.example.com/mcp \
  --header "Authorization: Bearer your-token"

Adding a Remote SSE Server (Deprecated)

SSE (Server-Sent Events) is an older transport. Use HTTP instead where available:

Bash
# Basic syntax
claude mcp add --transport sse <name> <url>

# With an API key header
claude mcp add --transport sse private-api https://api.company.com/sse \
  --header "X-API-Key: your-key-here"

Adding a Local stdio Server

Stdio servers run as local processes on your machine. They are ideal for tools that need direct system access:

Bash
# Basic syntax
claude mcp add [options] <name> -- <command> [args...]

# Add a PostgreSQL database server
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
  --dsn "postgresql://readonly:pass@localhost:5432/mydb"

# Add Airtable with an environment variable
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \
  -- npx -y airtable-mcp-server

# Add a custom local server
claude mcp add --transport stdio my-tools -- node /path/to/my-server.js

Important: Option ordering. All flags (--transport, --env, --scope, --header) must come before the server name. The -- separates the server name from the command that launches the MCP server process. This prevents conflicts between Claude's flags and the server's flags.

Windows users: On native Windows (not WSL), local MCP servers using npx require the cmd /c wrapper. Without it, you will get "Connection closed" errors.

Bash
claude mcp add --transport stdio my-server -- cmd /c npx -y @some/package

Adding from JSON Configuration

If you have a JSON configuration (for example, from documentation or a teammate), add it directly:

Bash
# HTTP server from JSON
claude mcp add-json weather-api '{"type":"http","url":"https://api.weather.com/mcp","headers":{"Authorization":"Bearer token"}}'

# stdio server from JSON
claude mcp add-json local-tools '{"type":"stdio","command":"/path/to/server","args":["--config","prod"],"env":{"API_KEY":"abc123"}}'

Importing from Claude Desktop

If you already have MCP servers configured in Claude Desktop, import them:

Bash
# Interactive dialog to select which servers to import
claude mcp add-from-claude-desktop

This reads the Claude Desktop configuration file and lets you select which servers to bring over.


Managing MCP Servers

Once configured, manage your servers with these commands:

Bash
# List all configured servers
claude mcp list

# Get details for a specific server
claude mcp get github

# Remove a server
claude mcp remove github

# Reset project approval choices (for .mcp.json servers)
claude mcp reset-project-choices

Inside a Claude Code session, use the /mcp command to see all server statuses, authenticate with OAuth servers, and troubleshoot connection issues:

> /mcp

Configuration Scopes and File Locations

MCP servers can be configured at three scope levels using the --scope flag:

Scope Flag Stored In Use Case
Local (default) --scope local ~/.claude.json (under project path) Personal servers for this project only
Project --scope project .mcp.json in project root Team-shared servers (commit to version control)
User --scope user ~/.claude.json Personal servers across all projects
Bash
# Add to local scope (default — only you, only this project)
claude mcp add --transport http stripe https://mcp.stripe.com

# Add to project scope (shared with team via .mcp.json)
claude mcp add --transport http paypal --scope project https://mcp.paypal.com/mcp

# Add to user scope (available in all your projects)
claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic

The `.mcp.json` File

Project-scoped servers are stored in .mcp.json at your project root. This file is designed to be committed to version control so your whole team gets the same MCP tools:

JSON
{
  "mcpServers": {
    "project-db": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@bytebase/dbhub", "--dsn", "postgresql://localhost/myproject"],
      "env": {}
    },
    "company-api": {
      "type": "http",
      "url": "${API_BASE_URL:-https://api.company.com}/mcp",
      "headers": {
        "Authorization": "Bearer ${API_KEY}"
      }
    }
  }
}

Notice the environment variable expansion.mcp.json supports ${VAR} and ${VAR:-default} syntax in command, args, env, url, and headers fields. This lets you share configuration while keeping secrets in each developer's environment.

Scope Precedence

When servers with the same name exist at multiple scopes, local takes priority over project, which takes priority over user. This lets personal configurations override shared ones.


OAuth Authentication

Many remote MCP servers require authentication. Claude Code supports OAuth 2.0 for secure connections.

Standard OAuth Flow

For servers that support dynamic client registration, the flow is simple:

Bash
# 1. Add the server
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

# 2. Inside Claude Code, authenticate
> /mcp
# Select "Authenticate" for the server — your browser opens for login

Authentication tokens are stored securely and refreshed automatically. Use "Clear authentication" in the /mcp menu to revoke access.

Pre-Configured OAuth Credentials

Some servers require you to register an OAuth app first. If you see "Incompatible auth server: does not support dynamic client registration," you need to provide credentials manually:

Bash
# Register an app in the server's developer portal, then:
claude mcp add --transport http \
  --client-id your-client-id --client-secret --callback-port 8080 \
  my-server https://mcp.example.com/mcp

The --client-secret flag prompts for the secret with masked input. For CI environments, set it via environment variable:

Bash
MCP_CLIENT_SECRET=your-secret claude mcp add --transport http \
  --client-id your-client-id --client-secret --callback-port 8080 \
  my-server https://mcp.example.com/mcp

You can also use claude mcp add-json with an oauth object:

Bash
claude mcp add-json my-server \
  '{"type":"http","url":"https://mcp.example.com/mcp","oauth":{"clientId":"your-client-id","callbackPort":8080}}' \
  --client-secret

The client secret is stored securely in your system keychain or a credentials file, never in your config files.


Here are some high-value MCP servers to consider:

GitHub — Code Reviews and Issue Management

Bash
claude mcp add --transport http github https://api.githubcopilot.com/mcp/

Then in Claude Code:

> "Review PR #456 and suggest improvements"
> "Create a new issue for the authentication bug we found"
> "Show me all open PRs assigned to me"

PostgreSQL — Database Queries

Bash
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
  --dsn "postgresql://readonly:pass@localhost:5432/analytics"

Then in Claude Code:

> "What's our total revenue this month?"
> "Show me the schema for the orders table"
> "Find customers who haven't purchased in 90 days"

Sentry — Error Monitoring

Bash
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

Then authenticate with /mcp and ask:

> "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?"

Puppeteer — Browser Automation

Bash
claude mcp add --transport stdio puppeteer -- npx -y @modelcontextprotocol/server-puppeteer

Claude can take screenshots, fill forms, and click buttons in a real browser.

Filesystem — Extended File Access

Bash
claude mcp add --transport stdio filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/allow

Provides more powerful file access than Claude Code's built-in file tools, scoped to specific directories.

Need more? Find hundreds of community MCP servers on GitHub, or check the MCP server registry built into the official documentation.


Using MCP Resources

MCP servers can expose resources that you reference with @ mentions, similar to how you reference files:

> Can you analyze @github:issue://123 and suggest a fix?
> Compare @postgres:schema://users with @docs:file://database/user-model

Type @ in your prompt to see available resources from all connected servers. Resources are automatically fetched and included as context.


Using Claude Code as an MCP Server

Claude Code itself can act as an MCP server for other applications:

Bash
# Start Claude Code as a stdio MCP server
claude mcp serve

Add it to Claude Desktop's configuration file:

JSON
{
  "mcpServers": {
    "claude-code": {
      "type": "stdio",
      "command": "claude",
      "args": ["mcp", "serve"],
      "env": {}
    }
  }
}

This gives other MCP clients access to Claude Code's tools (file editing, searching, and so on).


Security Considerations

MCP servers have real access to real systems. Follow these practices:

  • Audit before installing. Use third-party MCP servers at your own risk. Anthropic has not verified the correctness or security of all community servers. Be especially careful with servers that fetch untrusted content — these can expose you to prompt injection risk.
  • Scope database access. Create read-only database users for Claude. Never give Claude write access to production data unless you have reviewed the tools it exposes.
  • Use environment variables for secrets. Never hardcode API keys in .mcp.json files that get committed to version control. Use ${VAR} expansion syntax instead.
  • Review tool permissions. A tool named runArbitrarySQL is far more dangerous than queryReadOnly. Understand what each MCP server's tools can do.
  • Project-scoped server approval. Claude Code prompts for approval before using servers from .mcp.json files. This prevents malicious repositories from automatically connecting to arbitrary services.
  • Managed configuration for organizations. Administrators can deploy a managed-mcp.json file to control exactly which MCP servers are available, or use allowlists and denylists to set policy.

Debugging MCP Connections

When an MCP server is not working, use these steps to diagnose the problem:

Check Server Status

Inside Claude Code, run /mcp to see which servers are connected, failed, or degraded. This is your first diagnostic tool.

Common Issues and Fixes

Problem Cause Solution
"Connection closed" on Windows Windows cannot execute npx directly Use cmd /c wrapper: -- cmd /c npx -y @some/package
Server times out on startup Slow npm install or network Increase timeout: MCP_TIMEOUT=10000 claude
"Connection failed" error Wrong command path or missing dependency Verify the command works manually in your terminal
OAuth authentication fails Browser did not open or token expired Run /mcp, select the server, choose "Authenticate"
Output truncation warnings MCP tool returned too much data Set MAX_MCP_OUTPUT_TOKENS=50000 or configure the server to paginate
Tools not appearing Server connected but tools not loaded Check if Tool Search is active (auto-enabled when tools exceed 10% of context)

Verify Your Configuration

Bash
# Check what is configured
claude mcp list

# Inspect a specific server's configuration
claude mcp get my-server

# Remove and re-add a problematic server
claude mcp remove my-server
claude mcp add --transport http my-server https://example.com/mcp

Test stdio Servers Manually

For local stdio servers, verify the command works outside of Claude Code:

Bash
# Does the command run at all?
npx -y @modelcontextprotocol/server-postgres postgresql://localhost/mydb

# Check for missing dependencies
which npx
node --version

Environment Variable Tips

  • Use absolute paths in configuration and .env files — the working directory for MCP server processes may be undefined.
  • For stdio servers, messages logged to stderr are captured by Claude Code for debugging. Servers should never log to stdout as that interferes with the MCP protocol.
  • Set MCP_TIMEOUT to increase the startup timeout (default is a few seconds; set to milliseconds like 10000 for 10 seconds).

Practical Exercise

  1. Add a remote server. Connect to GitHub with HTTP transport:
    Bash
    claude mcp add --transport http github https://api.githubcopilot.com/mcp/
  2. Authenticate. Open Claude Code and run /mcp, then authenticate with GitHub in your browser.
  3. Use it. Ask Claude: "List my open GitHub issues and summarize the most urgent ones."
  4. Check status. Run /mcp again to see the server's connection status and available tools.
  5. Try a database. If you have a local PostgreSQL database, connect it:
    Bash
    claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
      --dsn "postgresql://localhost/mydb"
    Then ask Claude: "Show me all tables in the database and describe the schema."

Notice how Claude interacts with external services naturally, without you needing to copy-paste data or switch between tools.