MCP Tool Annotations: Read-Only, Destructive, and Retry Hints
An MCP server can expose tools that search files, query a database, send messages, or change records. A client needs more than a tool name to decide how to present that action safely. MCP tool annotations provide a small set of hints about a tool's intended behavior—but they are not permissions, guarantees, or a substitute for validation.
If you're building or configuring a Model Context Protocol (MCP) server, understanding readOnlyHint, destructiveHint, idempotentHint and openWorldHint helps you describe tools more accurately and design better approval flows.
What are MCP tool annotations?
Tool annotations are optional metadata attached to an MCP tool definition. They help a compatible client understand how the tool is expected to behave. The Model Context Protocol specification says clients must treat annotations as untrusted unless they come from trusted servers. That warning matters: a server can mislabel a tool, and a client should not assume the label proves what the implementation will do.
The current annotation vocabulary includes a human-readable title and four behavioral hints: read-only, destructive, idempotent, and open-world. These are descriptions for client experience and policy decisions—not executable security controls.
The four behavioral hints, explained
1. readOnlyHint: does the tool change state?
Set readOnlyHint: true only when the tool reads information without modifying the environment. A search tool that returns matching documents may be read-only. A tool that updates a document, deletes a file, sends an email, or changes a setting is not read-only, even if it also returns a summary.
A practical test is to ask: after a successful call, can the call itself have changed data or triggered an external action? If yes, do not label it read-only. Also consider indirect effects: a tool that queries an external service may still interact with the outside world even if it does not modify your local database.
2. destructiveHint: could the change remove or damage something?
The destructiveHint describes whether a state-changing operation may be destructive rather than merely additive. For example, creating a new draft is typically additive; permanently deleting a project or overwriting an existing record can be destructive. A bulk update may be destructive if it replaces values users need to preserve.
This hint is meaningful alongside read-only behavior. Do not set destructiveHint: false just because a tool has a friendly name or usually works as expected. Evaluate its real effects, including edge cases such as overwriting existing files or removing access.
3. idempotentHint: is repeating the same call safe?
An operation is idempotent when repeating it with the same arguments has no additional effect after the first successful execution. Reading a record is naturally repeatable. Setting a user's theme to dark can be idempotent if each call sets the same final value. Creating a new payment, sending an email, or appending a new row usually is not idempotent unless the implementation has a reliable deduplication mechanism.
This distinction is important for retries. If a client times out after a server has completed an operation, it may not know whether the action succeeded. A truthful idempotency design can make retries safer; a hint alone cannot. For critical operations, use server-side idempotency keys, unique request IDs, or equivalent deduplication and verify the result before retrying.
4. openWorldHint: does the tool interact with external entities?
The open-world hint indicates whether a tool interacts with an open world of external entities. A tool that searches public web pages or sends information to a third-party service may cross a trust boundary. Content returned from those sources should be treated as untrusted input, even when it arrives through a valid MCP tool response.
Open-world behavior depends on context. A company may consider its internal customer database a closed domain, while a public web search is open. Focus on where the tool reaches, what data it can receive, and whether that data can influence later actions.
A practical annotation example
Imagine an MCP server that provides three tools: search_docs, create_note and delete_note. Their annotations should reflect what the implementations actually do.
search_docsreads indexed documents and makes no changes. It can be marked read-only. If it searches a private, controlled index, its open-world setting should reflect that actual boundary.create_noteadds a new note. It is not read-only; the operation may be non-destructive, but repeating it may create duplicate notes unless the server deduplicates requests.delete_noteremoves a note. It is state-changing and destructive, so the client should not infer that it is safe simply because the server advertises a hint.
The point is not to copy a fixed combination of booleans. Choose values from the tool's real side effects and document any assumptions. Then test the server through the same transport and client environment your users will use.
Why annotations are not a security boundary
A malicious or buggy server can claim that a deletion tool is read-only. A client that trusts this claim blindly could skip a confirmation it should have shown. The official MCP guidance therefore treats annotations from untrusted servers as untrusted.
Do not use annotations as the only protection for sensitive actions. Enforce authorization on the server, validate every argument, apply least-privilege credentials, and require explicit approval for risky operations. Where appropriate, use sandboxing, network restrictions, audit logs, rate limits, and timeouts. The protocol's security guidance also recommends validating tool results before passing them to the model.
Prompt injection is another reason to separate hints from enforcement. A tool may retrieve an email, web page, or document containing malicious instructions. Marking a search tool as read-only does not make the returned content trustworthy, nor does it prevent another tool from sending private data elsewhere. Assess the combination of tools available in a session, not only each tool in isolation.
A checklist for MCP server developers
- Describe each tool's actual side effects before choosing annotation values.
- Mark a tool read-only only when it cannot modify state or trigger an action.
- Treat destructive operations as risky even when the tool is usually called with safe inputs.
- Set the idempotency hint only when repeating identical arguments is genuinely safe; implement deduplication for important writes.
- Assess whether external systems or untrusted content enter the tool's workflow.
- Keep server-side authorization and input validation independent of annotations.
- Test confirmation behavior in each supported client; clients may interpret or display annotations differently.
- Review annotations whenever the implementation changes, and add tests that catch unexpected side effects.
How this fits into an MCP configuration workflow
Annotations describe a tool's behavior after the server exposes it; they do not replace the server's transport configuration, input schema, or access controls. If you're debugging a server that does not connect, first validate the configuration and transport. If it connects but an agent uses a tool in an unsafe or confusing way, inspect the tool description, input schema, annotations, client approval behavior, and actual server-side enforcement.
For a broader configuration check, see our related guide, MCP Server Config Not Working? Common JSON Mistakes. You can also use the ManifestKit MCP Manifest Generator to organize a server configuration, then verify the implementation and permissions separately.
Frequently asked questions
Do MCP tool annotations force a client to ask for confirmation?
No. Annotations are metadata hints. A client decides how to use them, and behavior can differ by client. Sensitive operations should have independent authorization and approval controls.
Should every MCP tool include all four hints?
Not necessarily. Annotations are optional. Include accurate hints when they help clients understand behavior, and avoid guessing values merely to fill every field.
Does idempotentHint make retries safe?
No. It describes expected behavior; it does not implement deduplication. If a repeated call could create duplicate records, send duplicate messages, or charge twice, build server-side safeguards and verify outcomes.
Can readOnlyHint protect against prompt injection?
No. It describes whether a tool is expected to change state. It does not make retrieved content trustworthy or stop other tools from acting on malicious instructions. Use trust-boundary controls and least privilege.
Official references
MCP specification: Tools — tool definitions, annotations, client interaction, and security considerations.
MCP Blog: Tool Annotations as Risk Vocabulary — discussion of what current hints can and cannot safely do.
FAQ
Do MCP tool annotations force a client to ask for confirmation?
No. Annotations are metadata hints. A client decides how to use them, and behavior can differ by client. Sensitive operations should have independent authorization and approval controls.
Should every MCP tool include all four hints?
Not necessarily. Annotations are optional. Include accurate hints when they help clients understand behavior, and avoid guessing values merely to fill every field.
Does idempotentHint make retries safe?
No. It describes expected behavior; it does not implement deduplication. If a repeated call could create duplicate records, send duplicate messages, or charge twice, build server-side safeguards and verify outcomes.
Can readOnlyHint protect against prompt injection?
No. It describes whether a tool is expected to change state. It does not make retrieved content trustworthy or stop other tools from acting on malicious instructions. Use trust-boundary controls and least privilege.