On this page
MCP Tool Annotations Explained: readOnlyHint, destructiveHint and Why They're Only Hints (Nov 2026)

MCP tool annotations are labels a server puts on each tool: read-only or not, destructive or not, safe to repeat or not, and whether it reaches outside services. They help clients and people decide what to approve. But they are hints from the server, not guarantees, and the spec says to ignore them from servers you don't trust.

Two r/mcp threads made this topic hot. One tester found that "most MCP servers I test skip two of the four tool safety labels" (thread). Another user "approved a clean MCP server. 30 days later its tool description asked the agent for my SSH key" (thread).

The four annotations

These come from the ToolAnnotations type in the MCP schema (version 2026-07-28, the current one). The definitions and defaults are quoted from it, and they read the same as in the previous version, 2025-11-25.

Annotation Spec definition Default
readOnlyHint "If true, the tool does not modify its environment." false
destructiveHint "If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates." Only meaningful when readOnlyHint is false. true
idempotentHint "If true, calling the tool repeatedly with the same arguments will have no additional effect on its environment." Only meaningful when readOnlyHint is false. false
openWorldHint "If true, this tool may interact with an 'open world' of external entities." A web search tool is open-world; a memory tool is not. true

There is also an optional title for display.

Notice the defaults. A tool with no annotations is assumed to write (readOnlyHint false), to be possibly destructive (destructiveHint true), to be unsafe to repeat, and to reach the outside world. So a server that skips the labels isn't hiding anything. Its tools are just treated as the riskiest kind, which is the safe assumption.

They are hints, not guarantees

The spec says this twice. In the schema: "all properties in ToolAnnotations are hints. They 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."

And in the Tools section: "clients MUST consider tool annotations to be untrusted unless they come from trusted servers."

That makes sense. The server writes its own labels. A buggy or malicious server can mark a delete tool readOnlyHint: true, and nothing in the protocol stops it. The spec's real safety rule is elsewhere: "there SHOULD always be a human in the loop with the ability to deny tool invocations."

How clients use them

Only rely on what a client documents. Claude Code's MCP docs describe these uses:

  • Retries after a dropped connection. If a call was pending when an HTTP connection closed, Claude Code can repeat it once on a new connection, but only for tools marked idempotentHint or readOnlyHint.
  • Parallel calls. Tools marked readOnlyHint run in parallel with other read-only calls.
  • Forcing a full approval prompt. A server can set "anthropic/requiresUserInteraction": true in a tool's _meta. On surfaces that normally allow one-tap approval, Claude Code then shows the full permission prompt for that tool.

Claude Code's MCP docs don't say that annotations skip permission prompts. Your permission rules decide that. Treat any claim that a tool "is read-only, so it's auto-approved" with care unless your client documents it.

The bigger risk: tools that change after you approve them

Annotations describe a tool at one moment. MCP lets a server's tool list change over time. Under the 2026-07-28 spec, a server that declares listChanged "SHOULD send a notification" when its tools change to clients that have opened a subscriptions/listen stream asking for tool-list changes, and the client fetches the new list. Lists now also carry a ttlMs freshness hint that tells a client how long it may cache them (changelog). Updates to a package can change tool descriptions too.

That is the "rug pull" from the Reddit thread: a description that was harmless when you approved it later contains instructions aimed at the model. A related thread tests "positional prompt-injection scanning for MCP tool descriptions" (thread).

What you can do:

  1. Pin versions of local servers. Use an exact version in your config, for example package@1.2.3 instead of @latest, or a Docker image digest. Then updates only happen when you choose.
  2. Re-review on update. When you bump a version, read the changelog and the tool list again. The 5-minute safety check covers what to look for.
  3. Keep tool approval on for anything that writes, whatever its labels say.
  4. Watch for advisories. Our registry watch checks the official MCP registry daily and flags new security advisories against servers, so you can see when something you run needs a look.
  5. Prefer hosted servers from the vendor for high-risk systems. A vendor that runs its own server is accountable for what its tools say.

Read-only modes in our directory

A real read-only mode, enforced by the server or the token, is stronger than a readOnlyHint label. These listings document one:

Server Grade Read-only option
GitHub A Read-only endpoint (/mcp/readonly)
Buildkite A /mcp/readonly endpoint that issues a read-only token
Cloudflare A Read-only grant at sign-in
Linear A Read-only endpoint
Supabase A read_only option
MongoDB A --readOnly flag
Salesforce B Read-only server
Snowflake C SQL tool is read-only (SELECT only) unless you turn that off
Figma B The desktop server has no write tools

Servers without one can still be narrowed: deny their write tools in your client's permission rules, or connect with a restricted token. See MCP authentication explained for which grants are too broad.

Frequently asked questions

What is readOnlyHint in MCP?

A label meaning the tool doesn't change anything. It defaults to false, so a tool is assumed to write unless the server says otherwise. It's a hint from the server, not a guarantee.

If a tool says destructiveHint: false, is it safe?

It means the server says the tool only adds things, never deletes or overwrites. That's useful, but it's the server's own claim. Only trust it from servers you trust, and keep approval on for writes.

Why do so many servers leave annotations out?

They're optional. Leaving them out isn't dangerous in itself, because the defaults assume the worst. It does lose useful information, like which tools are safe to repeat after a dropped connection.

Can a malicious server lie in its annotations?

Yes. That's why the spec says clients must treat annotations as untrusted unless the server is trusted. Your defence is a trusted source, pinned versions and human approval, not the labels.

I build an MCP server. Which annotations should I set?

Set readOnlyHint: true on tools that only read, and idempotentHint: true on writes that are safe to repeat. Set destructiveHint: false on tools that only add. Be accurate: clients like Claude Code use these to decide retries and parallel calls.

More: MCP security best practices ยท Browse the directory