MCP server architecture
MCP is a client-host-server architecture built on JSON-RPC. The naming trips people up, because the part you install — the "server" — is usually the smallest piece, and the application you're actually using is the host that orchestrates everything.
For the plain-language version, start with what an MCP server is.
The three roles
- Host
- The application you interact with — Claude Desktop, Cursor, an agent you wrote. It creates and manages client instances, controls connection permissions, enforces security policies and consent, handles authorization decisions, coordinates the model, and aggregates context from every connection.
- Client
- Created by the host, one per server, each holding a single stateful session. It performs the protocol negotiation, routes messages in both directions, manages subscriptions and notifications, and keeps servers isolated from one another.
- Server
- The focused piece that exposes resources, tools and prompts. It operates independently, can ask the client for model completions through sampling, and may run as a local process or a remote service.
One host runs many clients, and each client has a strict 1:1 relationship with one server. That's not an implementation detail — it's the boundary that keeps two servers connected to the same assistant from seeing each other.
How a session starts
A session opens with capability negotiation. The client sends an initialize request declaring what it supports, and the server replies with its own capabilities. Each side must respect what the other declared for the rest of the session: a server that never declared tool support won't be asked to run one, and sampling only happens if the client said it could handle it.
After that, traffic runs in both directions. The client sends requests for tools and resources on behalf of the user or the model; the server can send requests of its own — most notably sampling, asking the client to run a model completion — and either side can push notifications, such as a server signalling that a resource changed or that its tool list is now different.
The design principles
Four principles shape the protocol, and the third is the one that matters most for anyone weighing up what a server can see:
- Servers should be extremely easy to build
- The host carries the complex orchestration, so a server only has to implement its own narrow capability against a simple interface.
- Servers should be highly composable
- Each provides focused functionality in isolation, and the shared protocol lets any combination of them work together.
- Servers cannot read the whole conversation or see other servers
- The full history stays with the host; a server receives only the context a given request needs, and cross-server interaction is controlled by the host rather than negotiated between servers.
- Features are added progressively
- The core protocol is deliberately minimal, with anything beyond it negotiated as a capability — so clients and servers can evolve independently without breaking each other.
The two standard transports
- stdio
- The client launches the server as a subprocess and exchanges newline-delimited JSON-RPC messages over its standard input and output, with standard error left free for logs. The specification says clients should support this transport wherever possible.
- Streamable HTTP
- The server runs independently and exposes a single endpoint handling both POST and GET. It answers with either one JSON object or a server-sent-events stream when it needs to send several messages. This replaced the earlier HTTP+SSE transport.
Both are just carriers. The protocol is transport-agnostic — custom transports are explicitly allowed, as long as they preserve the JSON-RPC message format and the session lifecycle — which is why the same server logic can be exposed either way.
Frequently asked questions
›What protocol does MCP use underneath?
JSON-RPC, carried over whichever transport is in use, with messages required to be UTF-8 encoded. MCP layers a stateful session on top of it — a session begins with an initialization exchange and both sides keep state for its duration, which is what allows subscriptions and server-initiated requests.
›What's the difference between an MCP host and an MCP client?
The host is the application — it owns the model, the conversation and the security decisions, and it creates clients. A client is the connection layer the host spins up, one for each server, handling negotiation and message routing for that single session. In everyday use people say "client" for the app itself, but the specification separates the two.
›What is capability negotiation in MCP?
At the start of a session each side declares which protocol features it supports — a server might declare tools, prompts or resource subscriptions; a client might declare sampling. Both must then respect those declarations for the whole session, so a feature that wasn't declared simply isn't available. It's what lets the protocol add features without breaking older implementations.
›Can an MCP server send requests to the client?
Yes. The clearest example is sampling: the server asks the client to run a model completion on its behalf, and the client — not the server — decides whether to allow it and forwards the result. Servers can also push notifications, for instance when a resource updates or their tool list changes.
›Can two MCP servers connected to the same app see each other?
No. Each server has its own client and its own session, and the architecture states plainly that servers should not be able to see into other servers or read the whole conversation. Any interaction between them is mediated by the host, which is what keeps one server's data out of another's reach.