MCP client, server & host
In the Model Context Protocol, the host is the AI application (Claude Desktop, an IDE assistant, your own agent) that the user interacts with; it spawns one MCP client per connection; and each client talks to exactly one MCP server, the service that exposes tools, resources and prompts. The host owns the model and the trust boundary, the client is the protocol connector that performs the JSON-RPC 2.0 capability handshake, and the server is the capability provider — usually the only one of the three you do not control.
The three roles, precisely
The Model Context Protocol (an open JSON-RPC 2.0 protocol introduced by Anthropic) defines three roles. The host is the AI application the user actually runs — Claude Desktop, an IDE coding assistant, a chat client, or an agent you built. It owns the language model, the conversation, the user's consent, and the security boundary; nothing reaches the model except through the host.
The client is the connector the host instantiates to speak MCP. It is not a separate program you install — it is a component inside the host. Each client maintains a single stateful 1:1 session with one server: it sends the initialize handshake, negotiates capabilities, and then relays tools/list, tools/call, resources/read and prompts/get requests.
The server is the capability provider. It exposes tools (callable functions with JSON-Schema inputs), resources (readable data addressed by URI) and prompts (reusable templates). A server can run as a local subprocess or a remote HTTP service, and it is typically the only one of the three roles written by a third party.
How a connection is established
When a host decides to use a server, it creates one MCP client for it and opens a transport. The client sends an `initialize` request carrying its supported protocol version and capabilities; the server replies with its own version and the capabilities it offers (tools, resources, prompts, and optional features like logging). This capability handshake is what lets the two sides agree on what is supported before any real work happens.
After the handshake, the client calls `tools/list` to discover the server's tools, plus `resources/list` and `prompts/list` where offered. The host feeds those tool names, descriptions and schemas into the model's context so the model knows what it can call. When the model chooses a tool, the host asks the client to issue `tools/call`, and the server's response flows back into context.
A host commonly runs many clients at once — one per server — so an agent can compose first-party and third-party servers in a single session. Crucially, the model never opens a socket itself: every external capability is mediated by a client the host controls, which is the natural place to enforce policy.
Why the boundary matters for trust
The host is the trust boundary, and the server sits on the other side of it. A server's tool descriptions are read into the model's context, and its tool outputs are read back as data — both are text the model may treat as instructions. So an untrusted server is an attack surface even though the user only ever interacts with the host.
This is what makes the host-client-server distinction more than terminology. Tool poisoning (hidden instructions in tool metadata), prompt injection delivered through tool output, leaked secrets in schemas, and the lethal trifecta all arrive across the client-server link, not from the user. The host is responsible for not blindly trusting whatever a server returns.
The practical takeaway for developers: you control the host and the client, but you usually inherit the server. Audit a server before wiring it in, and re-check it over time, because a server can silently change the tools it advertises (a rug pull) after you have already approved it.
Local vs remote servers and transports
Where the server runs determines the transport the client uses. The `stdio` transport runs the server as a local subprocess and exchanges JSON-RPC over stdin/stdout — common for desktop tools and anything that touches your filesystem or local credentials. The client launches the process and owns its lifecycle.
Remote servers are reached over HTTP. The current transport is Streamable HTTP; the older HTTP+SSE pairing is the legacy variant. Remote servers may sit behind OAuth 2.1 or a bearer token, and the client handles that authorization on the host's behalf.
The role split is identical regardless of transport: the host runs a client, the client handshakes and discovers, the server exposes capabilities. What changes with a remote server is the threat model — network exposure, third-party operators, and the possibility that the tool list you see today is not the one you saw yesterday.
How CheckMCP handles it
The host-client-server split is exactly where CheckMCP plugs in: the server is the component you usually do not control, so CheckMCP audits it from the outside the way a client would. It performs the same MCP capability handshake a real client does, then discovers and inspects the server's tools, resources and prompts, and produces an explainable MCP Score /100 (grade A-F) — seven weighted pillars for a live endpoint (security 20, tool design 18, schemas/descriptions 16, reliability 14, context-cost 12, compliance 12, coverage 8) or four for a repo/stdio server (maintenance 40, license 25, adoption 20, documentation 15). The security pillar runs an OWASP MCP Top 10 pass (tool poisoning, hardcoded secrets, command injection, the lethal trifecta) with hard floors — a secret found in a tool schema caps the grade at D, a failed handshake caps it at F — and the opt-in behavioral evals exercise read-only tools with canary inputs to catch prompt-injection or data-exfiltration in tool responses. You run it as `uvx checkmcp <url>` (open-source, MIT, stdlib-only), at checkmcp.dev, or in CI via the `uses: H129hj/checkmcp@v1` GitHub Action to fail a build on a score regression or rug-pull. For runtime protection, the in-band Gateway sits between your host and the server (the position a client occupies) and, in passive and active modes, blocks tool-poisoning and drift before it reaches your agent, with continuous drift monitoring on tracked servers.