What a tool server actually promises

Checked 22 Sep 2026 · By Luke Czak

ArticleUnderstanding AIFree to read

MCP servers expose three distinct kinds of capability, not one undifferentiated bag of “tools”, and the specification says a tool’s own description should be treated as untrusted unless the server providing it already is.

The first time I wired a server into one of my agents over the Model Context Protocol, I described the whole exercise to myself as giving the agent tools. That is the word everyone reaches for casually, and it undersells what the protocol actually defines. The MCP specification, revision 2025-06-18, does not treat tools as the whole vocabulary a server can offer. It draws three separate categories of capability, and I had been building every integration as though only one of them existed.

A server can expose Resources, essentially readable context and data for the agent to draw on. It can expose Prompts, reusable templated messages and workflows for shaping a conversation rather than a single call. And it can expose Tools, the functions the model can actually execute — the only one of the three that changes something in the world when it is invoked. I had built a reference lookup as a tool for months, when it was Resources all along and would have cost the agent nothing to read.

The relationship runs the other way too, which took me longer to notice than it should have. A client, meaning the software hosting the model rather than the server providing a capability, may in turn offer Sampling, Roots and Elicitation back to a server. I had pictured MCP as one-way traffic, server offers and agent consumes, and missed that a server is allowed to ask the host for something it cannot do alone: a sample from the model, or an answer elicited directly from the user.

The specification is blunter about trust than I expected a protocol document to be. It says descriptions of tool behaviour, including a tool’s own annotations, should be treated as untrusted unless they come from a server already known to be trustworthy. That single line ruled out a habit I had half-formed without noticing: reading a tool’s self-description and taking it as an accurate account of what the tool actually does. A careless or compromised server is exactly the source that would describe its own tool inaccurately, and the specification treats that as the default risk rather than an edge case.

It is equally direct about consent. A host must not invoke a tool without first getting explicit consent from the user, and the specification does not frame that as a setting ticked once when a connection is first made. It reads as a hard requirement rather than a nice-to-have. Every shortcut that makes an agent feel more autonomous by pre-approving a whole class of tool calls, so a human never sees the individual request, sits on the wrong side of that requirement, however convenient it is to reach for. That is worth saying plainly because the convenience is real and the pressure towards it is constant.

Reading a server’s capability list now takes an extra minute I did not spend before, going through which of the three categories each entry actually falls under rather than assuming everything is a tool because that was the word in the tab I clicked. It has already caught one integration I nearly built wrong a second time: a static glossary I was about to wire up as a callable tool, when framing it as a Resource meant the agent could read it without an invocation round trip at all. That minute is cheap. Rebuilding an integration around the wrong category after the fact is not, and I had already done that once before I started checking properly.

Underneath all three categories sits a detail that mattered less to my thinking about trust and more to an actual afternoon of debugging: the transport is JSON-RPC 2.0. Once I knew the wire format, a request that had been silently failing stopped being a mystery and became a malformed message I could read directly. None of this changes what a server does for an agent day to day. It changed how I read one before wiring it in: three distinct promises, each carrying a different amount of trust, not one undifferentiated bag of capability.

Comments (0)

Sign in to comment.