MCP 2026-07-28 one lesson per page
23 lessons
Core conceptArchitecture · FundamentalsTrack 1 · 1 / 9

Who does what: hosts, clients and servers

Every MCP question gets easier once you know which of the three parts is responsible. The host is in charge, each client talks to exactly one server, and a server sees only what it is given.

Listen to this lessonAudio overview in Gemini Notebook · about 15–25 min · opens in a new tab

The travel assistant with three servers

Your travel assistant app connects to three MCP servers: Calendar, Email and Flights. The app is the host. Behind the scenes it creates three clients, one per server.

You say "book me a flight to Lisbon after my Thursday meeting". The host asks Calendar for Thursday, hands the model the combined tool list, and when the model picks book_flight, the host shows you a confirmation before anything is charged.

Now suppose the Flights server is compromised. What can it see? Only the arguments of its own tool calls: {"to": "LIS", "date": "2026-10-09"}. Not your emails, not the calendar, not the rest of the chat. That isolation is a design principle, not luck: servers should not be able to read the whole conversation, nor "see into" other servers.

  • Host: "acts as the container and coordinator". It creates and manages client instances, controls connection permissions, enforces security policies and consent requirements, handles user authorization decisions, coordinates the LLM, and aggregates context across clients.
  • Client: "communicates with exactly one server". The spec calls this a 1:1 relationship. It attaches the protocol version and capabilities to every request, and maintains security boundaries between servers.
  • Server: exposes tools, resources and prompts, may ask the client for input (elicitation, sampling, roots) through input_required, and can be a local process or a remote service.

Four design principles, worth knowing word for word: servers should be extremely easy to build (the host does the orchestration), highly composable, unable to read the whole conversation or "see into" other servers, and features can be added progressively.

In practice a local server on stdio usually serves one client; a remote server on Streamable HTTP usually serves many.

Splitting the roles puts the hard, trust-sensitive work (consent, model access, combining context) in one place, the host, which the user already trusts. Servers stay small and replaceable. Isolation means one bad server can't read everything else.

The model interaction flow
UserHost + LLMMCP servertools/listtools (merged into one registry)"What's the weather in SF?"The LLM chooses weather_currentconfirm: run weather_current?yestools/call weather_currentresultanswer, using the result
Solid arrows are requests, dashed are responses or notifications. Red ✕ is the unsafe or failing step; green is the step that keeps you safe.

What the server actually receives

Examplerequest from the host's client
{  "jsonrpc": "2.0",  "id": 3,  "method": "tools/call",  "params": {    "name": "weather_current",    "arguments": {      "location": "San Francisco",      "units": "imperial"    },    "_meta": {      "io.modelcontextprotocol/protocolVersion": "2026-07-28",      "io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },      "io.modelcontextprotocol/clientCapabilities": { "elicitation": {} }    }  }}

Verbatim from the architecture guide. Notice what is not here: the user's question, the chat history, other servers' data. Just the tool name and its arguments.

What goes back to the model

Exampleresponse
{  "jsonrpc": "2.0",  "id": 3,  "result": {    "resultType": "complete",    "content": [      {        "type": "text",        "text": "Current weather in San Francisco: 68°F, partly cloudy with light winds from the west at 8 mph. Humidity: 65%"      }    ]  }}
  • Consent in the wrong place. A server that pops up its own "are you sure?" can't be trusted to; confirmation is the host's job.
  • Asking for context it shouldn't need. A tool that takes "the full conversation" as a parameter breaks isolation. Ask for the specific value instead.
  • One client, many servers. Clients are 1:1. Sharing one across servers mixes capabilities and security boundaries.
  • Trusting clientInfo. It's self-reported, for display and logs, never for security decisions.
First time here? Set up the test helper (once per terminal)
ShellSetup
# 1. In a SECOND terminal, start the reference server (Node 18+, no dependencies)curl -sO https://www.diegozuluaga.dev/mcpa/reference-server.mjsnode reference-server.mjs                 # http://localhost:3000/mcp, logs appear here # 2. In THIS terminal, define the helper every test uses (bash or zsh)export MCP=http://localhost:3000/mcpMETA='"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}'mcp() {  # usage: mcp <method> '<json body>' [extra curl args...]  curl -sS -N "$MCP" \    -H 'Content-Type: application/json' \    -H 'Accept: application/json, text/event-stream' \    -H 'MCP-Protocol-Version: 2026-07-28' \    -H "Authorization: Bearer ${MCP_USER:-alice}" \    -H "Mcp-Method: $1" "${@:3}" -d "$2" \    -w '\nHTTP %{http_code}\n'}# Demo auth: the reference server treats the bearer token as the user's name.# Prefix a command with MCP_USER=bob to act as someone else.

Play the host: discover what the server offers, then call one tool the way a host would after the model chose it.

ShellTests
# 1. What would the host merge into the model's tool registry?mcp tools/list '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{'"$META"'}}' | grep -o '"name":"[a-z_]*"' # 2. The model picked get_weather; the host (after asking you) calls itmcp tools/call '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_weather","arguments":{"location":"San Francisco"},'"$META"'}}' -H 'Mcp-Name: get_weather'# expect: a result with content. The server never saw your question, only the arguments.

Answer all 4 correctly and this lesson is marked as learned.

Q1Which component enforces user consent before a tool runs?

Q2How many servers does a single MCP client talk to?

Q3Spot the problem: a server's summarise tool takes a "conversation" parameter and asks the host to send the full chat history every time.

Q4A local MCP server launched over stdio typically serves…

Feedback or a correction? Email diego [at] diegozuluaga [dot] dev or open an issue on GitHub.

Content CC BY 4.0 · Code MIT

Tip: ← and → move between lessons. Hover any heading and press # to copy a link to it.