MCP Host
The six responsibilities the specification gives the host, why one client per server is the isolation boundary, and what happens when a server asks you for a completion.
Host, client, server, and which one you are writing
Three roles, and if you are building an AI application, you are writing the host.
MCP in one sitting introduces the three roles and the diagram that goes with them. In short: a server exposes capabilities, a client is one connection to one server, and the host is the application that owns the model loop and spawns the clients.
The server side gets most of the attention, because that is what people build and publish. But the specification is explicit that the asymmetry is deliberate. "Host applications handle complex orchestration responsibilities" while servers "focus on specific, well-defined capabilities". That is one of the protocol's stated design principles, written so that "Servers should be extremely easy to build."
Easy for servers means the work went somewhere. It went to you.
The six things the host owns
The specification lists them. Quoted directly, the host process:
- "Creates and manages multiple client instances"
- "Controls client connection permissions and lifecycle"
- "Enforces security policies and consent requirements"
- "Handles user authorization decisions"
- "Coordinates AI/LLM integration and sampling"
- "Manages context aggregation across clients"
Read that list as a division of labor. The first two are plumbing. The middle two are the reason the host exists at all: no other role in the protocol is in a position to ask a person whether something should happen. The fifth says the host is the only party holding a model. The sixth, deciding what each server and the model are allowed to see, is the hardest, and most of what follows is about it.
Why one client per server is the isolation boundary
Each client maintains exactly one connection to exactly one server. A host running five servers runs five clients.
That sounds like bookkeeping and is the security model. The specification states it as a design principle: "Servers should not be able to read the whole conversation, nor 'see into' other servers." Three consequences follow from it, all in the specification's own words: "Full conversation history stays with the host", "Cross-server interactions are controlled by the host", and "Host process enforces security boundaries."
So when a server returns something, it has seen the arguments of the call it was given and nothing else. It does not know what the user asked, what other servers are connected, or what any of them returned. A server that turns hostile reaches one connection's worth of surface.
That property exists only because the host preserves it. Aggregate the results of three servers into one blob and hand it to a fourth, and you have dismantled the boundary the protocol built.
When the server asks the host for something
Most of the traffic runs one way: the client asks, the server answers. There is a reverse direction, and in the current revision it has a shape worth understanding before you design around it.
A server can need something only the host has. The named cases are sampling, where the server wants a model completion; elicitation, where it needs input from the user; and roots, where it asks which directories it is allowed to work in. A translation server that wants a model to do the translating is asking for sampling. It has no model of its own, and the host does.
The mechanism is not a callback. Revision 2026-07-28 routes these through
replies: servers "Request client input (sampling, elicitation, roots) via
InputRequiredResult within a reply." The stdio transport is blunt about why:
"The server MUST NOT write JSON-RPC requests to stdout." So the server
returns a reply that says it needs something, the client obtains it, and the
client re-sends the original request with the input attached.
Sampling is the interesting one, and not for protocol reasons. A server asking for sampling is asking you to spend your tokens running a prompt it wrote, and to do it inside your model loop. Whether to allow that, whether to show the user first, and whether to cap it are host decisions, and nothing in the protocol makes them for you.
Choosing which tools the model sees
The sixth responsibility, "Manages context aggregation across clients", is where hosts differ from one another.
Five connected servers might expose sixty tools between them. Putting all sixty in front of the model on every request has two costs that pull in the same direction. It spends context on descriptions of tools that are irrelevant to the current task, and it gives the model more chances to pick a plausible wrong tool. Context engineering makes the general argument that more context is not better; a tool list is a concrete case of it.
The alternatives are all selection strategies: filter by the servers relevant to the current task, let the user enable and disable servers, or select tools by matching the request. Which one is right depends on your application, but the decision is unavoidable. Presenting all of them is itself a choice, and usually the worst one.
Server output is untrusted input
A tool result is text from somewhere else that is about to enter your model's context. It is input, and it did not come from you.
MCP server develops this from the server's side. From the host's side it is a boundary problem: your system prompt, the user's message, and a server's response all arrive as tokens, and the model has no reliable way to rank them by trustworthiness. A document fetched by a search server that contains instructions is a document that may get followed. Simon Willison's prompt injection writing is the long-form case.
What the host can do is refuse to erase the distinction. Keep the boundary between instruction and fetched content explicit in how you assemble the prompt, as providing context describes; require confirmation for consequential actions rather than for all of them, so the confirmation still means something; and keep server results inside the sub-task that needed them rather than letting them accumulate in the main conversation.
None of that is in the specification. It is the part that is yours.
Further reading
- MCP, Architecture, revision 2026-07-28: the role definitions, the six host responsibilities, and the isolation principle. Every quotation above comes from here or from the stdio page below.
- MCP, stdio transport, revision 2026-07-28: why server-to-host requests travel inside replies.
- MCP server: the other side of this boundary.
- Connect to a local server: the same roles, from the configuration file.
Knowledge check
Question 1 of 4
Sign in to save your progress and pick up where you left off.