From d381b8dd64b6d6ed58708b99471cae1f16e97271 Mon Sep 17 00:00:00 2001 From: Samiya Caur Date: Fri, 24 Apr 2026 13:35:46 +0200 Subject: [PATCH 1/3] fix: Handle errors during tool calls and check if a dialog is open This change also adds a check for existence of open dialogs before trying to detect open devtools --- src/WaitForHelper.ts | 6 ++++++ src/index.ts | 17 ++++++++++------- src/tools/ToolDefinition.ts | 12 ++++++++++++ 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/WaitForHelper.ts b/src/WaitForHelper.ts index f41ca84cc..6a67224c3 100644 --- a/src/WaitForHelper.ts +++ b/src/WaitForHelper.ts @@ -128,8 +128,10 @@ export class WaitForHelper { action: () => Promise, options?: {timeout?: number; handleDialog?: 'accept' | 'dismiss' | string}, ): Promise { + let dialogOpened = false; if (options?.handleDialog) { const dialogHandler = (dialog: Pick) => { + dialogOpened = true; if (options.handleDialog === 'dismiss') { void dialog.dismiss(); } else if (options.handleDialog === 'accept') { @@ -167,6 +169,10 @@ export class WaitForHelper { try { await navigationFinished; + if (dialogOpened) { + return; + } + // Wait for stable dom after navigation so we execute in // the correct context await this.waitForStableDom(); diff --git a/src/index.ts b/src/index.ts index 24b7d42a0..f7d550681 100644 --- a/src/index.ts +++ b/src/index.ts @@ -199,19 +199,22 @@ export async function createMcpServer( logger(`${tool.name} request: ${JSON.stringify(params, null, ' ')}`); const context = await getContext(); logger(`${tool.name} context: resolved`); - await context.detectOpenDevToolsWindows(); + const page = + serverArgs.experimentalPageIdRouting && + params.pageId && + !serverArgs.slim + ? context.getPageById(params.pageId) + : context.getSelectedMcpPage(); + // If there is a dialog open, we will skip devtools detection + if (!page.getDialog()) { + await context.detectOpenDevToolsWindows(); + } const response = serverArgs.slim ? new SlimMcpResponse(serverArgs) : new McpResponse(serverArgs); response.setRedactNetworkHeaders(serverArgs.redactNetworkHeaders); if ('pageScoped' in tool && tool.pageScoped) { - const page = - serverArgs.experimentalPageIdRouting && - params.pageId && - !serverArgs.slim - ? context.getPageById(params.pageId) - : context.getSelectedMcpPage(); response.setPage(page); await tool.handler( { diff --git a/src/tools/ToolDefinition.ts b/src/tools/ToolDefinition.ts index 762c800c4..ed2931bf9 100644 --- a/src/tools/ToolDefinition.ts +++ b/src/tools/ToolDefinition.ts @@ -336,6 +336,18 @@ export function definePageTool< return { ...definition, pageScoped: true, + handler: async (request, response, context) => { + try { + await definition.handler(request, response, context); + } catch (error) { + const dialog = request.page.getDialog(); + if (dialog) { + response.appendResponseLine(`[Blocked] Action triggered a dialog.`); + return; + } + throw error; + } + }, } as DefinedPageTool; } From 128195baf82ae0085e69b10f06e03e7ae48e3265 Mon Sep 17 00:00:00 2001 From: Samiya Caur Date: Mon, 27 Apr 2026 14:32:58 +0200 Subject: [PATCH 2/3] ran prettier --- src/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index f7d550681..8e1063470 100644 --- a/src/index.ts +++ b/src/index.ts @@ -201,8 +201,8 @@ export async function createMcpServer( logger(`${tool.name} context: resolved`); const page = serverArgs.experimentalPageIdRouting && - params.pageId && - !serverArgs.slim + params.pageId && + !serverArgs.slim ? context.getPageById(params.pageId) : context.getSelectedMcpPage(); // If there is a dialog open, we will skip devtools detection From 452490dba46856c37f19850f54ffeab5b35383fd Mon Sep 17 00:00:00 2001 From: Samiya Caur Date: Mon, 27 Apr 2026 15:16:24 +0200 Subject: [PATCH 3/3] add try catch block in index.ts to handle dialog --- src/index.ts | 44 ++++++++++++++++++++++--------------- src/tools/ToolDefinition.ts | 12 ---------- 2 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/index.ts b/src/index.ts index abc1850bd..2bb9abb7c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -226,31 +226,39 @@ export async function createMcpServer( logger(`${tool.name} request: ${JSON.stringify(params, null, ' ')}`); const context = await getContext(); logger(`${tool.name} context: resolved`); - const page = - serverArgs.experimentalPageIdRouting && - params.pageId && - !serverArgs.slim - ? context.getPageById(params.pageId) - : context.getSelectedMcpPage(); - // If there is a dialog open, we will skip devtools detection - if (!page.getDialog()) { - await context.detectOpenDevToolsWindows(); - } + await context.detectOpenDevToolsWindows(); const response = serverArgs.slim ? new SlimMcpResponse(serverArgs) : new McpResponse(serverArgs); response.setRedactNetworkHeaders(serverArgs.redactNetworkHeaders); if ('pageScoped' in tool && tool.pageScoped) { + const page = + serverArgs.experimentalPageIdRouting && + params.pageId && + !serverArgs.slim + ? context.getPageById(params.pageId) + : context.getSelectedMcpPage(); response.setPage(page); - await tool.handler( - { - params, - page, - }, - response, - context, - ); + try { + await tool.handler( + { + params, + page, + }, + response, + context, + ); + } catch (error) { + const dialog = page.getDialog(); + if (dialog) { + response.appendResponseLine( + `[Blocked] Action triggered a dialog.`, + ); + } else { + throw error; + } + } } else { await tool.handler( // @ts-expect-error types do not match. diff --git a/src/tools/ToolDefinition.ts b/src/tools/ToolDefinition.ts index 8eb9bd3ed..91c42dcc2 100644 --- a/src/tools/ToolDefinition.ts +++ b/src/tools/ToolDefinition.ts @@ -348,18 +348,6 @@ export function definePageTool< return { ...definition, pageScoped: true, - handler: async (request, response, context) => { - try { - await definition.handler(request, response, context); - } catch (error) { - const dialog = request.page.getDialog(); - if (dialog) { - response.appendResponseLine(`[Blocked] Action triggered a dialog.`); - return; - } - throw error; - } - }, } as DefinedPageTool; }