diff --git a/src/McpContext.ts b/src/McpContext.ts index ca583d732..32b7413e6 100644 --- a/src/McpContext.ts +++ b/src/McpContext.ts @@ -31,7 +31,6 @@ import type { } from './third_party/index.js'; import {Locator} from './third_party/index.js'; import {PredefinedNetworkConditions} from './third_party/index.js'; -import type {ToolGroup, ToolDefinition} from './tools/inPage.js'; import {listPages} from './tools/pages.js'; import {CLOSE_PAGE_ERROR} from './tools/ToolDefinition.js'; import type {Context, DevToolsData} from './tools/ToolDefinition.js'; @@ -85,7 +84,6 @@ export class McpContext implements Context { #screenRecorderData: {recorder: ScreenRecorder; filePath: string} | null = null; - #inPageTools?: ToolGroup; #nextPageId = 1; #extensionPages = new WeakMap(); @@ -449,14 +447,6 @@ export class McpContext implements Context { this.#updateSelectedPageTimeouts(); } - setInPageTools(toolGroup?: ToolGroup) { - this.#inPageTools = toolGroup; - } - - getInPageTools(): ToolGroup | undefined { - return this.#inPageTools; - } - #updateSelectedPageTimeouts() { const page = this.#getSelectedMcpPage(); // For waiters 5sec timeout should be sufficient. diff --git a/src/McpPage.ts b/src/McpPage.ts index e65c78dfa..1e311bc62 100644 --- a/src/McpPage.ts +++ b/src/McpPage.ts @@ -10,6 +10,7 @@ import type { Page, Viewport, } from './third_party/index.js'; +import type {ToolGroup, ToolDefinition} from './tools/inPage.js'; import {takeSnapshot} from './tools/snapshot.js'; import type {ContextPage} from './tools/ToolDefinition.js'; import type { @@ -50,6 +51,8 @@ export class McpPage implements ContextPage { #dialog?: Dialog; #dialogHandler: (dialog: Dialog) => void; + inPageTools: ToolGroup | undefined; + constructor(page: Page, id: number) { this.pptrPage = page; this.id = id; @@ -71,6 +74,10 @@ export class McpPage implements ContextPage { this.#dialog = undefined; } + getInPageTools(): ToolGroup | undefined { + return this.inPageTools; + } + get networkConditions(): string | null { return this.emulationSettings.networkConditions ?? null; } diff --git a/src/McpResponse.ts b/src/McpResponse.ts index 98bf25082..ed20e4c4f 100644 --- a/src/McpResponse.ts +++ b/src/McpResponse.ts @@ -421,8 +421,9 @@ export class McpResponse implements Response { let inPageTools: ToolGroup | undefined; if (this.#listInPageTools) { - inPageTools = await getToolGroup(context.getSelectedMcpPage()); - context.setInPageTools(inPageTools); + const page = this.#page ?? context.getSelectedMcpPage(); + inPageTools = await getToolGroup(page); + page.inPageTools = inPageTools; } let consoleMessages: Array | undefined; diff --git a/src/tools/ToolDefinition.ts b/src/tools/ToolDefinition.ts index 463c515fb..8001e18c7 100644 --- a/src/tools/ToolDefinition.ts +++ b/src/tools/ToolDefinition.ts @@ -194,7 +194,6 @@ export type Context = Readonly<{ triggerExtensionAction(id: string): Promise; listExtensions(): InstalledExtension[]; getExtension(id: string): InstalledExtension | undefined; - getInPageTools(): ToolGroup | undefined; getSelectedMcpPage(): McpPage; getExtensionServiceWorkers(): ExtensionServiceWorker[]; getExtensionServiceWorkerId( @@ -213,6 +212,7 @@ export type ContextPage = Readonly<{ action: () => Promise, options?: {timeout?: number}, ): Promise; + getInPageTools(): ToolGroup | undefined; }>; export function defineTool( diff --git a/src/tools/inPage.ts b/src/tools/inPage.ts index 34ede867e..5b0031f62 100644 --- a/src/tools/inPage.ts +++ b/src/tools/inPage.ts @@ -70,8 +70,7 @@ export const executeInPageTool = definePageTool({ .optional() .describe('The JSON-stringified parameters to pass to the tool'), }, - handler: async (request, response, context) => { - const page = request.page; + handler: async (request, response) => { const toolName = request.params.toolName; let params: Record = {}; if (request.params.params) { @@ -88,7 +87,7 @@ export const executeInPageTool = definePageTool({ } } - const toolGroup = context.getInPageTools(); + const toolGroup = request.page.getInPageTools(); const tool = toolGroup?.tools.find(t => t.name === toolName); if (!tool) { throw new Error(`Tool ${toolName} not found`); @@ -102,7 +101,7 @@ export const executeInPageTool = definePageTool({ ); } - const result = await page.pptrPage.evaluate( + const result = await request.page.pptrPage.evaluate( async (name, args) => { if (!window.__dtmcp?.executeTool) { throw new Error('No tools found on the page'); diff --git a/tests/tools/inPage.test.ts b/tests/tools/inPage.test.ts index cc1ceb876..622da9034 100644 --- a/tests/tools/inPage.test.ts +++ b/tests/tools/inPage.test.ts @@ -20,6 +20,7 @@ describe('inPage', () => { await withMcpContext( async (response, context) => { const page = await context.newPage(); + response.setPage(page); await page.pptrPage.evaluate(() => { window.__dtmcp = { @@ -76,6 +77,7 @@ describe('inPage', () => { await withMcpContext( async (response, context) => { const page = await context.newPage(); + response.setPage(page); await page.pptrPage.evaluate(() => { window.addEventListener('devtoolstooldiscovery', (e: Event) => { // @ts-expect-error Event has `respondWith` @@ -105,6 +107,7 @@ describe('inPage', () => { await withMcpContext( async (response, context) => { const page = await context.newPage(); + response.setPage(page); await page.pptrPage.evaluate(() => { window.addEventListener('devtoolstooldiscovery', () => { // do nothing @@ -133,6 +136,7 @@ describe('inPage', () => { await withMcpContext( async (response, context) => { const page = await context.newPage(); + response.setPage(page); await listInPageTools.handler({params: {}, page}, response, context); const result = await response.handle('list_in_page_tools', context); @@ -155,6 +159,7 @@ describe('inPage', () => { evaluateFn: () => void, ) { const page = await context.newPage(); + response.setPage(page); await page.pptrPage.evaluate(evaluateFn); await listInPageTools.handler({params: {}, page}, response, context); await response.handle('list_in_page_tools', context);