Chapter 2 — Unveiling the Model Context Protocol (MCP)

Published on: 2026-03-31 Last updated on: 2026-06-12 Version: 2
Chapter 2 — Unveiling the Model Context Protocol (MCP)

Chapter 2 — Unveiling the Model Context Protocol (MCP)

Second post of the chapter-by-chapter walkthrough of LLM Primer IV: Designing AI Cognition with MCP. In which we build the mental model — three roles, a JSON-RPC wire format, a dynamic discovery surface, and a session lifecycle — carefully enough that the rest of the book can stand on it.


Why this chapter exists

Chapter 1 named the problem. This chapter builds the mental model of the answer. MCP can be summarized in a sentence and misunderstood in a paragraph, so the chapter takes its time: what the protocol is at the wire level, what the three roles mean and what each owns, how it differs from a REST API in the cases that actually matter in production, and what happens during a session from connection to teardown. The goal is that, by the end, you can predict — before reading the next chapter — what a server primitive must be, what a client primitive must be, and why MCP earns the structure it has.

One line: MCP is a JSON-RPC protocol with three roles — Host, Client, Server — explicit capability negotiation, runtime discovery as the source of truth, and a bidirectional message model that makes agentic patterns natively expressible rather than bolted on.

2.1 What MCP is and what "USB-C for AI" actually means

The Model Context Protocol is an open specification for how LLM applications discover, describe, and invoke external capabilities. At the wire it is JSON-RPC 2.0 over one of a small number of transports. At the architectural level it is the contract that lets a host work with any conforming server without bespoke integration code. A tool built once against the protocol works with every host that speaks it. A host built once against the protocol can use every tool that speaks it.

The shorthand that has stuck is "USB-C for AI." The structural shape really does mirror USB-C — a single connection standard mediating between an open population of devices and an open population of hosts. The limits of the metaphor are worth naming: USB-C standardizes a connector plus a stack above it; MCP standardizes only the protocol. USB-C runs at electrical timescales with hardware-enforced framing; MCP runs at network timescales with software-defined framing, which means MCP gets to be more flexible and also has to handle dropped connections and slow peers that USB-C does not.

A closer comparison, for engineers, is LSP. The Language Server Protocol defined a protocol that any editor and any language server could speak; MCP defines one that any LLM host and any capability provider can speak. The shape of the win is identical — many-to-many collapsed by a shared protocol into something that scales additively. The choice to base MCP on JSON-RPC 2.0 rather than invent a fresh wire format was deliberate: JSON-RPC is small, mature, language-agnostic, and unglamorous. The interesting architectural choices are not at the wire level. They are in how Hosts, Clients, and Servers divide responsibility.

2.2 Hosts, Clients, and Servers — what each role owns

MCP defines three roles, and the first thing to understand is that "Client" and "Server" do not mean what they often mean elsewhere. A Server exposes capabilities — tools, resources, prompts. A Client is a single protocol-speaking connection to one Server, managed inside a larger application. The larger application is the Host. The Host owns the model, the user's session, and the policy about what the model is allowed to do. The Servers own their capability surfaces. The Clients are the wires between them, one per Server.

The split matters because each role has a different responsibility and a different trust posture. The Host is the trust boundary that matters from the user's perspective; everything else is something the Host has decided to let in. A Host talking to five Servers has five Clients running inside it, each with its own session state, its own subscriptions, its own view of which capabilities have been negotiated. If a Server crashes, the corresponding Client crashes; the other Clients keep running; the Host stays alive. The Clients are per-connection isolators that keep one bad Server from poisoning the whole session.

There is also a security argument for the split. Every Server is, at minimum, code written by someone else. The Client mediates everything the Server can do that affects the Host — notifications, elicitations, sampling requests, published resources — and it is where per-Server policy belongs. Hosts, Clients, and Servers are logical roles, not strictly physical ones: in a local setup the Server is often a subprocess over stdio; in a remote deployment it is a service over HTTP-based transport. The protocol does not care; the role boundaries do.

