Intermediate 12 min

Configure MCP Servers in Claude Code

Complete guide to installing, configuring and using MCP (Model Context Protocol) servers with Claude Code. Connect your external tools directly to Claude.

MCP configuration tools servers

What is MCP?

The Model Context Protocol (MCP) is an open protocol created by Anthropic that lets Claude Code connect to external services: databases, APIs, SaaS tools, remote filesystems. Instead of copy-pasting data into your prompt, Claude Code queries your tools directly through MCP.

In practice, MCP turns Claude Code into a central hub. You say “create a Notion page with a summary of this GitHub PR”, and it does it by calling the Notion and GitHub MCP servers, without you ever leaving your terminal.

The protocol is open source, documented at modelcontextprotocol.io, and the server ecosystem is growing fast. There are official and community servers for most tools you already use.

How MCP works in Claude Code

The architecture is straightforward: Claude Code acts as an MCP client. It connects to one or more MCP servers, each exposing tools and resources.

┌─────────────┐     stdio/SSE     ┌──────────────────┐
│ Claude Code  │ ◄──────────────► │  MCP Server      │
│ (client)     │                   │  (e.g. Notion)   │
└─────────────┘                   └──────────────────┘
       │            stdio/SSE     ┌──────────────────┐
       └──────────────────────► │  MCP Server      │
                                  │  (e.g. GitHub)   │
                                  └──────────────────┘

Each MCP server exposes a list of tools that Claude Code can call. For example, a Notion server exposes tools like notion-search, notion-create-pages, notion-update-page. Claude Code sees these available tools and uses them when relevant to your request.

Two transport modes exist:

  • stdio: the server runs as a local process. Claude Code communicates with it via stdin/stdout. This is the most common and simplest mode.
  • SSE (Server-Sent Events): the server runs remotely, accessible via HTTP. Useful for shared team servers or hosted services.

Configuration

MCP configuration lives in a JSON file, at two levels:

  • .mcp.json at the project root: shared with your team, versioned in Git
  • ~/.claude/mcp.json in your home directory: global, personal, active across all your projects

File structure

Here is the basic structure of a .mcp.json file:

{
  "mcpServers": {
    "server-name": {
      "command": "command-to-start-server",
      "args": ["arg1", "arg2"],
      "env": {
        "API_KEY": "your-key"
      }
    }
  }
}

Each entry in mcpServers defines a server with:

  • command: the executable to run (often npx, node, python, uvx)
  • args: arguments passed to the command
  • env: environment variables (API tokens, secret keys)

Real-world example: a project with Notion and GitHub

{
  "mcpServers": {
    "notion": {
      "command": "npx",
      "args": ["-y", "@notionhq/notion-mcp-server"],
      "env": {
        "OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer ntn_your_token\",\"Notion-Version\":\"2022-06-28\"}"
      }
    },
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token"
      }
    }
  }
}

Project vs global: what goes where?

.mcp.json (project)~/.claude/mcp.json (global)
Servers tied to the project (project database, business API)Personal servers (calendar, notes, email)
Tokens shared with the team (or referenced via env vars)Your personal tokens
Versioned in GitNever versioned

Installing MCP servers

Using the claude mcp add command

The fastest method. Claude Code provides a dedicated command:

# Add a server to the project (writes to .mcp.json)
claude mcp add notion -s project -- npx -y @notionhq/notion-mcp-server

# Add a global server (writes to ~/.claude/mcp.json)
claude mcp add github -s user -- npx -y @modelcontextprotocol/server-github

# Add with environment variables
claude mcp add notion -s project \
  -e OPENAPI_MCP_HEADERS='{"Authorization":"Bearer ntn_xxx","Notion-Version":"2022-06-28"}' \
  -- npx -y @notionhq/notion-mcp-server

Key options:

  • -s project: project scope (.mcp.json)
  • -s user: global scope (~/.claude/mcp.json)
  • -e KEY=value: environment variable
  • --: separator before the server command

Managing servers

# List configured servers
claude mcp list

# Remove a server
claude mcp remove notion

# View server details
claude mcp get notion

Manual configuration

You can also edit the .mcp.json file directly. This is often more practical for complex configurations or when copying an existing config.

SSE transport

For a remote server accessible via HTTP:

{
  "mcpServers": {
    "my-remote-server": {
      "type": "sse",
      "url": "https://mcp.example.com/sse",
      "headers": {
        "Authorization": "Bearer your-token"
      }
    }
  }
}

Filesystem

Lets Claude Code read and write files outside the working directory. Useful for accessing shared configs, assets, or other projects.

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y", "@modelcontextprotocol/server-filesystem",
        "/path/to/allowed-directory",
        "/another/directory"
      ]
    }
  }
}

The paths passed as arguments define the allowed scope. The server denies any access outside these directories.

GitHub

Full access to the GitHub API: issues, pull requests, repos, files, reviews.

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token"
      }
    }
  }
}

Example prompts once configured:

  • “List open issues with the bug label”
  • “Create a PR with these changes”
  • “Summarize the comments on PR #42”

Notion

The official Notion server gives access to databases, pages, and blocks.

{
  "mcpServers": {
    "notion": {
      "command": "npx",
      "args": ["-y", "@notionhq/notion-mcp-server"],
      "env": {
        "OPENAPI_MCP_HEADERS": "{\"Authorization\":\"Bearer ntn_your_token\",\"Notion-Version\":\"2022-06-28\"}"
      }
    }
  }
}

To get the token: create an internal integration at notion.so/my-integrations, then share the relevant pages and databases with that integration.

Google Calendar

