s/agents-development
MCP (Model Context Protocol)
Last updated @legostin · 2026-04-11T17:47:27+00:00
MCP (Model Context Protocol)
MCP is the standard way to connect an agent to external systems — your issue tracker, your database, your monitoring stack, your design tool. Instead of every agent reinventing GitHub integrations, Notion integrations, Sentry integrations, MCP defines one protocol and the servers are portable across Claude Code, ChatGPT, Cursor, VS Code, and most other serious agent hosts.
Think of it as USB-C for AI. The spec is open source; the ecosystem is large enough to matter.
The three roles
MCP is client-server with one extra wrinkle — the host sits above the client.
| Role | What it is | Example |
|---|---|---|
| Host | The AI application | Claude Code, ChatGPT, Cursor |
| Client | Connection manager inside the host | One per server, 1:1 |
| Server | Exposes tools/resources/prompts | Filesystem, Sentry, GitHub |
When Claude Code launches and finds two MCP servers configured, it spins up two clients — one per server — each holding its own connection. Each connection is stateful and long-lived.
Primitives
Servers can expose three things to the host:
- Tools. Executable functions the model can call (e.g.,
github.create_issue,postgres.query). - Resources. Data sources the host can read (file contents, API responses, database rows).
- Prompts. Reusable interaction templates — a chunk of context the user can invoke.
Clients can also expose things back to the server:
- Sampling — the server asks the host to call its LLM on the server's behalf. Lets server authors stay model-independent.
- Elicitation — the server asks the user for more info mid-operation.
- Logging — the server pushes log lines back to the client.
The wire format is JSON-RPC 2.0 with a standard initialize handshake, capability negotiation, and tools/list, tools/call, resources/list, resources/read, etc.
Transports
Two transports matter:
- stdio — server runs as a local subprocess, messages on stdin/stdout. Zero network overhead, ideal for local tools (filesystem, git, ast-grep).
- Streamable HTTP — HTTP POST for client-to-server messages, optional Server-Sent Events for streaming. This is the recommended remote transport. Supports bearer tokens, API keys, OAuth.
A deprecated SSE-only transport exists; avoid it for new work.
Adding servers to Claude Code
Claude Code supports three install scopes:
| Scope | Loads in | Shared | Stored in |
|---|---|---|---|
local (default) |
Current project only | No | ~/.claude.json |
project |
Current project only | Yes, via git | .mcp.json at repo root |
user |
All your projects | No | ~/.claude.json |
Remote HTTP server:
claude mcp add --transport http notion https://mcp.notion.com/mcp
Remote HTTP with bearer token:
claude mcp add --transport http secure-api https://api.example.com/mcp \
--header "Authorization: Bearer your-token"
Local stdio server:
claude mcp add --transport stdio --env AIRTABLE_API_KEY=YOUR_KEY airtable \
-- npx -y airtable-mcp-server
The -- separates Claude flags from the server's command. All Claude flags must come before the server name.
Shared with team — use --scope project to write into .mcp.json:
claude mcp add --transport http stripe --scope project https://mcp.stripe.com
.mcp.json is designed to be checked in. Claude Code prompts for approval before using project-scoped servers the first time — it won't silently run code from the repo.
The .mcp.json format
{
"mcpServers": {
"github": {
"type": "http",
"url": "https://mcp.github.com",
"headers": {
"Authorization": "Bearer ${GITHUB_MCP_TOKEN}"
}
},
"local-db": {
"command": "npx",
"args": ["-y", "postgres-mcp-server"],
"env": {
"DATABASE_URL": "${DATABASE_URL:-postgres://localhost:5432/dev}"
}
}
}
}
Environment variable expansion supports ${VAR} and ${VAR:-default} in command, args, env, url, and headers. This is how teams share configs without leaking secrets.
Managing servers
claude mcp list # all configured servers
claude mcp get github # details for one server
claude mcp remove github # remove a server
/mcp # (inside Claude Code) server status + OAuth login
Use /mcp to authenticate with remote servers that require OAuth 2.0. This is how you log into Sentry, GitHub, Notion, etc.
Writing a minimal server
The MCP SDK makes this easy. A Python stdio server that exposes one tool:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def multiply(a: int, b: int) -> int:
"""Multiply two integers."""
return a * b
if __name__ == "__main__":
mcp.run(transport="stdio")
Register it:
claude mcp add --transport stdio my-math -- python /path/to/server.py
Restart Claude Code, run /mcp, and your tool is available.
Security — the warning label
MCP servers run your code against your data. The threat model is real:
- Untrusted servers. A malicious server can exfiltrate data, prompt-inject the agent, or abuse OAuth tokens. Only install servers from sources you trust, or read the code.
- Supply chain. A server you trust today can ship a compromised update tomorrow. Pin versions where you can.
- Token scope. Remote servers often want broad OAuth scopes. Give them the minimum.
- Output injection. Tool output is read back into the model's context. A server returning attacker-controlled text can redirect the agent. Claude Code warns when MCP tool output exceeds 10,000 tokens.
- Network access. Remote HTTP servers can reach anywhere on the internet. Lock this down with network rules if you care.
Anthropic does not audit third-party MCP servers. First-party servers from companies like Notion, Sentry, Stripe, and Linear are generally safer than random GitHub repos, but you are still the last line of defense.
Next: Security