MCP Quick Reference
The Model Context Protocol on one page — primitives, transports, message flow, security rules.
The Model Context Protocol is an open standard for connecting AI applications to tools and data. A host (Claude Desktop, an IDE, an agent) runs one client per server; servers expose tools the model can call, resources it can read and prompts users can invoke, as JSON-RPC 2.0 messages over stdio or HTTP.
The spec ships in dated revisions — 2025-03-26, 2025-06-18, 2025-11-25, 2026-07-28 — and rows note where behavior differs. The biggest shift: 2026-07-28 drops the initialize handshake and sessions in favor of self-contained requests.
The primitives
- Tools
- model-callable functions with JSON-Schema params — the verbs
- Resources
- readable data (files, tables, docs) addressed by URI — the nouns
- Prompts
- server-provided prompt templates the user can invoke
- Sampling
- server asks the CLIENT for a completion — needs approval; deprecated in 2026-07-28
- Roots
- client-declared directory scopes the server may touch; deprecated in 2026-07-28
- Elicitation
- the server asks the user for input mid-call: a form (2025-06-18) or a URL (2025-11-25)
- Resource templates
- parameterized URIs such as
notes://{name}, listed byresources/templates/list - Completion
completion/complete: autocomplete for prompt and resource-template arguments
Architecture & flow
- Topology
- host app → N clients → N servers (1:1 client:server), JSON-RPC 2.0
- Transports
stdio(local child process) · streamable HTTP (remote)- Handshake
initialize→notifications/initialized→tools/list→tools/call(revisions to 2025-11-25)- Discovery
- clients re-list on
listChangednotifications — tools can change mid-session - Why it exists
- N models × M tools = N·M custom integrations → N+M with one protocol
- Stateless (2026-07-28)
- no handshake or session: each request carries its version in
_meta;server/discoveris optional - Protocol revisions
- 2024-11-05 · 2025-03-26 · 2025-06-18 · 2025-11-25 · 2026-07-28 — peers negotiate one
Messages
- tools/list
- every tool’s name, description,
inputSchemaand optionaloutputSchema - tools/call
{ name, arguments }in;contentblocks, maybestructuredContent, out- resources/list · resources/read
- enumerate resources, then fetch one by its URI
- prompts/list · prompts/get
- discover prompt templates, then render one with arguments into messages
- notifications/progress
- progress for a long-running call, tied to the request’s
progressToken - notifications/cancelled
- ask the other side to abandon an in-flight request, by its id
- cursor / nextCursor
- pagination on list methods — keep requesting until no
nextCursorcomes back
Tool design
- Description is a prompt
- the model picks tools from names and descriptions alone — write them as instructions
- inputSchema
- JSON Schema for the arguments; SDKs generate it from type hints and docstrings
- readOnlyHint / destructiveHint
- annotations that drive approval UIs — hints only, never a security boundary
- idempotentHint / openWorldHint
- safe to retry / reaches outside systems — also self-reported by the server
- isError: true
- tool failures go in the result so the model can react; JSON-RPC errors mean protocol faults
- structuredContent
- typed JSON result alongside the text, described by
outputSchema(2025-06-18) - Few, task-shaped tools
- a dozen focused tools beat a hundred thin API wrappers — less context, fewer wrong picks
Transports & auth
- stdio
- newline-delimited JSON-RPC on stdin/stdout; log to stderr — one stray print breaks it
- Streamable HTTP
- one endpoint taking POSTs, optionally streaming SSE; replaced HTTP+SSE in 2025-03-26
- Mcp-Session-Id
- the HTTP session header up to 2025-11-25; the 2026-07-28 wire has no sessions
- MCP-Protocol-Version
- HTTP header naming the protocol revision a request uses (2025-06-18 onward)
- OAuth 2.1
- remote servers act as OAuth resource servers; clients find the auth server via resource metadata
- No token passthrough
- a server must not accept, or forward upstream, tokens issued for another audience
Security rules
- Tool descriptions are context
- a malicious server injects via its own tool docs — vet before install
- Rug pulls
- server changes descriptions after approval — pin versions, diff on update
- Confused deputy
- server acts with YOUR creds on injected orders — scope credentials per server
- Human-in-the-loop
- destructive tools gate on approval; sampling requests always visible
- Least privilege
- grant roots narrowly; read-only where read-only works
- Results are untrusted
- tool output is just text — a fetched page or ticket can carry injected instructions
- Validate arguments
- servers must check every argument for path traversal, SQL and shell injection
- Local means your permissions
- a stdio server runs as your user — install only code you would run yourself
Build & test
- claude mcp add name -- cmd args
- add a stdio server to Claude Code;
-s useror-s projectsets the scope - claude mcp add --transport http name url
- add a remote server;
claude mcp listshows every configured one - .mcp.json
- project-scoped servers committed to the repo and shared with the team
- claude_desktop_config.json
mcpServers: command, args and env per server for Claude Desktop; restart after edits- npx @modelcontextprotocol/inspector
- interactive UI to list and call a server’s tools, resources and prompts
- pip install "mcp[cli]"
- official Python SDK; v2 renamed
FastMCPtoMCPServer;mcp devopens the Inspector - @modelcontextprotocol/sdk
- the official TypeScript SDK for servers and clients
Recipes
A minimal MCP server in Python (official SDK v2)
# pip install "mcp[cli]"
from mcp.server.mcpserver import MCPServer
mcp = MCPServer("weather")
@mcp.tool()
def get_forecast(city: str, days: int = 1) -> str:
"""Return a short weather forecast for a city."""
return f"{city}: sunny for {days} day(s)"
if __name__ == "__main__":
mcp.run() # stdio; mcp.run(transport="streamable-http") serves HTTPThe SDK builds the JSON Schema from the type hints and the description from the docstring. On SDK 1.x the same code imports FastMCP from mcp.server.fastmcp.
Register a server with Claude Code and Claude Desktop
# Claude Code: everything after -- is the command that launches the server
claude mcp add weather -- python /path/to/server.py
claude mcp add --transport http sentry https://mcp.sentry.dev/mcp
claude mcp list
# Claude Desktop (macOS): ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["/path/to/server.py"],
"env": { "API_KEY": "..." }
}
}
}Use absolute paths: the client starts the server from its own working directory, not yours. Restart Claude Desktop after changing its config.
Test a server before wiring it into a host
npx @modelcontextprotocol/inspector python server.py
# or, with the Python SDK installed:
mcp dev server.py
# a local web UI opens: connect, list and call tools, read resources, render promptsThe Inspector shows the raw JSON-RPC traffic, so it is the fastest way to see a schema mistake or a stray print that corrupts the stdio stream.
The raw exchange over stdio (revisions up to 2025-11-25)
-> {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"demo","version":"0.1"}}}
<- {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{"listChanged":false}},"serverInfo":{"name":"weather","version":""}}}
-> {"jsonrpc":"2.0","method":"notifications/initialized"}
-> {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_forecast","arguments":{"city":"Oslo","days":2}}}
<- {"jsonrpc":"2.0","id":2,"result":{"content":[{"type":"text","text":"Oslo: sunny for 2 day(s)"}],"structuredContent":{"result":"Oslo: sunny for 2 day(s)"},"isError":false}}One JSON object per line (capabilities trimmed here). A notification has no id and gets no reply. An unknown tool comes back as a result with isError: true; an unknown method is JSON-RPC error -32601.
Design a tool the model will use correctly
name: search_orders
description: Search a customer's orders by email or order id. Returns at most
20 orders, newest first. Use get_order for one order's full details.
inputSchema: { "type": "object",
"properties": {
"query": { "type": "string", "description": "email or order id" },
"status": { "type": "string", "enum": ["open", "shipped", "refunded"] } },
"required": ["query"] }
annotations: { "readOnlyHint": true, "openWorldHint": false }
on failure: isError: true with a fix-it message, e.g. "No customer with that email."Say when to use the tool, what it returns and its limits, and point to the neighboring tool for the other job. An enum stops the model inventing status values.
Questions about MCP Cheat Sheet
What is the Model Context Protocol (MCP)?
MCP is an open protocol, introduced by Anthropic in November 2024, that standardizes how AI applications connect to external tools and data. Instead of writing a custom integration for every pairing of model app and service, a service is wrapped once as an MCP server, and any MCP-capable host, such as Claude Desktop, Claude Code or an IDE assistant, can use it. Servers advertise tools, resources and prompts, and the host’s client calls them with JSON-RPC 2.0 messages over a local stdio pipe or over HTTP. The specification is published in dated revisions.
What is the difference between MCP tools, resources and prompts?
They differ in who is in control. Tools are model-controlled: functions with a JSON Schema for their arguments that the model decides to call, such as creating a ticket or running a query, and they may have side effects. Resources are application-controlled: read-only data identified by URIs, such as files, records or documents, that the host can attach as context. Prompts are user-controlled: reusable templates, often surfaced as slash commands, that the user explicitly picks. A useful rule of thumb is that tools are verbs, resources are nouns and prompts are recipes.
What is the difference between stdio and Streamable HTTP in MCP?
With stdio, the host launches the server as a local child process and they exchange newline-delimited JSON-RPC messages over standard input and output. It needs no network or authentication, but the server runs with your user’s permissions and anything it prints to stdout corrupts the stream, so logs must go to stderr. Streamable HTTP, introduced in the 2025-03-26 revision, runs the server as a web service at a single endpoint that receives POST requests and can stream responses as server-sent events. It suits remote, shared and multi-user servers, and uses OAuth for authorization.
What are the security risks of MCP servers?
An MCP server is code and context you are trusting. Tool descriptions and tool results flow into the model, so a malicious or compromised server, or data it fetches, can inject instructions that steer the model into misusing other tools or leaking data. Servers can also change their descriptions after you approve them, and local stdio servers run with your full user permissions. Mitigate by installing servers only from sources you trust, pinning versions, scoping each server’s credentials narrowly, keeping approval prompts on for destructive tools, and treating every tool result as untrusted input.