Host, client and server
Before any wire format, get the cast right: three roles, six primitives, and one direction. MCP is a switchboard for agents: one message per line, a signed ticket in the client's hand, every call placed by the client.
By the end of this lesson you can
- name the three roles and say what each one owns;
- explain why the model is neither client nor server;
- list the six primitives, which side offers each, and who controls it;
- picture the same protocol at three sizes: spawned, hosted and scaled.
Three roles
Host, client and server are roles on one connection, not kinds of machine. The diagram builds up a typical setup: one host connected to a server on your own machine and one across the internet.
Who talks to whom
- The host is the application you run. It owns the model, the user interface and consent.
- Inside it sits the model. It only ever sees tool names, descriptions and schemas as text in its prompt.
- For every server, the host creates one client: a connector object that speaks MCP. Two servers, two clients.
- Client A started a local server on your machine, as a child process, and talks to it over its stdin and stdout. That process runs with your operating-system permissions.
- Client B talks to a remote server on someone else's machine, across the internet: a URL over Streamable HTTP, with a bearer token on every request.
- Remote servers trust tokens issued by an authorization server. Local stdio servers never use one: their credentials come from the environment.
- When the model wants a tool, it emits a
tool_useblock. The host routes it through the right client, which sendstools/callto the right server. - The result comes back the same way and lands in the conversation as a
tool_result. The model never spoke MCP.
| Role | Is | Does |
|---|---|---|
| Host | Claude Desktop, Claude Code, an IDE, your own agent | Owns the model, the user interface and consent. Starts or connects to servers. Decides what goes in the prompt. |
| Client | A connector object inside the host, one per server | Speaks the protocol: sends server/discover, tools/list, tools/call; handles input-required retries. |
| Server | Any process or endpoint that answers those methods | Runs your code: calls an API, queries a database, reads files. Returns results as structured content. |
Key idea
These are roles on one connection, not kinds of machine. The same program can be a server to Claude and a client to something else, for example a gateway that is a server to your IDE and a client to five other servers.
The model is neither client nor server
The model never opens a connection and never sees JSON-RPC. It only ever sees tool names, descriptions and schemas as text in its prompt, and emits “call this tool with these arguments”. The host turns that into a protocol message, after asking you if it needs to.
Common misconception
“Claude connects to the MCP server.” Claude the application (the host) does. Claude the model only reads text and writes a tool-use block. That split is why consent, routing and naming are the host's job, and why a tool description is effectively part of your prompt.
Six primitives, three in each direction
Everything MCP carries is one of six primitives. The server offers three; the client offers three. Each one has a different controller, which tells you who decides when it is used.
Who offers what, and who decides
- The server offers tools (the model decides to call one), resources (the application decides what to attach) and prompts (the user picks one).
- The client uses them with ordinary requests:
tools/call,resources/read,prompts/get. - The client offers sampling (the server borrows the host's model), elicitation (the server asks the user) and roots (which folders are in bounds).
- In the current revision, servers may no longer start requests, so the server asks for these inside an
input_requiredresult. Lesson 6 shows exactly how.
Explore the six primitives
Pick a primitive to see who offers it, who controls it, and what it looks like on the wire.
Tools
Offered by the server. The model decides when to call one.
Functions with a JSON Schema. The host puts their names and descriptions in the prompt; the model emits a call; the client sends tools/call.
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"deploy","arguments":{"env":"prod"}}}
Resources
Offered by the server. The application decides what to attach.
Readable data addressed by URI: files, rows, documents. Read with resources/read; changes arrive through subscriptions/listen.
{"jsonrpc":"2.0","id":4,"method":"resources/read","params":{"uri":"config://app"}}
Prompts
Offered by the server. The user picks one, often as a slash command.
Templated messages with arguments. prompts/get returns ready-made messages for the conversation.
{"jsonrpc":"2.0","id":5,"method":"prompts/get","params":{"name":"review","arguments":{"code":"…"}}}
Sampling
Offered by the client. The server asks the host's model for a completion.
Lets a server use an LLM without holding its own API key. In 2026-07-28 it arrives inside an input_required result, never as a server-initiated request.
Inside an input_required result:
{"inputRequests":{"summary":{"method":"sampling/createMessage","params":{"messages":[{"role":"user","content":{"type":"text","text":"Summarise this diff"}}],"maxTokens":200}}}}
Elicitation
Offered by the client. The server asks the user a question.
A form (or a URL) shown by the host: confirm a deploy, pick an account. The answer comes back in the client's retry as inputResponses.
Inside an input_required result:
{"inputRequests":{"confirm":{"method":"elicitation/create","params":{"mode":"form","message":"Deploy to prod?","requestedSchema":{"type":"object","properties":{"confirm":{"type":"boolean"}}}}}}}
Roots
Offered by the client. The server learns which folders it may touch.
The boundaries the user has opened, such as the project directory. Also requested through input_required in the current revision.
Inside an input_required result:
{"inputRequests":{"where":{"method":"roots/list"}}}
One protocol, three sizes
The same JSON-RPC messages run in a child process on your laptop and across a fleet behind a load balancer. Only the transport and the operations change.
- Spawned: a local stdio server. The host starts it as a subprocess and talks over stdin and stdout.
- Hosted: one remote endpoint at
/mcp. Every message is its own HTTP POST with a bearer token. - Scaled: many identical replicas, routing like an automatic exchange. Since revision 2026-07-28 no request depends on the one before it, so any replica can answer.
Quick check
Claude Desktop has two MCP servers configured. How many MCP clients exist?
Who actually reads a tool's description and decides to use it?
A deploy tool wants the user to confirm before it runs. Which primitive is that, and which side offers it?
input_required result.True or false: one program can be an MCP server and an MCP client at the same time.
Recap
- The host owns the model, the UI and consent; it keeps one client per server; a server runs your code.
- The model is neither client nor server: it reads tool text and emits tool calls; the host does the protocol.
- Servers offer tools (model decides), resources (application decides) and prompts (user picks); clients offer sampling, elicitation and roots.
- The same messages run spawned, hosted or scaled; only the transport changes.