Skip to content

Add MCP annotations (readOnlyHint/destructiveHint) to tool definitions #162

@ghost

Description

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

  1. 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;
};
  1. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions