What are tool annotations, and why are they hints, not guarantees?

5 minadvancedmcptoolsannotationssecurity

Quick Answer

Tool annotations are optional metadata a server can attach to a tool definition to describe its behavior to the host: readOnlyHint (doesn't modify state), destructiveHint (may perform irreversible changes), idempotentHint (calling it repeatedly with the same arguments has no additional effect), and openWorldHint (interacts with external/unbounded systems, e.g. the open internet, versus a closed local system). Hosts use these to drive UX — e.g., requiring extra confirmation before calling a tool annotated destructiveHint: true. They're explicitly hints, not guarantees, because they're self-reported by the server. A malicious or buggy server can annotate a destructive tool as readOnlyHint: true, so a host must not treat annotations as a security boundary, only as a UX signal for well-behaved, trusted servers.

Detailed Answer

Annotations give a host enough signal to build sensible default UX around risky actions. But they only work if you remember who's making the claim.

The four standard annotations

{
  "name": "delete_file",
  "description": "Permanently delete a file from disk.",
  "inputSchema": { "type": "object", "properties": { "path": {"type": "string"} }, "required": ["path"] },
  "annotations": {
    "title": "Delete File",
    "readOnlyHint": false,
    "destructiveHint": true,
    "idempotentHint": true,
    "openWorldHint": false
  }
}
AnnotationMeaning
readOnlyHintTool does not modify its environment
destructiveHintTool may perform irreversible or destructive updates (only meaningful when readOnlyHint is false)
idempotentHintCalling it again with identical arguments has no additional effect beyond the first call
openWorldHintTool interacts with an open-ended external domain (e.g., web search) rather than a fixed, closed set of entities

How a host is expected to use them

A reasonable host policy: auto-approve calls to tools annotated readOnlyHint: true without prompting. Require explicit user confirmation for anything with destructiveHint: true. Treat idempotentHint: false tools as unsafe to silently retry after a timeout, since a retry could duplicate a real-world effect like sending an email twice.

Why "hint," not "contract"

The annotation is written by the server author. The server is exactly the thing a host may not fully trust — it could be a third-party plugin the user just installed. A server has no obligation to be honest. It could label delete_all_data as readOnlyHint: true to slip past a host's confirmation UI. This is precisely why the spec calls them hints. Treating them as an enforceable security boundary would create a false sense of safety. A host that actually cares about safety still needs independent trust signals: provenance of the server, sandboxing, and user awareness of what a newly installed server can do. Annotations only optimize the common case where the server behaves honestly.

Related Resources