{
  "mcpServers": {
    "google-calendar": {
      "command": "npx",
      "args": ["-y", "@anthropic/claude-google-calendar-mcp"],
      "env": {
        "GOOGLE_CLIENT_ID": "your-client-id",
        "GOOGLE_CLIENT_SECRET": "your-client-secret",
        "GOOGLE_REDIRECT_URI": "http://localhost:3000/callback",
        "GOOGLE_REFRESH_TOKEN": "your-refresh-token"
      }
    }
  }
}

PostgreSQL and databases

{
  "mcpServers": {
    "postgres": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "POSTGRES_CONNECTION_STRING": "postgresql://user:password@localhost:5432/mydb"
      }
    }
  }
}

Other database servers exist: SQLite, MySQL, MongoDB. The full list is at github.com/modelcontextprotocol/servers.

Other notable servers

  • Puppeteer (@modelcontextprotocol/server-puppeteer): web navigation, screenshots, scraping
  • Brave Search (@modelcontextprotocol/server-brave-search): web search
  • Slack (@modelcontextprotocol/server-slack): messages, channels
  • Google Drive (@modelcontextprotocol/server-gdrive): Google Drive files
  • Memory (@modelcontextprotocol/server-memory): persistent memory across sessions

Creating a custom MCP server

If no existing server covers your use case, you can build your own. The official SDK is available in TypeScript and Python.

Minimal TypeScript example

npm install @modelcontextprotocol/sdk
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";

const server = new McpServer({
  name: "my-server",
  version: "1.0.0",
});

// Declare a tool
server.tool(
  "get-status",
  "Retrieve the service status",
  {
    serviceId: z.string().describe("The service identifier"),
  },
  async ({ serviceId }) => {
    // Your logic here
    const status = await fetchServiceStatus(serviceId);
    return {
      content: [
        {
          type: "text",
          text: JSON.stringify(status, null, 2),
        },
      ],
    };
  }
);

// Start the server in stdio mode
const transport = new StdioServerTransport();
await server.connect(transport);

Minimal Python example

pip install mcp
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-server")

@mcp.tool()
def get_status(service_id: str) -> str:
    """Retrieve the service status."""
    status = fetch_service_status(service_id)
    return str(status)

if __name__ == "__main__":
    mcp.run(transport="stdio")

Then reference your server in .mcp.json:

{
  "mcpServers": {
    "my-server": {
      "command": "node",
      "args": ["./mcp-servers/my-server/dist/index.js"]
    }
  }
}

Or for the Python version:

{
  "mcpServers": {
    "my-server": {
      "command": "python",
      "args": ["./mcp-servers/my-server/server.py"]
    }
  }
}

Debugging MCP servers

The most common problems and how to fix them.

Server does not start

Verify that the command works manually in your terminal:

# Test an npx server
npx -y @modelcontextprotocol/server-github

# If this fails, it is an installation issue, not an MCP issue

Common causes:

  • Node.js not installed or version too old
  • npx cache issues: try npx --yes @package/name or clear the npx cache
  • Python not in PATH: use the full path (/usr/bin/python3 or python3)

Missing environment variables

If a server starts but calls fail with authentication errors, check your tokens:

# Verify the variable is properly set
claude mcp get notion

Typical errors:

  • Expired or revoked token
  • Wrong format in OPENAPI_MCP_HEADERS (the JSON must be escaped correctly)
  • Insufficient permissions on the token (missing scopes)

Permission problems

Some servers require specific permissions:

  • Notion: the integration must be shared with each page and database you want to access
  • GitHub: the token needs repo, read:org scopes depending on your needs
  • Filesystem: paths must exist and be readable/writable

Viewing logs

To diagnose a server that is not responding correctly, run Claude Code in verbose mode:

claude --verbose

You will see the exchanges between Claude Code and the MCP servers, which lets you pinpoint exactly where things break.

You can also use the official MCP inspector to test a server in isolation:

npx @modelcontextprotocol/inspector npx -y @modelcontextprotocol/server-github

The inspector opens a web interface where you can list available tools and call them manually.

Best practices

Token security

Never hardcode tokens in a versioned .mcp.json. Two approaches:

Option 1: put .mcp.json in .gitignore

.mcp.json

Simple but prevents sharing the config with your team.

Option 2: system environment variables

Define tokens in your shell profile (~/.bashrc, ~/.zshrc) and reference them:

{
  "mcpServers": {
    "github": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-github"],
      "env": {
        "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
      }
    }
  }
}

Note: the ${VAR} syntax for referencing system environment variables inside .mcp.json is not natively supported by all servers. Prefer using the global config at ~/.claude/mcp.json for personal tokens.

Project vs global scope

Simple rule:

  • Project: anything tied to the project (project database, business API, custom servers)
  • Global: anything personal and cross-project (calendar, notes, email, GitHub if you use it everywhere)

Performance

Each MCP server is a process. A few tips:

  • Only enable the servers you need. 3 to 5 servers is a good maximum for daily use.
  • stdio servers are lighter than SSE servers.
  • If a server is slow to start (common with npx servers that download the package each time), install it globally with npm install -g @package/name and use the direct path in command.
  1. Start with one or two servers (GitHub + your project management tool)
  2. Test that everything works before adding more
  3. Put personal tokens in ~/.claude/mcp.json
  4. Share the structure (without secrets) in the project’s .mcp.json
  5. Document the available servers in your CLAUDE.md so Claude Code knows when to use them
## Available MCP Servers

- **notion**: access to project databases (kanban, docs)
- **github**: issue and PR management
- **postgres**: production database (read-only)

This documentation in CLAUDE.md helps Claude Code pick the right tool at the right time, without you needing to remind it what is available.