cheat sheet
Claude Code MCP Servers
Add, configure, and build Model Context Protocol (MCP) servers for Claude Code — HTTP, SSE, and stdio transports, management commands, permission rules, and a curated list of useful servers.
Claude Code MCP Servers
What it is
MCP (Model Context Protocol) is an open standard by Anthropic for connecting AI models to external tools, data sources, and resources through a common JSON-RPC interface. Claude Code acts as an MCP client — you register MCP servers that expose additional tools (databases, APIs, GitHub, Slack, custom scripts), and Claude can call them exactly like its built-in tools during a session. Reach for MCP when the built-in Read/Edit/Bash/WebFetch tools are insufficient and you need Claude to interact with proprietary systems or specialized external APIs. The closest alternative is exposing the same functionality via a shell script that the Bash tool calls, which is simpler but lacks structured input schemas and discoverability.
How it works
Without MCP, Claude Code has built-in tools: Read, Edit, Write, Bash, Glob, Grep, WebSearch, WebFetch. With an MCP server, you add arbitrary new tools — databases, APIs, Slack, GitHub, custom scripts — and Claude can call them like any other tool.
Claude Code (MCP client)
↕ MCP protocol (JSON-RPC over stdio / SSE / HTTP)
MCP Server (exposes tools)
↕ native API
Postgres / GitHub / Slack / your service
Each registered server contributes a set of tools that show up alongside the built-ins. Tool names are prefixed mcp__<server-name>__<tool-name> so they cannot collide with built-ins or with each other.
Transport methods
MCP supports three transports. Pick by latency requirements and where the server lives.
| Transport | When to use | Latency | Setup |
|---|---|---|---|
stdio | Local processes, CLI tools | Lowest | Simplest |
sse (Server-Sent Events) | Remote servers, shared team servers | Medium | Needs HTTP server |
http | REST-compatible MCP servers | Medium | Needs HTTP server |
stdio is the default and most common — Claude Code spawns the server as a subprocess and talks JSON-RPC over its stdin/stdout. sse and http are for servers running elsewhere (or shared across a team) and require the server to expose an authenticated HTTP endpoint.
Add a server — CLI
The claude mcp add subcommand registers an MCP server in your user-global config and immediately validates that it starts and lists tools.
# Add a stdio server (local process)
claude mcp add my-server -- node /path/to/server.js
# Add an SSE server (remote)
claude mcp add my-remote-server --transport sse https://mcp.example.com/sse
# Add an HTTP server (remote)
claude mcp add my-http --transport http https://mcp.example.com/rpc
# Add with environment variables
claude mcp add my-db --env DATABASE_URL=postgresql://localhost/mydb -- node /path/to/db-server.js
Output:
✅ Added MCP server "my-server" (8 tools)
The trailing -- separates claude mcp add's own flags from the command to run. Everything after -- is the server command line.
List connected servers
claude mcp list
Output:
my-server stdio node /path/to/server.js ✅ connected (8 tools)
github stdio npx @modelcontextprotocol/server-github ✅ connected (12 tools)
postgres stdio npx @modelcontextprotocol/server-postgres ✅ connected (3 tools)
remote-svc sse https://mcp.example.com/sse ❌ disconnected
Inspect a server's tools
claude mcp tools github
Output:
github exposes 12 tools:
search_repositories(query: string, sort?: string, order?: string)
get_file_contents(owner: string, repo: string, path: string, branch?: string)
create_or_update_file(...)
create_issue(...)
create_pull_request(...)
list_commits(...)
...
Remove a server
claude mcp remove my-server
Output:
Removed MCP server "my-server".
Restart a server
If a server hangs or you change its environment, restart it without exiting Claude Code:
claude mcp restart github
Output:
Restarted "github" (12 tools available).
MCP in settings.json
For team-shared or committed server configs, define them in .claude/settings.json under mcpServers. These are picked up by every session opened in the project.
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
},
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "${DATABASE_URL}"]
},
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/alice/Code"]
},
"remote": {
"type": "sse",
"url": "https://mcp.example.com/sse",
"headers": {
"Authorization": "Bearer ${MCP_API_KEY}"
}
}
}
}
Use
${ENV_VAR}syntax in settings.json to reference environment variables without hardcoding secrets. The value is expanded at runtime from the shell environment that launchedclaude.
Useful MCP servers
The MCP ecosystem ships dozens of community servers. The ones below are the most common.
GitHub
Gives Claude tools to search repos, read files, create issues, open PRs, and review code — all authenticated with your GitHub token.
claude mcp add github -- npx -y @modelcontextprotocol/server-github
Output:
✅ Added MCP server "github" (12 tools)
Required env: GITHUB_PERSONAL_ACCESS_TOKEN
Tools added: create_or_update_file, search_repositories, create_issue, create_pull_request, list_commits, get_file_contents, and more.
PostgreSQL
Read-only access to a Postgres database — schema inspection, query execution, table listings.
claude mcp add postgres -- npx -y @modelcontextprotocol/server-postgres "$DATABASE_URL"
Output:
✅ Added MCP server "postgres" (3 tools)
Tools added: query, list_tables, describe_table.
Example use in-session:
> What are the 5 most recently created users in the database?
Output:
[Calls mcp__postgres__query with: SELECT id, email, created_at FROM users ORDER BY created_at DESC LIMIT 5]
Filesystem (extended)
Extends Claude's file access beyond the current working directory. Useful for referencing shared docs or a monorepo root from a subdirectory.
claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem /path/to/root
Output:
✅ Added MCP server "filesystem" (6 tools)
Fetch (web scraping)
Gives Claude a fetch tool for retrieving web pages as plain text. Useful for pulling documentation from URLs during a session without the limits of WebFetch.
claude mcp add fetch -- npx -y @modelcontextprotocol/server-fetch
Output:
✅ Added MCP server "fetch" (1 tool)
Brave Search
Replaces or complements the built-in WebSearch with Brave Search results, which can be more complete.
claude mcp add brave-search -- npx -y @modelcontextprotocol/server-brave-search
Output:
✅ Added MCP server "brave-search" (1 tool)
Required env: BRAVE_API_KEY (free tier available)
Slack
Read channels, post messages, and search Slack history.
claude mcp add slack -- npx -y @modelcontextprotocol/server-slack
Output:
✅ Added MCP server "slack" (4 tools)
Required env: SLACK_BOT_TOKEN, SLACK_TEAM_ID
Memory (persistent)
Gives Claude a key-value store that persists between sessions. Claude can save and recall facts using store_memory and retrieve_memory tools.
claude mcp add memory -- npx -y @modelcontextprotocol/server-memory
Output:
✅ Added MCP server "memory" (2 tools)
Puppeteer (headless browser)
Drive a real browser for scraping or testing — navigate, click, fill forms, screenshot.
claude mcp add puppeteer -- npx -y @modelcontextprotocol/server-puppeteer
Output:
✅ Added MCP server "puppeteer" (8 tools)
SQLite
Read/write access to a SQLite file. Great for local prototyping and analytics workflows.
claude mcp add sqlite -- npx -y @modelcontextprotocol/server-sqlite /path/to/db.sqlite
Output:
✅ Added MCP server "sqlite" (4 tools)
Build your own MCP server
A minimal stdio MCP server in Python. The server reads JSON-RPC requests from stdin and writes responses to stdout.
# my_server.py
import json, sys
def handle(request):
method = request["method"]
if method == "initialize":
return {"protocolVersion": "2024-11-05", "capabilities": {"tools": {}}, "serverInfo": {"name": "ci", "version": "0.1"}}
if method == "tools/list":
return {
"tools": [{
"name": "get_build_status",
"description": "Get the current CI build status for a branch.",
"inputSchema": {
"type": "object",
"properties": {
"branch": {"type": "string", "description": "Git branch name"}
},
"required": ["branch"]
}
}]
}
if method == "tools/call":
if request["params"]["name"] == "get_build_status":
branch = request["params"]["arguments"]["branch"]
# Replace with real CI API call
return {"content": [{"type": "text", "text": f"Branch '{branch}': passing"}]}
return {"error": {"code": -32601, "message": "Method not found"}}
for line in sys.stdin:
if not line.strip():
continue
req = json.loads(line)
result = handle(req)
response = {"jsonrpc": "2.0", "id": req.get("id"), "result": result}
sys.stdout.write(json.dumps(response) + "\n")
sys.stdout.flush()
Register it:
claude mcp add ci-status -- python3 /path/to/my_server.py
Output:
✅ Added MCP server "ci-status" (1 tool)
Now Claude can call get_build_status(branch="main") during a session.
Using the official SDKs
Anthropic publishes MCP SDKs for Python and TypeScript that handle the JSON-RPC plumbing for you. They're worth using once your server has more than two or three tools.
# Python
pip install mcp
# TypeScript
npm install @modelcontextprotocol/sdk
Output:
Successfully installed mcp-1.x.x
A Python SDK-based server is much shorter than the raw version above:
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
app = Server("ci")
@app.list_tools()
async def list_tools():
return [Tool(
name="get_build_status",
description="Get the current CI build status for a branch.",
inputSchema={"type": "object", "properties": {"branch": {"type": "string"}}, "required": ["branch"]},
)]
@app.call_tool()
async def call_tool(name, arguments):
branch = arguments["branch"]
return [TextContent(type="text", text=f"Branch '{branch}': passing")]
if __name__ == "__main__":
import asyncio
asyncio.run(stdio_server(app))
Output: (none — runs as a stdio MCP server)
Check MCP status in-session
> /mcp
Output:
Connected MCP servers:
github (12 tools) ✅
postgres (3 tools) ✅
memory (2 tools) ✅
MCP permission rules
MCP tools follow the same permission system as built-in tools. Deny or allow specific MCP tools in settings.json. Tool names follow the pattern mcp__<server-name>__<tool-name>.
{
"permissions": {
"allow": [
"mcp__github__search_repositories",
"mcp__github__get_file_contents",
"mcp__postgres__query",
"mcp__memory__retrieve_memory"
],
"deny": [
"mcp__github__create_pull_request",
"mcp__github__delete_file",
"mcp__slack__post_message"
]
}
}
Wildcards work the same way as for built-in tools:
{
"permissions": {
"allow": ["mcp__postgres__*"],
"deny": ["mcp__github__delete_*", "mcp__github__create_pull_request"]
}
}
Authentication patterns
MCP servers that talk to external services need credentials. There are three common patterns:
Environment variables passed via settings.json
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"}
}
}
}
Secret-manager-backed env via apiKeyHelper-style script
{
"mcpServers": {
"github": {
"command": "bash",
"args": ["-c", "GITHUB_PERSONAL_ACCESS_TOKEN=$(op read op://Personal/GitHub/token) exec npx -y @modelcontextprotocol/server-github"]
}
}
}
OAuth for remote (SSE/HTTP) servers
Some MCP servers (Gmail, Google Calendar, Mintlify) implement an OAuth flow. The first call to a tool from such a server triggers an authenticate step that returns a URL; the user opens it, completes consent, and the server stores the resulting token.
> /mcp tools gmail
gmail: 2 tools
authenticate() ← call this first
send_email(to, subject, body)
Output:
> Use gmail/authenticate, then send a test email to alice@example.com
[Calls mcp__gmail__authenticate → returns URL → user completes → token stored]
Common pitfalls
- Server not starting —
claude mcp addvalidates startup but doesn't always surface the error; run the server command manually and watch stderr. - Env vars not expanded —
${VAR}only expands insidemcpServers.*.envandmcpServers.*.args; literal$VARstrings are passed through unchanged. - Tool name length — MCP tool names are namespaced
mcp__<server>__<tool>; servers with long names produce unwieldy permission entries — keep server names short (≤8 chars). - Permission deny for a server prefix — there's no
mcp__github__*deny rule for ALL tools; you must list them individually or use a glob if your version supports it. npx -ycaching —npx -yre-downloads the package on every cold start; for slow networks, install globally withnpm i -g @modelcontextprotocol/server-githuband reference it directly.- Server crashes mid-session — when a server dies, Claude sees tool call failures but doesn't auto-restart; check
/mcpand runclaude mcp restart <name>. - Shared SSE server auth tokens leak — never commit
Authorizationheaders to.claude/settings.json; use.claude/settings.local.jsonor${ENV_VAR}.
Real-world recipes
Database-aware code review
Add a Postgres MCP server in read-only mode so Claude can verify migrations against the live schema during reviews.
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-postgres", "${READONLY_DATABASE_URL}"]
}
},
"permissions": {
"allow": ["mcp__postgres__query", "mcp__postgres__list_tables", "mcp__postgres__describe_table"],
"deny": ["mcp__postgres__execute"]
}
}
Team-wide GitHub server
A shared SSE MCP server lets the whole team share one access token and audit log. Run it on an internal host and reference it from each developer's settings.
{
"mcpServers": {
"team-github": {
"type": "sse",
"url": "https://mcp.internal.example.com/github/sse",
"headers": {"Authorization": "Bearer ${TEAM_MCP_TOKEN}"}
}
}
}
Custom CI status server
Wire your build system into Claude with a small Python MCP server. Useful when Claude is iterating on a flaky test and needs to verify whether main is green.
claude mcp add ci-status -- python3 ~/bin/ci-mcp-server.py
Output:
✅ Added MCP server "ci-status" (3 tools)
Then in-session:
> Is the build green on main?
[Calls mcp__ci-status__get_build_status(branch="main") → "Branch 'main': passing"]
Memory across sessions
Use the memory MCP server as Claude's "scratchpad that survives /clear". Drop key facts there so the next session can pick up where this one left off.
> Save to memory: the auth module uses bcrypt rounds=12, never lower.
[Calls mcp__memory__store_memory]
Output:
Stored.