MCP Architecture: Hosts, Clients, and Servers
Understand the MCP architecture: hosts, clients, servers, transport layers, and JSON-RPC communication. Learn how the pieces fit together before writing code.
Premium Course Content
This lesson is part of a premium course. Upgrade to Pro to unlock all premium courses and content.
- Access all premium courses
- 1000+ AI skill templates included
- New content added weekly
Before writing code, you need a mental model of how MCP works. This lesson maps the architecture — every component, how they communicate, and why it’s designed this way.
Think of it like understanding how a web server works before building your first website. The concepts are straightforward, and they’ll make everything in later lessons click.
The Three-Layer Architecture
MCP has three distinct roles:
Host
The Host is the AI application the user interacts with — Claude Desktop, Claude Code, ChatGPT, or any MCP-compatible tool.
The Host:
- Manages the overall context and conversation
- Decides which MCP servers to connect to
- Controls permissions (which tools can be called, which data accessed)
- Presents tool results back to the user
Think of the Host as the manager. It delegates work but stays in control.
Client
The Client lives inside the Host and handles protocol communication. Each Client maintains a 1:1 connection with one Server.
The Client:
- Sends requests to the server (e.g., “call this tool with these parameters”)
- Receives responses and notifications
- Handles capability negotiation during connection setup
- Manages the lifecycle (initialize → use → shutdown)
If the Host connects to three MCP servers (database, GitHub, filesystem), it creates three separate Clients — one per server.
Server
The Server is what you build. It exposes capabilities that AI assistants can use.
The Server:
- Advertises its capabilities during initialization (“I have these tools, these resources, these prompts”)
- Executes tool calls when requested
- Returns data from resources when asked
- Provides prompt templates on request
✅ Quick Check: If Claude Desktop connects to a Postgres MCP server and a Slack MCP server simultaneously, how many MCP Clients are created? (Answer: Two — one Client per Server connection. Each Client maintains a 1:1 relationship with its Server.)
The Connection Lifecycle
Every MCP connection follows this sequence:
1. INITIALIZE
Client → Server: "Here's my protocol version and capabilities"
Server → Client: "Here's my version and what I offer"
Client → Server: "Initialized" (confirmation)
2. OPERATE
Client → Server: "Call tool X with params Y"
Server → Client: "Here's the result"
(repeated as needed)
3. SHUTDOWN
Client → Server: "Closing connection"
(clean disconnect)
During initialization, the server tells the client exactly what it can do. This is called capability negotiation — the server advertises its tools, resources, and prompts, and the client knows what’s available before making any requests.
JSON-RPC 2.0: The Message Format
Under the hood, every MCP message is JSON-RPC 2.0. Here’s what a tool call looks like:
Client sends a request:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "city": "Tokyo" }
}
}
Server responds:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [{
"type": "text",
"text": "Tokyo: 22°C, partly cloudy"
}]
}
}
You don’t write this JSON manually — the SDKs handle it. But understanding the format helps when debugging.
✅ Quick Check: In JSON-RPC 2.0, what does the
idfield do? (Answer: It matches requests to responses. When the client sends a request withid: 1, the server includesid: 1in its response so the client knows which request it’s answering.)
Transport Layers
Transport is how the Client and Server exchange messages. MCP supports two:
stdio (Standard Input/Output)
The simplest transport. The Host launches the Server as a child process, and they communicate through stdin and stdout:
Host → spawns Server process
Client writes JSON to Server's stdin
Server writes JSON to Client's stdout
Use when: The server runs locally on the same machine. This is the default for Claude Desktop and Claude Code.
Advantage: No network setup, no authentication needed, instant startup.
Limitation: Single client only. The server process belongs to one Host.
Important gotcha: Never use console.log() in a stdio server. It writes to stdout and corrupts the JSON-RPC message stream. Use console.error() (which writes to stderr) for debugging.
Streamable HTTP
For remote servers. The client connects over HTTP, and the server can stream responses back:
Client → HTTP POST to server URL
Server → streams responses back
Use when: The server runs on a different machine, multiple clients need access, or you’re deploying to production.
Advantage: Works over networks, supports multiple clients, can add authentication.
Limitation: More complex setup — needs HTTP server, potentially TLS, authentication.
| Feature | stdio | Streamable HTTP |
|---|---|---|
| Setup complexity | Minimal | Moderate |
| Network required | No | Yes |
| Multiple clients | No | Yes |
| Authentication | Not needed | Required for production |
| Best for | Local dev, single user | Production, multi-user |
The Three Primitives (Preview)
MCP servers expose capabilities through three primitives. We’ll cover each in depth in later lessons, but here’s the overview:
| Primitive | Controlled By | What It Does | Example |
|---|---|---|---|
| Tools | Model (AI decides when to call) | Execute actions, return computed results | query_database, send_slack_message |
| Resources | Application (client fetches) | Provide data and context | Database schemas, config files, docs |
| Prompts | User (explicitly selected) | Reusable interaction templates | “Analyze this SQL query”, “Review this PR” |
The key distinction: Tools are called by the AI model during a conversation. Resources are fetched by the client application to provide context. Prompts are selected by the user as starting points.
Putting It All Together
Here’s a complete flow when you ask Claude “What’s the weather in Tokyo?”:
- You type the question in Claude Desktop (the Host)
- Claude recognizes it needs the weather tool from the connected MCP server
- The Client sends a JSON-RPC request:
tools/callwithget_weatherandcity: "Tokyo" - The request travels over stdio (local) or HTTP (remote) to the Server
- The Server calls a weather API, formats the result
- The Server sends a JSON-RPC response back through the transport
- The Client receives the result and passes it to Claude
- Claude presents the answer: “It’s 22°C and partly cloudy in Tokyo”
The user never sees the protocol. They just ask a question and get an answer — with real data from an external service.
Key Takeaways
- MCP has three layers: Host (AI app), Client (protocol handler), and Server (your code)
- Each Client connects to exactly one Server (1:1 relationship)
- Connections follow a lifecycle: initialize → operate → shutdown
- Messages use JSON-RPC 2.0, but SDKs handle the formatting
- Two transports: stdio for local development, Streamable HTTP for production
- Three primitives: Tools (model-controlled), Resources (app-controlled), Prompts (user-controlled)
Up Next
In the next lesson, you’ll build your first MCP server — a working tool that Claude can call — in under 50 lines of code.
Knowledge Check
Complete the quiz above first
Lesson completed!