Chapter 57 — How MCP works: hosts, clients, servers, and primitives
In one sentence
An MCP host application creates a client for each server it connects to, and the server offers tools, resources, and prompts over JSON-RPC 2.0.
The three roles
Get these right and the rest is easy — the naming trips everyone up at first.
+--------------------------------------------------------------+
| HOST The AI application you're using. |
| (an IDE, a chat app, your own agent program) |
| It talks to the LLM and decides what to do. |
| |
| +--------------------+ +--------------------+ |
| | CLIENT | | CLIENT | |
| | one per server, | | one per server | |
| | lives inside | | | |
| | the host | | | |
| +---------|----------+ +---------|----------+ |
+-------------|-------------------------- |---------------------+
| |
JSON-RPC 2.0 JSON-RPC 2.0
| |
+---------v---------+ +---------v---------+
| SERVER | | SERVER |
| "GitHub tools" | | "our database" |
| a separate | | |
| process/service | | |
+-------------------+ +-------------------+
- Host — the application. It owns the LLM conversation and the user relationship.
- Client — a connector inside the host, one per server. It speaks the protocol.
- Server — the thing exposing capabilities. Usually a small separate program.
The critical point: the server never talks to the LLM. It exposes capabilities; the host decides what to show the model and what to execute. That separation is why MCP can be a security boundary.
What a server offers (server features)
Three kinds of thing, and the distinction is about who is in control:
| Primitive | Controlled by | What it is | Example |
|---|---|---|---|
| Tools | the model | Functions the model can decide to call | create_issue, run_query |
| Resources | the application | Data the host can read and put in context | a file's contents, a database schema, a wiki page |
| Prompts | the user | Templated messages/workflows the user can invoke | a /review-pr command, a "summarise this" template |
That control axis is the clearest way to remember them: model-controlled, app-controlled, user-controlled.
What a client offers (client features)
The server can also ask things of the client:
- Elicitation — the server requests additional information from the user mid-operation. ("Which repository did you mean?")
Extensions
Beyond the core, MCP defines opt-in extensions, negotiated at initialization. Notable ones include:
- Tasks — asynchronous execution of long-running operations, with polling and durable handles (so a 20-minute job doesn't hold a connection open)
- Skills over MCP — structured instructions for agent workflows
- MCP Apps — interactive UI elements (charts, forms) rendered inline
The transports
stdio The server runs as a LOCAL SUBPROCESS.
Messages go over standard input/output.
-> local tools: filesystem, git, a local database
-> simple, fast, no network, inherits your permissions
HTTP The server is a remote service with a single MCP endpoint.
Optional Server-Sent Events for server-to-client streaming
(Chapter 43 - the same SSE you already know).
-> shared/hosted servers, SaaS integrations
The messages
MCP uses JSON-RPC 2.0. A tool call looks like this:
--> {"jsonrpc": "2.0", "id": 1, "method": "tools/list"}
<-- {"jsonrpc": "2.0", "id": 1, "result": {"tools": [
{"name": "get_order",
"description": "Look up an order by ID.",
"inputSchema": {"type": "object",
"properties": {"order_id": {"type": "string"}},
"required": ["order_id"]}}
]}}
--> {"jsonrpc": "2.0", "id": 2, "method": "tools/call",
"params": {"name": "get_order", "arguments": {"order_id": "ORD-9931"}}}
<-- {"jsonrpc": "2.0", "id": 2, "result": {"content": [
{"type": "text", "text": "{\"status\": \"shipped\"}"}]}}
Notice inputSchema — it's the same JSON Schema you wrote by hand in
Chapter 52. MCP just standardises how it's delivered.
The stateless change (spec 2026-07-28)
Earlier revisions kept a session between client and server (with an
Mcp-Session-Id header). The current specification made the protocol core
stateless:
BEFORE: client and server maintained a session; requests belonged to it
NOW: each request is SELF-CONTAINED.
Protocol version, client identity, and capabilities travel
with every request, typically in `_meta`.
Servers must not rely on earlier requests for context.
Why it matters: any server instance behind an ordinary load balancer can answer any request. It scales like a normal web service instead of needing sticky sessions — the same lesson as stateless HTTP.
Practice (20 min) — use an MCP server before building one
The fastest way to understand MCP is to connect an existing server.
# The official SDKs and reference servers:
# github.com/modelcontextprotocol/servers
# Many are runnable with no install via npx or uvx.
# Example: run a filesystem server directly and speak JSON-RPC to it by hand.
npx -y @modelcontextprotocol/server-filesystem /tmp
It will wait on stdin. Paste a request and press Enter:
{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"manual-test","version":"0.1.0"}}}}
You will see the tool list come back as JSON. That is the entire protocol,
visible. Try tools/call next.
Then connect a server to a real host (Claude Desktop, an MCP-capable IDE, or your own client) via its MCP configuration, and watch the tools appear in the UI.
Common confusions
- "Is the server the LLM?" No. The server has no model. It exposes capabilities; the host owns the model.
- "Client and server sound backwards." The host application contains clients; the tool provider is the server — same as LSP, and the opposite of what people often assume.
- "Tools vs resources?" Tools are actions the model chooses; resources are data the application supplies. If the model decides, it's a tool.
- "Do I need HTTP?" For local tools,
stdiois simpler and safer.
Check yourself
- Name the three roles and which one talks to the LLM.
- What are the three server primitives, and who controls each?
- What message format does MCP use?
- What changed in the
2026-07-28revision, and why does it matter?
Further reading
- Docs:
modelcontextprotocol.io/specification— read the Architecture and Server Features pages. Surprisingly readable. - Docs: the "Core concepts" tutorials on the same site.
- Code:
github.com/modelcontextprotocol/servers— read a small reference server (the filesystem or fetch one) start to finish.