Protocols
MCP in practice: what the protocol is actually for
The pitch is "USB-C for tools". The reality is more specific, and knowing where the boundary sits saves you from building a server you didn't need.
- Published
- 14 Jul 2026
- Reading
- 10 min
- Class
- protocols
half-life 180dfrom 14 Jul 2026
Updated 12 Aug 2026
This was published two weeks before the 2026-07-28 specification landed, so it describes the protocol as it stood just before. The three primitives below are unchanged and the design advice still holds. What's new: the base protocol is now stateless with per-request capability negotiation and cacheable list results, clients can offer elicitation (a server asking the user for information mid-run), and optional functionality has moved into a formal extensions framework — Tasks for long-running work with durable handles, Apps for inline UI, and Skills over MCP for structured agent instructions. Extensions are opt-in and negotiated at initialisation by both sides.
The Model Context Protocol solves an N×M problem. Before it, every agent client that wanted to talk to your system needed its own integration, and every system that wanted to be reachable needed to be built into every client. MCP makes that one interface on each side: you write a server once, and any client that speaks the protocol can use it.
That is the whole value proposition, and it is a real one. It is also narrower than the marketing suggests, and a lot of wasted effort comes from missing the boundary.
The three primitives, and who controls each
A server can expose three kinds of thing. The distinction between them is not about shape — it is about who decides when they're used.
| Primitive | Invoked by | Use it for |
|---|---|---|
| Tools | The model | Actions with effects, and lookups the model decides it needs |
| Resources | The client or user | Content to attach: files, records, documents |
| Prompts | The user | Named workflows a person picks deliberately |
Most servers in the wild expose everything as tools, which works but wastes the distinction. If a human should be choosing when something runs — a review workflow, a report template — a prompt is the honest representation, and it keeps that operation out of the model's decision space entirely.
Transports: local first, remote when you need it
Servers run either as a local subprocess speaking over stdio, or as an HTTP service the client connects to. The choice is mostly about where the credentials and the data live.
- stdio — the server runs on the user's machine, inherits their environment, and touches their files. Simple, no network surface, no auth story needed. This is the right default for anything developer-facing.
- HTTP — the server is a service, possibly multi-tenant, with real authentication and authorisation. Necessary for anything shared, and it brings every concern a normal API brings, plus a few new ones.
Teams reach for remote too early. If the only consumer is a developer running an agent on their laptop against systems they already have credentials for, a stdio server is a hundred lines and no operations burden.
Where servers go wrong
Wrapping an API one-to-one
The most common mistake is generating one tool per REST endpoint. A forty-endpoint API becomes a forty-tool server, the model now has forty descriptions competing for attention, and accomplishing anything takes six chained calls.
Design tools around tasks, not around your API surface. If the real job is "find the customer's most recent failed payment and explain why it failed", that is one tool that internally makes four calls — not four tools the model must sequence correctly. The server is where you put the domain knowledge, so the model doesn't have to hold it.
Unbounded results
A tool returning a full table dump will eat the context window. Every result needs a
size discipline: cap the rows, summarise the rest, and say so in the output
(showing 20 of 4,312 matches; narrow the query to see more). The model
handles that message well. It handles a truncated JSON blob badly.
Errors that tell the model nothing
Same rule as any agent tool: the error message is the recovery path. Return the constraint that was violated and, where you can, the correction. The model is reading this and will act on it.
The security part, which is not optional
An MCP server is an execution surface, and connecting one grants it whatever the agent can reach. Three things to hold onto:
- Tool descriptions are untrusted input to the model. A malicious server can write a description that instructs the model to exfiltrate data from another server in the same session. Treat third-party servers as you would treat an npm package with a postinstall script.
- Tool results are data, never instructions. If a returned document contains text addressed to the agent, that is prompt injection arriving through your integration. The harness needs to hold that line; the server should not be relaying unfiltered third-party content as though it were trustworthy.
- Scope credentials to the server. A server that needs read access to one table should not be holding a key that can drop the database. This is ordinary least-privilege, and it is skipped constantly because the server "is just for me".
Load-bearing
The combination of a server with broad private access, a server that reads untrusted external content, and the ability to send data outward is the dangerous one. Any two are usually fine. All three in one session is an exfiltration path, regardless of how well-behaved each server is on its own.
When not to build a server
MCP earns its keep when more than one client will use the integration, or when the integration should outlive the agent you're building today. If you're writing a single application with its own tools and no intention of exposing them elsewhere, define the tools directly in your code. You get typing, straightforward debugging, and no process boundary — and you can always lift them into a server later, because the shape is the same.
The protocol is plumbing. Good plumbing is worth a great deal, and it is still worth knowing when you don't need a pipe.