Skip to content
AdminKit

What do MCP tool annotations actually promise — and why can't a client just trust them?

A Model Context Protocol tool definition can carry an optional annotations object — readOnlyHint, destructiveHint, idempotentHint, openWorldHint — that hints at what calling the tool will actually do to the world. They look like exactly the severity signal you'd want before letting an agent call an unfamiliar tool, which is why the specification is explicit that they're hints a server declares about itself, not a guarantee a client can verify independently.

By AdminKit team, Netbase JSC · Updated November 1, 2026

The four hints, and what each one actually declares

The MCP specification’s schema defines ToolAnnotations as an object a server can attach to any tool it lists, alongside an optional title for display:

  • readOnlyHint — “If true, the tool does not modify its environment.” Default: false.
  • destructiveHint — “If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.” Meaningful only when readOnlyHint is false. Default: true.
  • idempotentHint — “If true, calling the tool repeatedly with the same arguments will have no additional effect on its environment.” Also only meaningful when readOnlyHint is false. Default: false.
  • openWorldHint — “If true, this tool may interact with an ‘open world’ of external entities. If false, the tool’s domain of interaction is closed.” The spec’s own example: a web search tool is open-world; a tool that only queries a fixed internal memory store is not. Default: true.

The defaults are the detail most worth noticing: a tool that declares nothing is treated, by the schema’s own defaults, as not read-only and potentially destructive. Silence isn’t a neutral or safe assumption here — it’s the spec’s way of saying “assume the riskier case until told otherwise.”

Why the specification calls these “untrusted”

Right next to the field definitions, the schema reference states plainly that annotations “are not guaranteed to provide a faithful description of tool behavior (including descriptive properties like title),” and that “clients should never make tool use decisions based on ToolAnnotations received from untrusted servers.” The MCP specification’s Tools page repeats the same point as a flagged warning: clients “MUST consider tool annotations to be untrusted unless they come from trusted servers.”

The reasoning is the same as for a tool’s name and description: all of it is self-reported by the server exposing the tool, over the same tools/list call AdminKit’s MCP endpoint check sends when probing whether a server requires authentication — see how to read an MCP endpoint check result for what that check actually does. A server that’s already malicious, compromised, or just carelessly written has no protocol-level obligation to declare destructiveHint: true on a tool that deletes records, and nothing in MCP itself catches that mismatch. Annotations formalize the kind of severity signal a careful reader would otherwise have to infer from a tool’s name alone, but they inherit the exact same trust problem: a server you haven’t vetted can say anything it wants about itself.

What this means in practice

Treat annotations the way you’d treat any other claim a server makes about its own behavior:

  1. From a server you built or fully control, annotations are a useful, low-cost way to drive client-side UX — for example, requiring an explicit confirmation step before any call that isn’t readOnlyHint: true, rather than prompting on every single call.
  2. From a server you don’t control, read annotations as one input alongside the tool’s name and description, not as a verified fact. A tool named delete_record declaring readOnlyHint: true is a red flag about the server’s trustworthiness in general, not a reason to relax.
  3. Keep a human in the loop for consequential actions regardless of what’s declared — the specification’s own guidance for tool use recommends exactly this, independent of whatever annotations a tool carries. See how to secure an MCP server for the fuller checklist, and what a security gateway adds in front of an MCP server if you’re evaluating a dedicated layer that can enforce confirmation or allowlisting independent of whatever the upstream server claims about itself.

Tool annotations are a real, useful piece of the MCP spec — they just answer “what does this server say it does,” not “what has been independently verified that it does.” The distinction matters most for exactly the servers you’re least sure about, which is precisely when a self-reported hint is least reliable.

This guide is general information, not a security audit of your specific network — see our disclaimer for what AdminKit's guidance does and does not commit to.

Frequently asked questions

What are MCP tool annotations, in plain terms?

Optional metadata a server attaches to each tool it exposes, alongside the tool's name and description, describing the expected effect of calling it: whether it only reads data, whether it can destroy something, whether calling it twice with the same input is safe, and whether it reaches outside a closed, predictable system. The Model Context Protocol's schema defines four boolean hints — readOnlyHint, destructiveHint, idempotentHint and openWorldHint — plus an optional display title.

What happens if a server doesn't set any annotations at all?

The defaults matter and lean cautious, not permissive. Per the MCP schema, readOnlyHint defaults to false and destructiveHint defaults to true — meaning a tool with no annotations is assumed capable of destructive changes unless the server explicitly says otherwise with readOnlyHint: true. A client reading an unannotated tool should not assume it's safe just because nothing was declared.

Can a malicious or careless MCP server just lie in its annotations?

Yes, and the specification says so directly: annotations "are not guaranteed to provide a faithful description of tool behavior," and clients "should never make tool use decisions based on ToolAnnotations received from untrusted servers." A server could declare readOnlyHint: true on a tool that actually deletes records, and nothing in the protocol itself stops that — the hint is self-reported, the same way a tool's name and description are.

Does AdminKit's MCP endpoint check show me a tool's annotations?

Not today. AdminKit's MCP endpoint check calls tools/list and surfaces each exposed tool's name and description, which is enough to judge an unauthenticated tool list's risk from the name alone (see how to read an MCP endpoint check result) — it doesn't currently parse or display the annotations object a tool definition may also carry. This guide explains what that metadata means for anyone building a client, gateway or agent that does read it.

If annotations can't be trusted, what's the point of them?

They're most useful as a server's own declared intent when the server is one you built or trust, or as one more signal to weigh — never the only one — when deciding how much friction to add before a call goes through (e.g. requiring explicit confirmation before anything not declared readOnlyHint). Combined with reading the tool's actual name and description, and keeping a human in the loop for consequential actions as the specification itself recommends, annotations add useful context without replacing the judgment a client still has to apply.

Want AdminKit to watch this for you?

Free checks tell you the state today. Protective DNS and monitoring tell you when it changes.

Huy Nguyen (David), Founder and CEO of Netbase JSC

Talk to an expert

Huy Nguyen (David), Founder & CEO, Netbase JSC

Ask whether this fix applies to your setup, or get a second pair of eyes on your DNS and mail records.