2.3 MCP versus REST — what dynamic discovery and semantic descriptions buy you

The reasonable question is "is this not just REST?" The differences are not cosmetic. The most consequential are dynamic discovery, semantic descriptions written for an LLM, and a bidirectional message model.

A REST API publishes endpoints in documentation written for human developers. The set of endpoints a client uses is fixed at build time; new endpoints require redeploys. MCP inverts this. At session start, the Client asks "what do you offer?" and the Server replies with a typed catalog — schemas, descriptions, metadata — that the host uses programmatically. If the Server later adds a tool, a listChanged notification updates the Client mid-session without restart. The Server is the authoritative source of truth about its own capabilities; the description cannot drift from the implementation because there is no separate client-side copy to drift from.

Semantic descriptions are the second difference. A REST endpoint's docs are written for a developer who will read and decide. An MCP tool's description is written for an LLM that will read it as part of its prompt and decide autonomously. A description that reads "POST to /users/:id/orders" is useless to an LLM, which needs to know what conceptual operation the tool performs, when it should be preferred, what side effects it has, and what its inputs mean in domain terms. The work of translating the API into LLM-readable terms has been pushed once, into the Server, where the people closest to the capability can maintain it.

The third difference is bidirectionality. REST is request-response; the connection closes. MCP is bidirectional by design. The Server can send notifications at any time, can initiate sampling requests back at the Client, can elicit answers from the user mid-flow. None of these are technically impossible over REST. All of them are awkward there. In MCP they are part of the standard.

2.4 Capability negotiation and the session lifecycle

A session begins when the Client opens a transport and sends an initialize request carrying its protocol version and capabilities. The Server replies with its own capabilities — does it expose tools, does it expose resources, does it offer subscriptions, does it support advanced features. The Client confirms with an initialized notification. The session is then in the operational state, and the available message types are exactly the subset both sides agreed to.

This negotiation is what lets a Client and Server with different feature sets coexist productively. It is also where versioning is handled: the Server picks the highest version both sides support. Operationally, the lifecycle has consequences. Initialization is not free — there is a round-trip cost and, for remote servers, a connection setup on top. Long-lived sessions are the preferred pattern; capability changes flow as notifications rather than as reconnection. Hosts that respect this — keeping sessions warm, reconnecting in the background after network blips — get materially better latency. Hosts that tear down and re-initialize for every request work correctly but inefficiently.

An asymmetry worth pinning down: requests have replies; notifications do not. List-changed events are notifications, so a Client that misses one must be prepared to refresh its view by re-calling list_tools. The notification is an optimization, not a guarantee. Robust MCP code treats it as a hint, not a record.

Worth holding onto: read the three roles as a deliberate factoring of responsibility — Host owns model and policy, Server owns capability, Client owns per-connection mediation. Read dynamic discovery as the move that makes Servers the source of truth and eliminates client-side drift. Read the bidirectional message model as what makes agentic patterns native rather than retrofitted. None of these is a small detail; each is doing structural work.

What Chapter 2 sets up

You now have the mental model. MCP is a JSON-RPC protocol with three roles, dynamic discovery that makes the Server authoritative for its own capabilities, descriptions written for an LLM audience, a bidirectional message model with notifications and server-initiated requests, and a lifecycle that opens with explicit capability negotiation and operates inside whatever subset both sides agreed to. This is enough scaffolding to talk concretely about what Servers and Clients each expose, which is what the next two chapters do.


Next — Chapter 3: Server Primitives — Resources, Prompts, Tools. The three nouns a server can offer, why each one matters, and the discipline of choosing the right primitive instead of overloading one into another's territory.

Want the full picture? The book walks the wire format with annotated message traces, develops the comparison to LSP and USB-C with practical implications, and treats the lifecycle in enough detail to ground Chapters 11 and 12 on security. View LLM Primer IV on Amazon →

SHO
SHO
CTO of Receipt Roller Inc., he builds innovative AI solutions and writes to make large language models more understandable, sharing both practical uses and behind-the-scenes insights.