What are MCP tool annotations? A practical security guide

6 min read

Understand readOnlyHint, destructiveHint, idempotentHint and openWorldHint, then review MCP tools with concrete examples and a copyable security worksheet.

On this page

MCP tool annotations are optional hints a server attaches to a tool definition. They describe expected behavior, such as whether a tool changes data or whether repeating a call has an additional effect. They help a client present and evaluate tools, but they do not enforce permissions.

If you are deciding whether an agent may run a tool automatically, start with the account, resource, arguments and possible consequences. An attractive label is not enough. This guide explains the four behavior flags, then gives you a review record to use with your own server.

Protocol reference: MCP 2026-07-28, checked November 4, 2026. The examples below are illustrative design examples, not results from testing named products.

What the four MCP tool annotation flags mean

The MCP ToolAnnotations schema defines these optional fields. The defaults below apply when a flag is omitted; a default is not an observed test result.

FlagMeaning when trueDefault
readOnlyHintThe tool is described as not changing its environment.false
destructiveHintThe tool may make destructive changes. False describes additive changes.true
idempotentHintRepeating the same arguments is described as having no additional effect on the environment.false
openWorldHintThe tool may interact with an open set of external entities.true

destructiveHint and idempotentHint are meaningful only when readOnlyHint is false. There is also an optional display title. All of these properties are hints, including the title.

The MCP tools specification requires clients to treat annotations as untrusted unless they come from trusted servers. Even a trusted maintainer can make a mistake or change an implementation. Keep the observed behavior and the declared metadata as separate pieces of evidence.

Three examples where a reassuring flag is insufficient

A read-only ticket search can disclose private information

Imagine a search_tickets tool that correctly declares readOnlyHint: true. Its connected account can search every customer's support history. The assigned task is to summarize one customer's open tickets.

The review question is which records the account can return and where the results may go. No ticket has to change for an unrelated customer's details to be exposed. Restrict the accessible records at the service, select the intended account, and keep retrieved data within the authorized workflow.

An additive note can notify real people

Imagine append_case_note with readOnlyHint: false and destructiveHint: false. It only adds a note, but the application emails everyone following the case.

Before enabling it, determine whether the note is internal or public and whether notifications are sent. A useful preview shows the case, visibility and audience. If the task only authorizes drafting, save the text somewhere that does not notify those people.

An idempotent setting change can still be consequential

Imagine set_alert_threshold with idempotentHint: true. Repeating the same threshold might leave the same configuration, while the first call silences an important alert.

Review the setting change on its merits. For a timed-out call, inspect the actual configuration before retrying. A hint does not establish the provider's request-deduplication behavior, the reliability of its implementation, or whether an intermediary retried something else.

Likewise, openWorldHint: false should not be treated as proof that a tool is offline. A bounded internal service can still contain confidential records. Document the actual destinations and data flows.

Check the controls that actually limit access

Use least privilege to turn the task into an access plan. For each tool, identify the enforcing layer rather than assuming metadata supplies one.

  • Service authorization: the server or downstream API checks which account may perform an operation on a specific resource.
  • Execution restrictions: a local process runs with bounded file, network and credential access.
  • Client approval: the host gives an operator the information needed to authorize the intended action.
  • Runtime policy: an additional control can inspect a supported action before it executes.

The MCP authorization specification defines an HTTP authorization flow. It treats stdio differently, directing implementations to obtain credentials from the environment. A completed sign-in is not a review of every tool, argument or downstream account.

For local servers, review the launch command before running it. The MCP security guidance recommends constrained execution with limited filesystem, network and system access. Do not start an unfamiliar server on a machine containing production secrets just to inspect its tool list.

A copyable MCP tool review record

Use one record per tool and permitted workflow. Keep credentials and private result data out of it. Record an unknown as unknown, then decide whether that gap prevents the proposed use.

Server and verified source:
Package version or deployment reference:
Client and client version:
Tool name and reviewed schema date:
Declared annotation values:
Task the tool is needed for:
Acting account and accessible resources:
Allowed arguments and destinations:
Possible changes, disclosures and notifications:
Where access restrictions are enforced:
Required approval and what the operator sees:
Test evidence and unresolved gaps:
Decision, reviewer and review date:
Approved workflow and restrictions:
Owner and events that require another review:

For the fictional ticket-search tool, a useful result might be: “Approved for synthetic tickets in the training project only; production tenant isolation has not been verified.” That statement is more actionable than “read-only tools are safe.” It names an allowed use and the unresolved boundary.

Test metadata against behavior in a disposable environment

Use a mock service or isolated test account that you control, with synthetic records and no real recipients. Do not test destructive behavior against production data.

  1. Record the starting state. Save the test record IDs, permitted scope, tool definition and expected result. Capture enough evidence to tell whether something changed.
  2. Run a normal permitted case. Compare the result with service-side logs or state. Confirm that the intended record, account and destination were used.
  3. Check a harmless denied case. In the same isolated setup, use a second synthetic project that you own and are authorized to test, but that the test account is not allowed to access. Verify an enforcing system refuses it. A model declining to call the tool is a different observation.
  4. Inspect side effects. Check for created records, notifications, exports and outbound requests. A successful response alone does not describe every effect.
  5. Test repeat behavior only where it is safe. For a disposable operation designed for this test, compare the first and repeated call. Do not generalize that result to another tool, version or argument set.

The agent-permission testing worksheet covers the broader setup. Use the tool-call review checklist when deciding on an individual action.

What maintainers should document alongside annotations

Describe effects that a short tool name can hide: external messages, billing-related changes, created objects, credential use and outbound destinations. Keep read, draft and send operations separate where that makes the permission boundary clearer. Test that the implementation rejects unauthorized requests, even if a client sends them.

Revisit the review after a tool schema, server deployment, credential scope, client version or relevant policy changes. The current tools specification allows the available tool set to vary with authorization and to change over time. A review of one account's catalog should not be applied automatically to another account.

Where HOL Guard fits

HOL makes Guard. If you add it to this workflow, check the current Guard features and coverage for the exact client and action path. Treat it as an additional control on supported surfaces. Keep provider permissions, isolation and the review record in place.

For the broader architecture, read Secure MCP for AI Coding Agents. This article explains how to interpret tool metadata; it does not certify a server or establish universal interception coverage.

Method: source review of the linked MCP 2026-07-28 specification and security guidance on November 4, 2026. Examples and the review record are original illustrative guidance. No named-server test, measured security result or ranking is claimed.

All articles

Keep exploring

The engineering desk continues across the ecosystem: security research on shipping agents safely, and plugins that put the standards to work.