From d617b738b986c5b67f3723bbb052b74a0967da7e Mon Sep 17 00:00:00 2001 From: triepod-ai <199543909+triepod-ai@users.noreply.github.com> Date: Mon, 29 Dec 2025 08:35:19 -0600 Subject: [PATCH 1/2] Add destructiveHint and openWorldHint annotations to all 26 tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR adds the missing MCP tool annotations to improve AI assistant understanding of tool capabilities: - openWorldHint: true for all 26 tools (browser automation = external interaction) - destructiveHint: true for closePage, navigatePage, evaluateScript (irreversible changes) - destructiveHint: false for all other write operations (reversible modifications) These annotations help AI assistants make better decisions about: - Which tools require user confirmation before execution - Which tools interact with external systems - Which operations may cause data loss 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- src/tools/ToolDefinition.ts | 10 ++++++++++ src/tools/console.ts | 2 ++ src/tools/emulation.ts | 2 ++ src/tools/input.ts | 14 ++++++++++++++ src/tools/network.ts | 2 ++ src/tools/pages.ts | 12 ++++++++++++ src/tools/performance.ts | 3 +++ src/tools/screenshot.ts | 2 ++ src/tools/script.ts | 2 ++ src/tools/snapshot.ts | 3 +++ 10 files changed, 52 insertions(+) diff --git a/src/tools/ToolDefinition.ts b/src/tools/ToolDefinition.ts index d017640cd..20c3c2e26 100644 --- a/src/tools/ToolDefinition.ts +++ b/src/tools/ToolDefinition.ts @@ -24,6 +24,16 @@ export interface ToolDefinition< * If true, the tool does not modify its environment. */ readOnlyHint: boolean; + /** + * If true, the tool may perform destructive updates to its environment. + * If false, the tool performs only additive updates. + */ + destructiveHint?: boolean; + /** + * If true, this tool may interact with an "open world" of external + * entities (e.g., websites, APIs, external services). + */ + openWorldHint?: boolean; }; schema: Schema; handler: ( diff --git a/src/tools/console.ts b/src/tools/console.ts index 9c3d145bb..05d339f08 100644 --- a/src/tools/console.ts +++ b/src/tools/console.ts @@ -43,6 +43,7 @@ export const listConsoleMessages = defineTool({ annotations: { category: ToolCategory.DEBUGGING, readOnlyHint: true, + openWorldHint: true, }, schema: { pageSize: zod @@ -91,6 +92,7 @@ export const getConsoleMessage = defineTool({ annotations: { category: ToolCategory.DEBUGGING, readOnlyHint: true, + openWorldHint: true, }, schema: { msgid: zod diff --git a/src/tools/emulation.ts b/src/tools/emulation.ts index 13119250d..9c5b68663 100644 --- a/src/tools/emulation.ts +++ b/src/tools/emulation.ts @@ -21,6 +21,8 @@ export const emulate = defineTool({ annotations: { category: ToolCategory.EMULATION, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { networkConditions: zod diff --git a/src/tools/input.ts b/src/tools/input.ts index 505568922..748f83542 100644 --- a/src/tools/input.ts +++ b/src/tools/input.ts @@ -18,6 +18,8 @@ export const click = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { uid: zod @@ -57,6 +59,8 @@ export const hover = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { uid: zod @@ -141,6 +145,8 @@ export const fill = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { uid: zod @@ -169,6 +175,8 @@ export const drag = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { from_uid: zod.string().describe('The uid of the element to drag'), @@ -198,6 +206,8 @@ export const fillForm = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { elements: zod @@ -230,6 +240,8 @@ export const uploadFile = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { uid: zod @@ -278,6 +290,8 @@ export const pressKey = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { key: zod diff --git a/src/tools/network.ts b/src/tools/network.ts index d3b6c1fe6..3918e4f31 100644 --- a/src/tools/network.ts +++ b/src/tools/network.ts @@ -38,6 +38,7 @@ export const listNetworkRequests = defineTool({ annotations: { category: ToolCategory.NETWORK, readOnlyHint: true, + openWorldHint: true, }, schema: { pageSize: zod @@ -92,6 +93,7 @@ export const getNetworkRequest = defineTool({ annotations: { category: ToolCategory.NETWORK, readOnlyHint: true, + openWorldHint: true, }, schema: { reqid: zod diff --git a/src/tools/pages.ts b/src/tools/pages.ts index 96ab2cc01..6d1c4f5b6 100644 --- a/src/tools/pages.ts +++ b/src/tools/pages.ts @@ -16,6 +16,7 @@ export const listPages = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: true, + openWorldHint: true, }, schema: {}, handler: async (_request, response) => { @@ -29,6 +30,7 @@ export const selectPage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: true, + openWorldHint: true, }, schema: { pageIdx: zod @@ -57,6 +59,8 @@ export const closePage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: false, + destructiveHint: true, + openWorldHint: true, }, schema: { pageIdx: zod @@ -85,6 +89,8 @@ export const newPage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { url: zod.string().describe('URL to load in a new page.'), @@ -109,6 +115,8 @@ export const navigatePage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: false, + destructiveHint: true, + openWorldHint: true, }, schema: { type: zod @@ -205,6 +213,8 @@ export const resizePage = defineTool({ annotations: { category: ToolCategory.EMULATION, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { width: zod.number().describe('Page width'), @@ -229,6 +239,8 @@ export const handleDialog = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { action: zod diff --git a/src/tools/performance.ts b/src/tools/performance.ts index a8b24903c..0bbe0d007 100644 --- a/src/tools/performance.ts +++ b/src/tools/performance.ts @@ -26,6 +26,7 @@ export const startTrace = defineTool({ annotations: { category: ToolCategory.PERFORMANCE, readOnlyHint: true, + openWorldHint: true, }, schema: { reload: zod @@ -107,6 +108,7 @@ export const stopTrace = defineTool({ annotations: { category: ToolCategory.PERFORMANCE, readOnlyHint: true, + openWorldHint: true, }, schema: {}, handler: async (_request, response, context) => { @@ -125,6 +127,7 @@ export const analyzeInsight = defineTool({ annotations: { category: ToolCategory.PERFORMANCE, readOnlyHint: true, + openWorldHint: true, }, schema: { insightSetId: zod diff --git a/src/tools/screenshot.ts b/src/tools/screenshot.ts index 4312c02aa..4ff146b52 100644 --- a/src/tools/screenshot.ts +++ b/src/tools/screenshot.ts @@ -17,6 +17,8 @@ export const screenshot = defineTool({ category: ToolCategory.DEBUGGING, // Not read-only due to filePath param. readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { format: zod diff --git a/src/tools/script.ts b/src/tools/script.ts index de28fe0b4..8b86fe413 100644 --- a/src/tools/script.ts +++ b/src/tools/script.ts @@ -17,6 +17,8 @@ so returned values have to JSON-serializable.`, annotations: { category: ToolCategory.DEBUGGING, readOnlyHint: false, + destructiveHint: true, + openWorldHint: true, }, schema: { function: zod.string().describe( diff --git a/src/tools/snapshot.ts b/src/tools/snapshot.ts index 143d04093..df77d0702 100644 --- a/src/tools/snapshot.ts +++ b/src/tools/snapshot.ts @@ -18,6 +18,8 @@ in the DevTools Elements panel (if any).`, category: ToolCategory.DEBUGGING, // Not read-only due to filePath param. readOnlyHint: false, + destructiveHint: false, + openWorldHint: true, }, schema: { verbose: zod @@ -47,6 +49,7 @@ export const waitFor = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: true, + openWorldHint: true, }, schema: { text: zod.string().describe('Text to appear on the page'), From 2342bb7c60526951a006ea9236efe4795864698b Mon Sep 17 00:00:00 2001 From: triepod-ai <199543909+triepod-ai@users.noreply.github.com> Date: Wed, 7 Jan 2026 17:28:49 -0600 Subject: [PATCH 2/2] fix: Remove destructiveHint per maintainer feedback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address review feedback from @OrKoN and @sebastianbenz: - Remove all destructiveHint annotations since destructiveness is payload-dependent for browser automation tools - Keep openWorldHint: true on all tools (interact with external web) - Keep readOnlyHint for tools that only query state The destructiveness of browser automation tools cannot be reliably inferred at the tool level - a click on "Delete Account" is destructive, but a click on "Read More" is not. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- src/tools/emulation.ts | 1 - src/tools/input.ts | 7 ------- src/tools/pages.ts | 5 ----- src/tools/screenshot.ts | 1 - src/tools/script.ts | 1 - src/tools/snapshot.ts | 1 - 6 files changed, 16 deletions(-) diff --git a/src/tools/emulation.ts b/src/tools/emulation.ts index 9c5b68663..cb04befe9 100644 --- a/src/tools/emulation.ts +++ b/src/tools/emulation.ts @@ -21,7 +21,6 @@ export const emulate = defineTool({ annotations: { category: ToolCategory.EMULATION, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { diff --git a/src/tools/input.ts b/src/tools/input.ts index 748f83542..a9aea5aca 100644 --- a/src/tools/input.ts +++ b/src/tools/input.ts @@ -18,7 +18,6 @@ export const click = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -59,7 +58,6 @@ export const hover = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -145,7 +143,6 @@ export const fill = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -175,7 +172,6 @@ export const drag = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -206,7 +202,6 @@ export const fillForm = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -240,7 +235,6 @@ export const uploadFile = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -290,7 +284,6 @@ export const pressKey = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { diff --git a/src/tools/pages.ts b/src/tools/pages.ts index 6d1c4f5b6..8975ae9dc 100644 --- a/src/tools/pages.ts +++ b/src/tools/pages.ts @@ -59,7 +59,6 @@ export const closePage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: false, - destructiveHint: true, openWorldHint: true, }, schema: { @@ -89,7 +88,6 @@ export const newPage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -115,7 +113,6 @@ export const navigatePage = defineTool({ annotations: { category: ToolCategory.NAVIGATION, readOnlyHint: false, - destructiveHint: true, openWorldHint: true, }, schema: { @@ -213,7 +210,6 @@ export const resizePage = defineTool({ annotations: { category: ToolCategory.EMULATION, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { @@ -239,7 +235,6 @@ export const handleDialog = defineTool({ annotations: { category: ToolCategory.INPUT, readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { diff --git a/src/tools/screenshot.ts b/src/tools/screenshot.ts index 4ff146b52..ecd94ff33 100644 --- a/src/tools/screenshot.ts +++ b/src/tools/screenshot.ts @@ -17,7 +17,6 @@ export const screenshot = defineTool({ category: ToolCategory.DEBUGGING, // Not read-only due to filePath param. readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: { diff --git a/src/tools/script.ts b/src/tools/script.ts index 8b86fe413..33d096267 100644 --- a/src/tools/script.ts +++ b/src/tools/script.ts @@ -17,7 +17,6 @@ so returned values have to JSON-serializable.`, annotations: { category: ToolCategory.DEBUGGING, readOnlyHint: false, - destructiveHint: true, openWorldHint: true, }, schema: { diff --git a/src/tools/snapshot.ts b/src/tools/snapshot.ts index df77d0702..2a24f2e47 100644 --- a/src/tools/snapshot.ts +++ b/src/tools/snapshot.ts @@ -18,7 +18,6 @@ in the DevTools Elements panel (if any).`, category: ToolCategory.DEBUGGING, // Not read-only due to filePath param. readOnlyHint: false, - destructiveHint: false, openWorldHint: true, }, schema: {