Why MCP Exists & The Architecture
Module 1 — Why MCP Exists & The Architecture
Phase 1 · Foundations. This is the conceptual bedrock. Everything later — transports, primitives, OAuth, entitlements, gateways — is structure bolted onto the ideas here. Read slowly. The goal isn’t to memorize terms; it’s to be able to reconstruct the whole picture from scratch and explain it to someone else.
By the end you can:
- Explain the problem MCP solves and why a protocol (not a library or an API) is the right shape for it.
- Name and correctly distinguish the three roles — host, client, server — without confusing who owns the model.
- Walk an end-to-end tool call from user keystroke to answer, naming every hop.
- Spot the five misconceptions that trip up almost everyone.
1. The problem: N×M integration
Large language models are good at reasoning over text but, on their own, are sealed in a box. They can’t read your files, query your database, hit an API, or take an action in the world. To be useful, an AI application has to be connected to external capabilities.
Before MCP, every connection was bespoke. If you had N AI applications (a chat app, an IDE assistant, an internal agent) and M capabilities you wanted them to reach (GitHub, Postgres, Slack, your CRM, the filesystem), you needed a custom integration for each pair. That’s N × M integrations. Add one new AI app and you re-integrate all M tools. Add one new tool and you re-integrate it into all N apps. The cost grows multiplicatively, every integration is slightly different, and nothing is reusable.
Without a standard (N×M) With MCP (N+M)
App1 App2 App3 App1 App2 App3
│ ╲ │ ╲ │ │ │ │
│ ╲ │ ╲ │ every line is ╲ │ ╱
┌─┼────╲┼───╲─┼─┐ a custom build ╲ │ ╱
│ │ X X │ ╲ │ ╱ each speaks
│ GH Postgres │ ┌────[ MCP ]────┐ ONE protocol
│ Slack CRM │ │ │ │ │
└──────────────┘ GH Postgres Slack CRM
MCP turns N×M into N+M. Every host learns to speak one protocol. Every capability is exposed once, as an MCP server speaking that same protocol. Now any compliant host can use any compliant server with zero bespoke glue. Build a server for your CRM and it instantly works in every MCP-capable application — present and future.
This is the same move USB-C made for hardware: instead of a different cable per device, one connector shape that any device and any port agree on. The phrase you’ll see repeated — “USB-C for AI applications” — is exactly this idea.
Why a protocol, and not a library or a plugin API?
This distinction matters and shows up in design interviews. A library would tie you to one language and one runtime. A vendor plugin API would tie you to one host (you’d build “ChatGPT plugins” or “IDE-X extensions” separately). MCP is an open protocol — a wire format and a set of rules for messages — which buys three things:
- Language-agnostic. The protocol is JSON over a transport. A Python host happily uses a TypeScript server; neither knows or cares about the other’s language.
- Process-isolated and independently deployable. A server is its own program. It can crash, be sandboxed, be updated, or be revoked without touching the host. This isolation is also a security property you’ll lean on heavily in Phase 3.
- Independently versioned. Servers and hosts evolve on their own schedules, and the lifecycle handshake (Module 3) negotiates a compatible version at connection time.
Hold onto that framing: MCP standardizes the connection, not the capability. The cleverness is all in the agreement, not in any one piece of code.
2. The Three Roles
There are exactly three roles. Confusing them is the #1 source of beginner errors, so we’ll be precise.
Host
The host is the AI application the user actually interacts with — a desktop chat app, an IDE assistant, an agent platform, Cowork. The host is the boss. It:
- Owns and runs the LLM (or calls out to a model provider),
- Manages the conversation and the user,
- Decides which servers to connect to,
- Enforces user consent and security policy,
- and decides whether to act on a model’s request to call a tool.
If something “contains the AI,” it’s the host. Servers never do.
Client
A client lives inside the host. It’s the connector component that holds a session with exactly one server — a strict 1:1 relationship. If a host connects to five servers, it runs five clients. The client speaks the protocol: it does the handshake, sends requests, receives responses and notifications, and routes them back into the host. Think of the client as the host’s “port” for one specific server.
Host : clients is 1-to-many. Client : server is 1-to-1. A host with three connected servers = three clients, three sessions.
Server
A server is an external program that exposes capabilities and responds to the client. It offers some combination of tools (actions), resources (readable data), and prompts (reusable templates) — these are the primitives in Modules 4–5. The server:
- does not contain the model,
- is model-agnostic (it works with any host regardless of which LLM is behind it),
- executes work when asked and returns results,
- and stays in its lane: it advertises capabilities and answers requests.
A server can be local (a subprocess on your machine, talking over stdio) or remote (reached over HTTP). Same protocol either way.
┌──────────────────────── HOST (the AI app) ────────────────────────┐
│ │
│ ┌────────────┐ the model decides to call a tool; │
│ │ LLM │ the host approves and routes the call │
│ └─────┬──────┘ │
│ │ │
│ ┌─────┴───────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Client A │ │ Client B │ │ Client C │ (1 per server)│
│ └─────┬───────┘ └──────┬──────┘ └──────┬──────┘ │
└─────────┼──────────────────┼─────────────────┼────────────────────┘
│ MCP │ MCP │ MCP
┌────┴─────┐ ┌──────┴──────┐ ┌─────┴──────┐
│ Server A │ │ Server B │ │ Server C │
│ (files) │ │ (database) │ │ (GitHub) │
└──────────┘ └─────────────┘ └────────────┘
3. Who decides what? (the control flow that everyone gets wrong)
Here is the single most important sentence in this module:
The server does not call the AI. The host’s model decides to use a tool; the client forwards the call; the server merely executes and returns a result.
Picture a user asking, “What’s in my notes.txt?” with a filesystem server connected. The flow is:
- User types the question into the host.
- The host sends the conversation to the LLM, along with the list of available tools it learned from connected servers (e.g. a
read_filetool). - The LLM reasons and decides: “I should call
read_filewithpath: notes.txt.” It doesn’t execute anything — it just emits a request to call that tool. - The host sees this request. It applies policy and (often) asks the user for consent — “Allow reading notes.txt?” The host is the gatekeeper here.
- On approval, the host hands the call to the client connected to the filesystem server.
- The client sends a
tools/callrequest over the protocol to the server. - The server executes — actually reads the file off disk — and returns the contents as a result.
- The client passes the result back to the host, which inserts it into the conversation as context.
- The host sends the updated conversation back to the LLM, which now has the file contents and writes the final natural-language answer.
- The host shows that answer to the user.
User → Host → LLM ("call read_file") → Host (consent gate) → Client
→ [MCP: tools/call] → Server (reads disk) → [MCP: result] → Client
→ Host (adds to context) → LLM (writes answer) → Host → User
Notice the model is consulted twice — once to decide to call the tool, once to use the result. Notice the server is dumb in the best sense: it has no idea there’s an LLM anywhere. It got a read_file request and returned bytes. And notice the host is the security boundary: every consequential action passes through its consent and policy gate. That gate is exactly where, in Phase 3, entitlements and authorization will live.
The one exception: sampling (a preview)
There is one case where the direction inverts — a server can ask the client to run an LLM completion on its behalf. That’s called sampling, and it’s deliberately built so the host still stays in control of model choice, cost, and approval. We cover it properly in Module 5. For now just file the asterisk: “servers don’t have a model — except they can borrow the host’s via sampling, with the host’s permission.”
4. The connection, in one breath (capability negotiation)
You’ll go deep on lifecycle and transports in Module 3, but you need the shape now so the roles feel concrete.
When a host connects a client to a server, they perform a short handshake:
- The client sends an
initializemessage announcing the protocol version it wants and the capabilities it supports (e.g. “I can do sampling, I can provide roots”). - The server replies with a version it accepts and its capabilities (e.g. “I offer tools and resources, and my tool list can change at runtime”).
- The client sends an
initializednotification, and normal operation begins.
This is capability negotiation: each side declares only what it supports, so a feature-rich host and a minimal server still interoperate — they simply use the intersection of what they both understand. Nothing is assumed; everything is advertised. This is why MCP can evolve (new primitives like Tasks in 2025-11-25) without breaking older peers — unknown capabilities are simply not negotiated.
5. Five misconceptions to kill now
- “The server runs the AI.” No. The host owns the model. The server only exposes capabilities and executes requests. (Sampling lets a server borrow the host’s model — it never has its own.)
- “A client is the chat UI.” No. The host is the application/UI. A client is an internal connector with a 1:1 link to one server. One host, many clients.
- “MCP is an API for the model to call.” Backwards. MCP connects the host to servers. The model never speaks MCP; it emits a tool-call request that the host fulfills via a client.
- “More tools connected = automatically better.” No. Every tool’s description enters the model’s context and influences behavior — it’s a reliability and security surface (tool descriptions can carry prompt injection). Curate.
- “A tool failure is a protocol error.” No — different layers. A tool that fails returns a successful protocol response carrying an error flag in its result; a malformed message is a protocol error. You’ll formalize this split in Module 2, and it matters for both UX and security.
6. Milestone exercise
Task: In your own words (no peeking), write a one-page explanation of what happens end-to-end when a user asks a question that requires a tool call. You must correctly use all three roles and name every hop.
Then check yourself against this rubric — a strong answer mentions:
- The host sends the conversation plus the available tool list to the model.
- The model decides to call a tool and emits a request — it does not execute it.
- The host applies policy / asks the user for consent before acting.
- The client (1:1 with that server) sends
tools/callover the protocol. - The server executes and returns a result; it has no knowledge of the LLM.
- The result goes back into context and the model is consulted a second time to write the answer.
- You did not claim the server “called the AI.”
Stretch (do this — it cements everything): redraw the diagram from Section 3 from memory, then write one sentence each on: why a protocol beats a library, why client:server is 1:1, and where the security boundary sits.
If you can do the milestone cleanly, you’re ready for Module 2 — JSON-RPC 2.0 & the message layer, where we drop from concepts down to the actual bytes on the wire and hand-write these messages.
Quick reference — Module 1 glossary
- Host — the AI application; owns the model, the user, and the consent/security gate.
- Client — connector inside the host; 1:1 with one server; speaks the protocol.
- Server — external program exposing tools/resources/prompts; model-agnostic; no LLM of its own.
- N×M → N+M — the integration-explosion problem MCP collapses by standardizing the connection.
- Capability negotiation — the
initializehandshake where each side advertises version + supported features; peers use the intersection. - Sampling (preview) — the one inverted flow: a server asks the client to run a model completion, with the host still in control.