From fedf5416b310b74508acc426a0abeed8059b7944 Mon Sep 17 00:00:00 2001 From: Anderson Martinez Date: Wed, 27 May 2026 10:32:51 -0400 Subject: [PATCH 1/6] build: changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87f6ebb..8ae3bd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ - Dependency updates +# v1.5.1 - 2026-05-27 + +- Add destructive hints for tools +- Enable OpenAI connectors in OAuth + # v1.5.0 - 2026-05-26 - Dependency updates From 6f166d27d32b6fc86ecb50a208d279350f85190b Mon Sep 17 00:00:00 2001 From: Anderson Martinez Date: Wed, 27 May 2026 10:36:43 -0400 Subject: [PATCH 2/6] fix: update ChatGPT redirect URI patterns for clarity and legacy support --- src/config.ts | 3 ++- test/lib/config.spec.ts | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/config.ts b/src/config.ts index 8f685c1..36abcb1 100644 --- a/src/config.ts +++ b/src/config.ts @@ -13,7 +13,8 @@ const DEFAULT_ALLOWED_REDIRECT_URI_PATTERNS = [ 'http://localhost:*', // Claude Desktop, VS Code, Windsurf, and anything else using a local loopback callback 'http://127.0.0.1:*', 'https://claude.ai/api/mcp/auth_callback', // Claude.ai web custom connectors - 'https://chatgpt.com/connector_platform_oauth_redirect', // ChatGPT MCP connector + 'https://chatgpt.com/connector/oauth/*', // ChatGPT / OpenAI Apps SDK connector (current per-connector callback id) + 'https://chatgpt.com/connector_platform_oauth_redirect', // ChatGPT MCP connector (legacy, still honored for already-published apps) 'cursor://anysphere.cursor-mcp/oauth/callback', // Cursor (private-use URI scheme registered by the desktop app) 'https://api.devin.ai/mcp/oauth/callback', // Devin prod 'https://api.beta.devin.ai/mcp/oauth/callback', // Devin beta diff --git a/test/lib/config.spec.ts b/test/lib/config.spec.ts index 431f165..acd5669 100644 --- a/test/lib/config.spec.ts +++ b/test/lib/config.spec.ts @@ -6,6 +6,7 @@ const BASELINE_PATTERNS = [ 'http://localhost:*', 'http://127.0.0.1:*', 'https://claude.ai/api/mcp/auth_callback', + 'https://chatgpt.com/connector/oauth/*', 'https://chatgpt.com/connector_platform_oauth_redirect', 'cursor://anysphere.cursor-mcp/oauth/callback', 'https://api.devin.ai/mcp/oauth/callback', From 6ddd4d1dfa415c4634943fd292c26eb69f32acab Mon Sep 17 00:00:00 2001 From: Anderson Martinez Date: Wed, 27 May 2026 10:38:38 -0400 Subject: [PATCH 3/6] build: changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ae3bd7..dffc48e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ - Dependency updates -# v1.5.1 - 2026-05-27 +# v1.5.2 - 2026-05-27 - Add destructive hints for tools - Enable OpenAI connectors in OAuth From 9b2c29f3f769a597cd3865211c064faf08c8a2ee Mon Sep 17 00:00:00 2001 From: Anderson Martinez Date: Wed, 27 May 2026 10:51:54 -0400 Subject: [PATCH 4/6] fix: ensure all tools have explicit boolean annotations for behavioral hints --- src/tools/agent.ts | 2 + src/tools/crawl.ts | 1 + src/tools/download.ts | 1 + src/tools/export.ts | 1 + src/tools/function.ts | 1 + src/tools/map.ts | 1 + src/tools/performance.ts | 1 + src/tools/search.ts | 1 + src/tools/smartscraper.ts | 1 + test/tools/annotations.spec.ts | 79 ++++++++++++++++++++++++++++++++++ 10 files changed, 89 insertions(+) create mode 100644 test/tools/annotations.spec.ts diff --git a/src/tools/agent.ts b/src/tools/agent.ts index 75521f8..87413d3 100644 --- a/src/tools/agent.ts +++ b/src/tools/agent.ts @@ -948,6 +948,7 @@ export function registerAgentTools( annotations: { title: 'Load Browserless Skill', readOnlyHint: true, + destructiveHint: false, openWorldHint: false, }, run: async ({ params }) => renderSkill(params.id), @@ -973,6 +974,7 @@ export function registerAgentTools( annotations: { title: 'Browserless Agent', readOnlyHint: false, + destructiveHint: true, openWorldHint: true, }, run: async ({ diff --git a/src/tools/crawl.ts b/src/tools/crawl.ts index 465d655..dbc8087 100644 --- a/src/tools/crawl.ts +++ b/src/tools/crawl.ts @@ -237,6 +237,7 @@ export function registerCrawlTool( annotations: { title: 'Browserless Crawl', readOnlyHint: true, + destructiveHint: false, openWorldHint: true, }, validateUrl: (p) => validateHttpUrl(p.url), diff --git a/src/tools/download.ts b/src/tools/download.ts index f991286..23bad78 100644 --- a/src/tools/download.ts +++ b/src/tools/download.ts @@ -47,6 +47,7 @@ export function registerDownloadTool( annotations: { title: 'Browserless Download', readOnlyHint: false, + destructiveHint: true, openWorldHint: true, }, profileNotFoundMessage: (profile) => diff --git a/src/tools/export.ts b/src/tools/export.ts index 4248890..210a705 100644 --- a/src/tools/export.ts +++ b/src/tools/export.ts @@ -81,6 +81,7 @@ export function registerExportTool( annotations: { title: 'Browserless Export', readOnlyHint: true, + destructiveHint: false, openWorldHint: true, }, validateUrl: (p) => validateHttpUrl(p.url), diff --git a/src/tools/function.ts b/src/tools/function.ts index 85024c2..34570a7 100644 --- a/src/tools/function.ts +++ b/src/tools/function.ts @@ -143,6 +143,7 @@ export function registerFunctionTool( annotations: { title: 'Browserless Function', readOnlyHint: false, + destructiveHint: true, openWorldHint: true, }, profileNotFoundMessage: (profile) => diff --git a/src/tools/map.ts b/src/tools/map.ts index 1558602..9f7938c 100644 --- a/src/tools/map.ts +++ b/src/tools/map.ts @@ -61,6 +61,7 @@ export function registerMapTool( annotations: { title: 'Browserless Map', readOnlyHint: true, + destructiveHint: false, openWorldHint: true, }, validateUrl: (p) => validateHttpUrl(p.url), diff --git a/src/tools/performance.ts b/src/tools/performance.ts index 4b4230c..8a7ecb1 100644 --- a/src/tools/performance.ts +++ b/src/tools/performance.ts @@ -66,6 +66,7 @@ export function registerPerformanceTool( annotations: { title: 'Browserless Lighthouse Performance Audit', readOnlyHint: true, + destructiveHint: false, openWorldHint: true, }, validateUrl: (p) => validateHttpUrl(p.url), diff --git a/src/tools/search.ts b/src/tools/search.ts index 3a68271..e1c7b21 100644 --- a/src/tools/search.ts +++ b/src/tools/search.ts @@ -96,6 +96,7 @@ export function registerSearchTool( annotations: { title: 'Browserless Search', readOnlyHint: true, + destructiveHint: false, openWorldHint: true, }, run: async ({ client, params, log }) => { diff --git a/src/tools/smartscraper.ts b/src/tools/smartscraper.ts index fd6d289..6cc2bac 100644 --- a/src/tools/smartscraper.ts +++ b/src/tools/smartscraper.ts @@ -76,6 +76,7 @@ export function registerSmartScraperTool( annotations: { title: 'Browserless Smart Scraper', readOnlyHint: true, + destructiveHint: false, openWorldHint: true, }, validateUrl: (p) => validateHttpUrl(p.url), diff --git a/test/tools/annotations.spec.ts b/test/tools/annotations.spec.ts new file mode 100644 index 0000000..f7169cc --- /dev/null +++ b/test/tools/annotations.spec.ts @@ -0,0 +1,79 @@ +import { expect } from 'chai'; +import sinon from 'sinon'; +import { FastMCP } from 'fastmcp'; +import { registerSmartScraperTool } from '../../src/tools/smartscraper.js'; +import { registerFunctionTool } from '../../src/tools/function.js'; +import { registerDownloadTool } from '../../src/tools/download.js'; +import { registerExportTool } from '../../src/tools/export.js'; +import { registerAgentTools } from '../../src/tools/agent.js'; +import { registerSearchTool } from '../../src/tools/search.js'; +import { registerMapTool } from '../../src/tools/map.js'; +import { registerCrawlTool } from '../../src/tools/crawl.js'; +import { registerPerformanceTool } from '../../src/tools/performance.js'; +import type { McpConfig } from '../../src/@types/types.js'; + +const mockConfig: McpConfig = { + browserlessToken: 'test-token', + browserlessApiUrl: 'https://api.example.com', + transport: 'stdio', + port: 8080, + requestTimeout: 30000, + maxRetries: 0, + cacheTtlMs: 0, + analyticsEnabled: false, + sqsRegion: 'us-east-1', + oauthEnabled: false, + supabaseUrl: '', + supabaseOAuthClientId: '', + supabaseOAuthClientSecret: '', + supabaseServiceRoleKey: '', + mcpBaseUrl: '', + oauthAllowedRedirectUriPatterns: [], +}; + +// Every register function used by src/index.ts. registerAgentTools registers +// two tools (browserless_skill + browserless_agent); the rest register one. +const registrars = [ + registerSmartScraperTool, + registerFunctionTool, + registerDownloadTool, + registerExportTool, + registerAgentTools, + registerSearchTool, + registerMapTool, + registerCrawlTool, + registerPerformanceTool, +]; + +// MCP clients (notably OpenAI) reject any tool that does not set all three +// behavioural hints to an explicit boolean. fastmcp forwards `annotations` +// verbatim into tools/list, so the hint must live on every tool's annotations. +const REQUIRED_HINTS = [ + 'readOnlyHint', + 'destructiveHint', + 'openWorldHint', +] as const; + +describe('tool annotations', () => { + afterEach(() => sinon.restore()); + + it('every registered tool sets all three behavioural hints as booleans', () => { + const server = new FastMCP({ name: 'test', version: '0.1.0' }); + const addToolSpy = sinon.spy(server, 'addTool'); + + registrars.forEach((register) => register(server, mockConfig)); + + expect(addToolSpy.callCount).to.be.greaterThan(0); + + addToolSpy.getCalls().forEach((call) => { + const tool = call.args[0]; + const annotations = tool.annotations ?? {}; + REQUIRED_HINTS.forEach((hint) => { + expect( + annotations[hint], + `${tool.name} is missing ${hint} (must be an explicit boolean)`, + ).to.be.a('boolean'); + }); + }); + }); +}); From 79ed0d02d87adbc34469a553f113bd5909e76af3 Mon Sep 17 00:00:00 2001 From: Anderson Martinez Date: Wed, 27 May 2026 10:52:22 -0400 Subject: [PATCH 5/6] build: changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dffc48e..26647b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ - Dependency updates -# v1.5.2 - 2026-05-27 +# v1.5.3 - 2026-05-27 - Add destructive hints for tools + +# v1.5.2 - 2026-05-27 + - Enable OpenAI connectors in OAuth # v1.5.0 - 2026-05-26 From 8acab03cfeb022755d06b43a264141d8178ad05d Mon Sep 17 00:00:00 2001 From: Anderson Martinez Date: Wed, 27 May 2026 10:52:51 -0400 Subject: [PATCH 6/6] fix: update version to 1.5.3 in package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index b5c5c35..9ad05b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "browserless-mcp", - "version": "1.3.4", + "version": "1.5.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "browserless-mcp", - "version": "1.3.4", + "version": "1.5.3", "hasInstallScript": true, "license": "SSPL-1.0", "dependencies": {