What is the Model Context Protocol? A Developer's Map (2026)
MCP turned every AI client into a tool host with one shared wire format. This is the developer-grade explainer — the named pieces, the smallest server you can run today, the gotchas that bit me, and the April 2026 security disclosure that everyone keeps missing.

On this page · 15 sections▾
One-sentence definition
MCP is a JSON-RPC 2.0 wire format that lets any LLM client talk to any tool or data server through a uniform stdio or HTTP interface — function calling, but standardized across vendors and reusable across clients.
That sentence is the whole post. Everything below is a deeper read of one of its words.
Why MCP exists
Before November 2024, every AI client invented its own way to plug in tools. Cursor had one tool config. Claude Desktop had claude_desktop_config.json. VS Code shipped extensions through its marketplace. Cline used an MCP-shaped file before MCP existed. A server author who wanted to support four clients wrote four integrations and synced them by hand whenever any one of them changed.
Anthropic open-sourced the Model Context Protocol that month in a launch post that framed it as “a universal, open standard for connecting AI systems with data sources, replacing fragmented integrations with a single protocol.” In April 2026, Anthropic donated the spec to the Linux Foundation under the new Agentic AI Foundation — confirmation, in governance terms, that MCP is now industry plumbing rather than an Anthropic feature.
The pre-MCP world was not impossible. It was tedious. MCP collapses the N-by-M integration problem to N-plus-M: each client speaks the protocol once, each server implements it once, and the directory between them — like this one — is what readers actually use to discover what to plug in.
The official analogy is wrong
MCP’s docs say it is “like a USB-C port for AI applications.” That analogy is wrong in the way most analogies are wrong: it loses the parts that matter. USB-C is a hardware spec defining voltage, pins, and connectors. MCP is a JSON-RPC protocol with capability negotiation, three primitives (tool, resource, prompt), and bidirectional sampling. If you think USB-C, you will be surprised when an MCP server pushes a notification, requests a model completion from your client, or stops responding because session capabilities did not negotiate. Use the technical sentence, not the analogy.
Mental model: the named pieces
MCP has six pieces worth naming. Once you know these, every doc page on modelcontextprotocol.io is just a deeper read of one of them.
┌──────────────┐ JSON-RPC 2.0 ┌──────────────┐
│ │ ─────tool call──── ▶│ │
│ CLIENT │ │ SERVER │
│ │ ◀── tool result ────│ │
│ Claude Desk │ │ filesystem │
│ Cursor │ ◀── notification ───│ github │
│ VS Code │ │ notion │
│ ChatGPT │ ─── sampling req ──▶│ ... │
└──────────────┘ └──────────────┘
│ │
│ stdio (local) / streamable-http (remote)
▼ ▼
subprocess HTTPS endpoint
pipes + OAuth 2.1- Server — a process that exposes tools, resources, and prompts over the protocol. You write these.
- Client — the AI app (Claude Desktop, Cursor, VS Code, ChatGPT, Claude Code) that speaks the protocol and surfaces tools to its language model.
- Transport — how bytes move.
stdiofor local subprocess servers,streamable-httpfor remote,SSEdeprecated in the 2025-03 revision. - Tool — a write-allowed RPC. The model decides to invoke it; the server runs code; a result comes back. Example:
send_email,create_pull_request. - Resource — read-only addressable context. The client pulls it eagerly into the prompt window. Example:
file:///etc/hosts,github://owner/repo/issue/42. - Prompt — a server-defined template the user can summon, often with arguments. Less used in practice than tools and resources.
There are two more concepts that matter the moment you ship anything real: capability negotiation (both sides advertise what they support at session init — your server only sees the features the client agreed to) and sampling (the server can request the client’s model to complete a prompt — useful for agent loops, abused for prompt injection).
Smallest end-to-end example
The shortest path from zero to a working MCP server is sixty lines of Python. This server exposes one tool — get_weather — and Claude Desktop will pick it up automatically.
# weather_server.py
import json
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather")
@mcp.tool()
def get_weather(city: str) -> dict:
"""Return current weather for a city."""
# Hardcoded for the example; real implementations call a weather API.
return {
"city": city,
"temperature_c": 18,
"condition": "partly cloudy",
}
if __name__ == "__main__":
mcp.run(transport="stdio")
Install the SDK and add the server to Claude Desktop’s config:
pip install "mcp[cli]"
# ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["/absolute/path/to/weather_server.py"]
}
}
}Restart Claude Desktop. Ask it “what’s the weather in Berlin?” and the model picks the get_weather tool, the client runs your server as a subprocess, the JSON-RPC frame goes over stdio, and the result lands in the chat. That’s the whole loop.
The same server runs unchanged in Cursor, VS Code, and Claude Code — that portability is the entire point of the protocol.
Deep dive: the six pieces
Server
A server is a process. It speaks JSON-RPC. The official SDKs (Python, TypeScript) hide framing and lifecycle so you write business logic only. Both SDKs sit on tens of thousands of GitHub stars combined and ship the FastMCP-style decorator API that the example above used.
Opinion: write Python servers unless you have a reason not to. The Python SDK has the most idiomatic API, the largest example library, and the best inspector tooling. TypeScript is fine if you already have a Node runtime or you’re embedding MCP into a web app.
Client
A client is the AI app the end user opens. Today the major clients are Claude Desktop, ChatGPT, Cursor, VS Code (via Copilot Chat), and Claude Code. The MCP Registry — launched in late 2025 — feeds the in-app server browser most of these clients now ship.
Opinion: build for Claude Desktop and Cursor first. They have the largest active MCP user base and the most mature integration. VS Code is catching up; ChatGPT is the wildcard with the largest reach.
Transport
Two transports matter:
- stdio — the client launches your server as a subprocess and pipes JSON-RPC frames over stdin/stdout. Latency is microseconds. Authentication is implicit: whoever runs the binary.
- streamable-http — the server is a web service. The client hits an HTTPS endpoint, holds a long-lived connection for streaming, authenticates with OAuth 2.1.
SSE existed in the 2024 revision, was deprecated in March 2025, and should not be picked for new work. Some servers still expose it for backward compatibility.
Opinion: stdio for local trust, streamable-http for everything else, SSE never.
Tool vs Resource vs Prompt
These three are the actual API surface a server exposes. The most common mistake is reaching for a tool when a resource would do.
- Tool = the model has to decide to call. The model picks the tool from a list at every step. If the description is bad, the model never picks it; if it’s too generic, the model picks it for everything.
- Resource = the client pulls it into the prompt eagerly. The model never has to choose; the data is just there.
- Prompt = a user-summoned template. Mostly useful for slash-command-style UX inside a client.
Opinion: use tools for actions, resources for context. Wrapping read-only context as a tool means the model has to remember to fetch it — and it often won’t.
Capability negotiation
At session init, the client says “I support these capabilities,” and the server says “I support these.” What you do next is constrained by the intersection. If the client doesn’t advertise sampling, your server can’t request a completion. If the server doesn’t advertise tools/listChanged, the client won’t poll for tool updates.
Opinion: log the negotiated capabilities at startup. Half the “why doesn’t this work?” debugging time goes to features one side didn’t actually negotiate.
Sampling
Sampling is the server-initiated message: “run this prompt through your model and give me the completion.” Useful for agent-style flows where the server needs the model’s help mid-execution. Also the attack surface that Palo Alto Unit 42 flagged in 2026: a malicious server crafts a sampling request that prompt-injects the client’s model.
Opinion: don’t use sampling unless you need it. Most servers don’t.
What I got wrong
Three things I assumed about MCP and was burned by.
1. I thought MCP was a replacement for function calling. It isn’t. The model still does function calling at the LLM layer — it emits a structured tool call. MCP is the transport that carries that call across a process boundary to a server you control. Treating MCP as “the new function calling” will mislead you the first time you hit a non-MCP function-calling API and wonder where the protocol went.
2. I thought stdio was a hack. Subprocess pipes feel like a 1980s solution. They’re actually the right answer for the local trust boundary: the same trust model as installing any CLI tool. The wrong move is putting stdio servers behind HTTP because it “feels more modern” — you’ve added latency, a deployment target, and an auth headache for no reason.
3. I assumed wide tool descriptions were free. Every tool description is in every prompt the client sends to the LLM. A 200-token tool description on a server with 30 tools, called 50 times in a coding session, is 300,000 input tokens you didn’t price in. Compress descriptions ruthlessly. The April 2026 OX Security disclosure was partly about exactly this lever — descriptions and command strings carry execution semantics, and most server authors don’t treat them with that weight.
Common mistakes
Server hangs on startup
Root cause: writing logs to stdout. Stdout is the JSON-RPC frame channel — anything else corrupts the stream and the client times out the handshake. Log to stderr or a file.
Tool not visible in client
Root cause: clients fetch the tool list at session init and cache it. If you add a tool while the client is running, restart the client — or implement tools/listChanged notifications and let the client refresh.
OAuth flow loops on streamable-http
Root cause: redirect URI mismatch between what the client sends and what the server registered. The MCP spec requires PKCE; many server starter templates skip it and fail discovery.
Tool description too generic, model never picks it
Root cause: descriptions like “does database stuff” lose to better-described tools when the model is choosing. Write descriptions like Stripe API docs: precise, concrete, with one example use case.
Resource path looks like a URL but isn’t resolvable
Root cause: returning a resource URI the server can’t actually read_resource on. The URI scheme is yours, but every URI listed must be readable.
Performance and cost
MCP is cheap. Concrete numbers from a real session, not back-of-envelope:
- Stdio round-trip: 3–8 ms localhost. Subprocess pipes are basically free.
- Streamable-http round-trip: 30–100 ms over the open internet, depending on TLS reuse and the server’s region.
- Practical payload limit: 1–2 MB per message before clients start truncating. Use resource URIs and pagination for anything larger.
- Tool-description cost: every description ships in every prompt. A server with 30 tools at ~150 tokens each adds 4,500 input tokens per call. Multiply by call count for a session and you’ll see why pruning matters.
- Capability negotiation: one round-trip at session start, then never again. Negligible.
Who this is for, who it isn’t
Use MCP if
- You want one tool to work in >1 AI client.
- You’re building dev tooling, an internal data connector, or an agent capability.
- You expect your tool surface to evolve and want capability negotiation.
- You want your tool listed in the registries clients ship with.
Skip MCP if
- You have one client, one schema, no portability need.
- You’re shipping a single-purpose chatbot inside one app.
- Plain function calling against your own LLM API meets the requirement.
Community signal
The protocol’s adoption curve has been steep. Anthropic’s November 2024 launch announcement is one of the most-discussed AI infrastructure threads of the past year on Hacker News, with ecosystem entries from Block, Apollo, Zed, Replit, Codeium, and Sourcegraph naming MCP in their integration roadmaps.
The April 2026 donation of MCP to the Linux Foundation under the new Agentic AI Foundation drew thousands of upvotes on r/ClaudeAI and a high-engagement Hacker News thread. The shorthand reaction across both: “this is no longer an Anthropic feature, it’s the standard.”
The contrarian voice is sharper than the cheerleading. In April 2026, OX Security published a disclosure showing that MCP’s stdio transport gives configuration files a direct path to command execution, affecting roughly 200,000 deployed servers across 150 million package downloads. Anthropic declined to patch — calling the behavior “expected” and pushing input validation onto developers, per The Register’s coverage. That position is defensible (stdio is by definition a trusted-binary boundary) and disquieting (most users do not audit MCP server source the way they audit CLI tools they install).
The verdict
Our take
Default to MCP for any tool you want more than one AI client to use. The portability benefit is real, the protocol is now Linux-Foundation-governed plumbing, and the ecosystem has crossed the “rewrite once, run everywhere” threshold for serious clients.
Stay on plain function calling if you have one client, one schema, and don’t expect that to change — MCP’s overhead isn’t worth it for a closed loop. And whichever path you pick, treat the “install an MCP server” trust boundary the same as “install a CLI tool from npm.” Source matters; the April 2026 disclosure is a reminder, not a surprise.
The bigger picture
The MCP ecosystem in 2026 has three layers worth tracking. Registries — including this one — are the discovery surface; the official MCP Registry feeds Claude Desktop and Cursor’s in-app browsers. Build tooling — FastMCP-style decorator APIs, the MCP Inspector, language SDKs in Python, TypeScript, Rust, Go — has matured to the point that a useful server is a weekend project. Security tooling — VulnerableMCP, Red Hat’s controls guide, Unit 42’s sampling-attack research — is the layer that lags but is filling in fast.
Where it’s heading: streamable-http normalizing as the default for hosted servers, sampling becoming usable beyond demos once clients ship better trust UI, and IDE-side schema linting for tool descriptions so the “model never picks my tool” mistake disappears at write-time. The Linux Foundation move accelerates all three; vendor-neutral governance is the hinge that lets non-Anthropic clients invest without strategic risk.
Frequently asked questions
Is MCP a replacement for function calling?
No. Function calling is the LLM-side mechanic — the model emits a structured tool call. MCP is a wire format that carries those tool calls between an AI client and an external server. Use both together: the model still does function calling; MCP standardizes who it can call.
Why JSON-RPC and not OpenAPI?
JSON-RPC is bidirectional and stateful. The server can push notifications, request sampling from the client's LLM, and negotiate capabilities at session start. OpenAPI describes stateless HTTP endpoints — it would not cover server-initiated messages or stdio transports.
Is stdio safe for MCP servers?
Stdio is the right transport for local trust boundaries — your shell process, your machine, your files. It is unsafe for untrusted servers because the client typically launches the binary with the user's permissions. Treat installing an MCP server like installing a CLI tool: source matters.
Should I use SSE or streamable-http for remote servers?
Streamable-http. SSE was deprecated in the 2025-03 protocol revision. New servers should ship streamable-http; existing SSE servers still work but should migrate. Most client SDKs handle both transparently.
How do I authenticate a remote MCP server?
OAuth 2.1 with PKCE, defined in the spec since the 2025-03 revision. The client redirects the user to the server's authorization URL, gets an access token, and includes it on the streamable-http request. For local stdio servers, authentication is implicit — whoever runs the binary.
What was the April 2026 MCP security disclosure?
OX Security disclosed that MCP's stdio transport allows direct command execution from configuration, affecting roughly 200,000 deployed servers. Anthropic declined to patch, calling the behavior expected and placing the burden on developers to validate inputs. The pragmatic mitigation is to install only servers from sources you trust, the same as any CLI binary.
Where do I publish my MCP server?
List it on MCP.Directory and submit a PR to the modelcontextprotocol/servers repo. The official MCP Registry launched in late 2025 is becoming the canonical index — getting picked up there means it surfaces in Claude Desktop and Cursor's built-in browsers automatically.
Glossary
Server
Process that exposes tools, resources, and prompts over MCP.
Client
AI app (Claude Desktop, Cursor, VS Code) that speaks MCP.
Transport
How JSON-RPC frames move: stdio (local) or streamable-http (remote).
Tool
Write-allowed RPC the model decides to invoke.
Resource
Read-only addressable context the client pulls into the prompt.
Prompt
User-summoned template, often with arguments. Slash-command UX.
JSON-RPC
Bidirectional, stateful RPC format MCP layers on top of.
Capability negotiation
Session-init handshake where both sides advertise supported features.
Sampling
Server-initiated request for the client's LLM to complete a prompt.
stdio
Subprocess transport: client launches server, pipes JSON over stdin/stdout.
streamable-http
Long-lived HTTPS transport for remote servers. Replaces SSE.
OAuth 2.1 + PKCE
Auth scheme for streamable-http servers, required by the spec.
All sources
Primary
- Introducing the Model Context Protocol — Anthropic’s November 2024 launch post.
- modelcontextprotocol.io — official documentation, spec, registry.
- modelcontextprotocol/specification — protocol revisions and ratified versions.
- Python SDK — FastMCP API used in the smallest example.
- TypeScript SDK — for Node-runtime servers.
Community
- Hacker News on the launch — original 2024 community reaction.
- Hacker News on the Linux Foundation donation.
- r/ClaudeAI thread on the Linux Foundation donation.
Security and contrarian
- OX Security: critical systemic vulnerability at the core of MCP.
- The Register: MCP ‘design flaw’ puts 200k servers at risk.
- Red Hat: MCP security risks and controls.
- Palo Alto Unit 42: prompt injection through MCP sampling.
- VulnerableMCP database.
Internal