Skip to content

Add MCP annotations to tool definitions (especially chrome_inject_script, chrome_javascript) #317

@ghost

Description

Summary

The 37 tool definitions in this server don't include MCP annotations (readOnlyHint, destructiveHint, idempotentHint). These are optional hints defined in the MCP spec that help LLMs decide when to ask for user confirmation before executing a tool.

This matters especially for mcp-chrome because several tools execute arbitrary code or modify browser state:

High-priority tools

Tool Suggested annotation Why
chrome_inject_script destructiveHint: true Injects and executes arbitrary JavaScript in the page — could modify DOM, exfiltrate data, or break page state
chrome_javascript destructiveHint: true Executes arbitrary JS — same risks as inject_script
chrome_bookmark_delete destructiveHint: true Permanently removes bookmarks
chrome_close_tabs destructiveHint: true Closes browser tabs, potential data loss if unsaved work
chrome_fill_or_select destructiveHint: true Modifies form state, could submit forms
chrome_upload_file destructiveHint: true Uploads files from the user's system
chrome_userscript destructiveHint: true Installs/runs userscripts

Read-only tools

Tool Suggested annotation Why
get_windows_and_tabs readOnlyHint: true Inspects browser state only
chrome_screenshot readOnlyHint: true Captures page state, no side effects
chrome_read_page readOnlyHint: true Reads page content only
chrome_console readOnlyHint: true Reads console messages
chrome_history readOnlyHint: true Reads browsing history
chrome_bookmark_search readOnlyHint: true Searches bookmarks without modification
chrome_get_interactive_elements readOnlyHint: true Inspects DOM elements
search_tabs_content readOnlyHint: true Searches tab content
chrome_get_web_content readOnlyHint: true Fetches page content
performance_analyze_insight readOnlyHint: true Analyzes traces

Example implementation

In packages/shared/src/tools.ts, annotations can be added to each tool schema:

{
  name: TOOL_NAMES.BROWSER.INJECT_SCRIPT,
  description: 'Inject and execute a JavaScript ...',
  annotations: {
    destructiveHint: true
  },
  inputSchema: { ... }
},
{
  name: TOOL_NAMES.BROWSER.SCREENSHOT,
  description: 'Take a screenshot ...',
  annotations: {
    readOnlyHint: true
  },
  inputSchema: { ... }
}

Why this matters

Without destructiveHint, an LLM has no signal that chrome_inject_script executes arbitrary code. It may call it without asking the user first. For a browser automation server, this is a significant safety gap — especially since the tools have access to cookies, localStorage, and the full page DOM.

I ran these tool definitions through the MCP Quality Benchmark and this was the most common gap. The MCP Validator can check all 37 tools at once if useful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions