Breaking down MCP's three-layer architecture — Host, Client, and Server — along with its main primitives like Tools, Resources, and Prompts, plus the transports connecting them all: Streamable HTTP, SSE, and stdio.

After understanding MCP's history and motivation in episode 1, it's time to break down how this protocol actually works. This episode is the most important foundation in the entire series: the three-layer architecture and the primitives we'll keep using through the last episode.
You'll learn who plays what role (Host, Client, Server), what a server can expose (tools, resources, prompts), and through which medium they communicate (transport). Understand this episode, and every following episode — from SDK to deployment — is just implementation detail.
MCP is built on three well-defined roles:
| Role | Description | Examples |
|---|---|---|
| Host | The user-facing application where users interact with the model | Claude Desktop, IDEs, chat applications |
| Client | The component that maintains a 1:1 connection with a single server, inside the host | Client SDK inside the application |
| Server | The program that exposes capabilities (tools, resources, prompts) | Weather server, database server, GitHub server |
The golden rule: one client connects to one server. If a host wants to talk to many servers, the host has many clients — each with its own connection. No single client connects to many servers at once.
From the model's point of view, the communication flow is: the model lives inside the host, the host uses a client to call the server, and the server responds back to the host through the client. You can think of the client as the "cable" and the server as the "socket" — each cable plugs into one socket.
An MCP server exposes three main primitives:
| Primitive | Function | Analogy |
|---|---|---|
| Tools | Functions the model can call to perform an action | The server's hands for acting |
| Resources | Formatted data the model can read as context | The server's library |
| Prompts | Reusable templates that help users complete tasks | Ready-made guides/recipes |
Tools are functions the model can call to perform an action: write a file, send an email, run a query, call an external API. Tools are described with JSON Schema so the model knows which parameters to fill in. We'll cover tools in depth in episode 4.
Resources are context data the model can read — like file contents, query results, or documentation. Unlike tools, which perform actions, resources are passive: the model reads, it doesn't execute. An example method: resources/read. Episode 5 covers this.
Prompts are reusable templates designed to complete specific tasks — for example, a "summarize meeting" template or "generate commit message". The host shows a list of prompts to the user, then the template with specific arguments is sent to the model. Details in episode 5.
Info
In the legacy era (specifications up to 2025-11-25), there were three additional primitives: Roots (announcing file locations to the server), Sampling (the server asks the model to create a completion), and Logging (log delivery). All three are now officially deprecated and have a "removal clock" of around one year. Episodes 3 and 17 will cover the transition period.
Primitives only make sense when there's a medium connecting them. MCP has three transport options:
Streamable HTTP is the standard transport for remote servers in the modern era. It uses regular JSON-RPC request/response over HTTP, plus an SSE stream for notifications and streaming long-running results. Servers can be stateless, easy to scale, and it forms the foundation of the 2026-07-28 era.
Server-Sent Events (SSE) is MCP's original transport when it first shipped on 2024-11-05. It relies on a long-lived SSE connection and has been considered legacy since 2025-03-26 — still supported for compatibility, but not the choice for new servers. Each SSE endpoint serves only one client, which limits scalability.
stdio runs the server as a local subprocess and communicates over stdin/stdout. It's the simplest transport and suits local integration — for example CLI agents, editors, and developer tooling. Data is sent as one JSON message per line, with no network required.
| Transport | Location | Stateless? | Example Use Cases |
|---|---|---|---|
| Streamable HTTP | Remote | Yes (modern era) | Production servers, web integration |
| SSE | Remote | No | Legacy servers, compatibility |
| stdio | Local | Yes | CLI agents, editors, local tooling |
Let's follow one simple MCP conversation from start to finish. Imagine a model (inside a host) wants to know today's weather:
tools/list through the client to see which tools the weather server offers.get_weather, requiring a city parameter.tools/call with the user's city as the argument.{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "get_weather",
"description": "Ambil cuaca terkini untuk sebuah kota",
"inputSchema": {
"type": "object",
"properties": {
"city": { "type": "string" }
},
"required": ["city"]
}
}
]
}
}All these steps are nothing more than JSON-RPC request/response — as you already know from episode 0. The transport only determines where this JSON-RPC is sent: over HTTP, SSE, or stdin. In episode 7 we'll observe this flow directly via npx @modelcontextprotocol/inspector.
In this episode 2 you've understood MCP's three-layer architecture (Host, Client, Server), the three main primitives (tools, resources, prompts), deprecated primitives (roots, sampling, logging), and the three transport options (Streamable HTTP, SSE, stdio) along with when to use each.
Key takeaways:
In the next episode 3 we'll cover the MCP connection lifecycle — how a connection starts, what session state was in the legacy era, and how the stateless era of 2026-07-28 changed everything with server/discover. See you in episode 3!