MCP's architecture is a triangle. Three roles, three responsibilities, and a strict rule about who talks to whom.
- Host — the application the user actually uses. Claude Desktop, VS Code with Copilot, Cursor, your custom assistant. The host owns the user experience, runs the LLM (or the API call to it), and is responsible for security decisions like asking the user to approve tool runs.
- Client — a piece of code inside the host that speaks MCP to one server. A host that uses three MCP servers maintains three client objects, one per connection. Clients are paired 1:1 with servers; they are not pooled.
- Server — a separate process (or remote service) that exposes tools, resources, and prompts to a client. A weather server, a GitHub server, a Postgres server. Servers know nothing about each other; they each speak only to their paired client.
The strict rule is: a server never talks to another server, and a server never reaches the host directly. All cross-server coordination goes through the host. This is on purpose. It keeps every server's blast radius bounded — the worst a malicious or buggy server can do is misbehave to the one client that hosts it. The host is the security boundary; the protocol enforces it by topology.
Two consequences fall out of this. First, capability composition is the host's job: if the user asks "look up this user in Postgres and post their summary to Slack," the host orchestrates one tool call to the Postgres server, then one to the Slack server. Neither server learns about the other. Second, permissions are per-server: granting "read code" to a GitHub server does not grant the same to a filesystem server, and vice versa. The triangle is the trust model.