Summary
The tool definitions don't include MCP annotations (readOnlyHint, destructiveHint, idempotentHint). These are optional hints in the MCP spec that help LLMs decide when to ask for user confirmation.
The ToolSchema type in src/tools/tool.ts currently only has name, description, and inputSchema — it doesn't include an annotations field.
Suggested annotations
| Tool |
Annotation |
Reason |
browser_click |
destructiveHint: true |
Clicks elements, triggers actions, could submit forms |
browser_type |
destructiveHint: true |
Enters text into page fields |
browser_drag |
destructiveHint: true |
Moves elements, modifies page state |
browser_navigate |
destructiveHint: false |
Changes page but not truly destructive |
browser_press_key |
destructiveHint: true |
Key presses can trigger actions (Enter = submit) |
browser_select_option |
destructiveHint: true |
Modifies form selection state |
browser_snapshot |
readOnlyHint: true |
Captures ARIA snapshot, no side effects |
browser_hover |
readOnlyHint: true |
Hovers without clicking, minimal side effects |
browser_go_back |
readOnlyHint: false, destructiveHint: false |
Navigation, not destructive |
browser_go_forward |
readOnlyHint: false, destructiveHint: false |
Navigation, not destructive |
browser_wait |
readOnlyHint: true |
Just waits, no side effects |
Implementation
- Add
annotations to the ToolSchema type:
// src/tools/tool.ts
import type { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
export type ToolSchema = {
name: string;
description: string;
inputSchema: JsonSchema7Type;
annotations?: ToolAnnotations;
};
- Add annotations to each tool:
// src/tools/snapshot.ts
export const click: Tool = {
schema: {
name: ClickTool.shape.name.value,
description: ClickTool.shape.description.value,
inputSchema: zodToJsonSchema(ClickTool.shape.arguments),
annotations: { destructiveHint: true },
},
// ...
};
export const snapshot: Tool = {
schema: {
name: SnapshotTool.shape.name.value,
description: SnapshotTool.shape.description.value,
inputSchema: zodToJsonSchema(SnapshotTool.shape.arguments),
annotations: { readOnlyHint: true },
},
// ...
};
Why this matters
Without annotations, an LLM has no signal that browser_click or browser_type modify page state. It may call these tools without asking the user first. For a browser automation server, annotations help LLMs distinguish between safe inspection (snapshot, hover) and actions that change state (click, type, drag).
These findings came from the MCP Quality Benchmark. The MCP Validator can check all tools at once.
Summary
The tool definitions don't include MCP annotations (
readOnlyHint,destructiveHint,idempotentHint). These are optional hints in the MCP spec that help LLMs decide when to ask for user confirmation.The
ToolSchematype insrc/tools/tool.tscurrently only hasname,description, andinputSchema— it doesn't include anannotationsfield.Suggested annotations
browser_clickdestructiveHint: truebrowser_typedestructiveHint: truebrowser_dragdestructiveHint: truebrowser_navigatedestructiveHint: falsebrowser_press_keydestructiveHint: truebrowser_select_optiondestructiveHint: truebrowser_snapshotreadOnlyHint: truebrowser_hoverreadOnlyHint: truebrowser_go_backreadOnlyHint: false, destructiveHint: falsebrowser_go_forwardreadOnlyHint: false, destructiveHint: falsebrowser_waitreadOnlyHint: trueImplementation
annotationsto theToolSchematype:Why this matters
Without annotations, an LLM has no signal that
browser_clickorbrowser_typemodify page state. It may call these tools without asking the user first. For a browser automation server, annotations help LLMs distinguish between safe inspection (snapshot,hover) and actions that change state (click,type,drag).These findings came from the MCP Quality Benchmark. The MCP Validator can check all tools at once.