What are MCP tool annotations?
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs.
MCP tool annotations are optional metadata an MCP server attaches to each tool it exposes — a display title plus four yes/no hints about whether the tool changes anything, whether the change is destructive, whether repeating the call is harmless, and whether it reaches external systems — which clients may use to shape their interface but must not treat as guarantees.
This page describes the annotation fields as defined in the MCP specification revision 2025-06-18, what each one means when the tools are an exchange account, how an honest trading server would annotate its tools, and what annotations are and are not good for. For where read-only access actually has to be enforced, see read-only vs trade permission in an MCP setup; this page is about the vocabulary itself.
Why this matters now
When an MCP client connects to a server it receives a list of tools, and it has to decide how to present them: which to group together, which to highlight, which to confirm before running. Annotations are the only structured signal the protocol gives it for those decisions. As exchange MCP servers multiply, the annotations they ship are starting to shape what users see — and a confirmation dialog, or its absence, is the difference between reviewing an order and not seeing it at all.
How it actually works
A tool definition, returned by tools/list, has a name, an optional title,
a description, an inputSchema (JSON Schema), an optional outputSchema and
optional annotations. The annotations object has five fields:
| Field | Default | Meaning, verbatim from the schema |
|---|---|---|
title | — | “A human-readable title for the tool.” |
readOnlyHint | false | “If true, the tool does not modify its environment.” |
destructiveHint | true | “If true, the tool may perform destructive updates to its environment. If false, the tool performs only additive updates.” |
idempotentHint | false | “If true, calling the tool repeatedly with the same arguments will have no additional effect on the its environment.” |
openWorldHint | true | “If true, this tool may interact with an ‘open world’ of external entities.” |
Two structural points:
destructiveHintandidempotentHintonly mean something whenreadOnlyHintis false. A tool that changes nothing cannot be destructive or non-idempotent.- The defaults assume the worst. A tool with no annotations is treated as state-changing, destructive, non-idempotent and open-world. Leaving a field out is the conservative choice.
Annotating trading tools honestly
The spec’s definitions were written for tools in general. Applied to an exchange account, some are obvious and some need a judgement:
| Tool | readOnly | destructive | idempotent | openWorld | Reasoning |
|---|---|---|---|---|---|
get_balance, get_positions | true | — | — | true | Reads only; talks to the exchange |
get_ticker, get_orderbook | true | — | — | true | Market data from an external system |
place_order | false | true | false | true | Can close, flip or add to a position; twice means two orders |
cancel_order | false | true | arguably true | true | Removing a protective stop is destructive; a second cancel of the same order adds nothing |
set_leverage | false | true | true | true | Setting the same value twice has no extra effect — and it still changes liquidation distance |
withdraw | false | true | false | true | Should not be exposed to a model at all |
| Local position-size calculator | true | — | — | false | Pure arithmetic; touches nothing external |
Three things stand out.
“Additive” is a poor description of an order. destructiveHint: false means
“performs only additive updates”. Placing an order adds an order, but its effect
can close a position or reverse it. Declaring an order tool non-destructive is
technically arguable and practically misleading; leave the default.
Idempotent is not the same as safe. set_leverage is idempotent in the
spec’s sense — the second identical call changes nothing — and it can still move
your liquidation price. A client that relaxes confirmation for idempotent tools
would relax it for this one.
idempotentHint: false on order placement is load-bearing. It is the
signal that a failed call must not be retried blindly, which is the failure
described in
retrying a failed order is not safe.
Hints, not guarantees
The schema says so directly:
“NOTE: all properties in ToolAnnotations are hints. They are not guaranteed to provide a faithful description of tool behavior (including descriptive properties like
title).Clients should never make tool use decisions based on ToolAnnotations received from untrusted servers.”
And the tools specification makes it normative: clients “MUST consider tool annotations to be untrusted unless they come from trusted servers”.
An annotation is the server describing itself. Nothing verifies it. A
place_order tool declared readOnlyHint: true is a false claim the protocol
has no way to catch. That is why the useful reading of annotations is
asymmetric: a conservative annotation costs you nothing if it is wrong; an
optimistic one costs you whatever it caused a client to skip.
Annotations can change after you look
The tool list is not fixed. A server that declares the listChanged capability
can send notifications/tools/list_changed, and the new list can carry new
tools and new annotations. A review of a server’s annotations at install time is
a snapshot. Re-check after updates, and treat a tool whose annotations became
more permissive as a change worth understanding.
Where the boundary should sit
- Use annotations for presentation. Grouping read tools apart from write tools, labelling, and choosing sensible defaults for servers you trust — that is what they are for.
- Do not use them as permission. What a tool can do on your account is decided by the exchange key and by local code between the model and the venue — see why MCP needs an approval layer.
- Keep auto-retry off where
idempotentHintis false — and also where it is true but the server is not one you have audited. - If you write a server, annotate conservatively. Mark only genuinely
read-only tools as read-only, leave
destructiveHintat its default for anything that places or cancels orders, and never annotate optimistically to reduce confirmation prompts.
FAQ
What are MCP tool annotations?
They are optional metadata on each MCP tool: a human-readable title and four
hints — readOnlyHint, destructiveHint, idempotentHint and openWorldHint
— describing how the tool behaves. Clients can use them to decide how to display
and confirm tools. The specification states they are hints that are not
guaranteed to be accurate.
What does destructiveHint mean?
It says whether a state-changing tool may perform destructive updates (true) or
only additive ones (false). It defaults to true and only applies when
readOnlyHint is false. For trading tools, placing and cancelling orders should
keep the default, because an order can close or reverse a position and a cancel
can remove a protective stop.
Can a client trust readOnlyHint to auto-approve tool calls?
Not from a server it does not trust. The MCP schema says clients should never make tool-use decisions based on annotations from untrusted servers, and the specification says clients must treat such annotations as untrusted. A tool annotated read-only can still place an order if the server is wrong or malicious; enforce read-only at the exchange key instead.
What happens if a tool has no annotations?
The defaults apply, and they are conservative: the tool is treated as state-changing, destructive, non-idempotent and interacting with external systems. An unannotated trading tool is therefore described more cautiously than one a server has annotated optimistically.