From e729494bd9bf5181a308f8d402c763b8392ae594 Mon Sep 17 00:00:00 2001 From: Simon Knott Date: Tue, 15 Apr 2025 01:09:48 +0200 Subject: [PATCH] feat: browser_resize (#92) --- src/index.ts | 4 ++-- src/tools/common.ts | 31 +++++++++++++++++++++++++++++-- tests/basic.spec.ts | 19 +++++++++++++++++++ tests/capabilities.spec.ts | 2 ++ 4 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/index.ts b/src/index.ts index 2d28e72..0900fb9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,7 +32,7 @@ import type { Server } from '@modelcontextprotocol/sdk/server/index.js'; import type { LaunchOptions } from 'playwright'; const snapshotTools: Tool[] = [ - ...common, + ...common(true), ...files(true), ...install, ...keyboard(true), @@ -43,7 +43,7 @@ const snapshotTools: Tool[] = [ ]; const screenshotTools: Tool[] = [ - ...common, + ...common(false), ...files(false), ...install, ...keyboard(false), diff --git a/src/tools/common.ts b/src/tools/common.ts index 93e6650..82f79e3 100644 --- a/src/tools/common.ts +++ b/src/tools/common.ts @@ -17,7 +17,7 @@ import { z } from 'zod'; import { zodToJsonSchema } from 'zod-to-json-schema'; -import type { Tool } from './tool'; +import type { Tool, ToolFactory } from './tool'; const waitSchema = z.object({ time: z.number().describe('The time to wait in seconds'), @@ -62,7 +62,34 @@ const close: Tool = { }, }; -export default [ +const resizeSchema = z.object({ + width: z.number().describe('Width of the browser window'), + height: z.number().describe('Height of the browser window'), +}); + +const resize: ToolFactory = captureSnapshot => ({ + capability: 'core', + schema: { + name: 'browser_resize', + description: 'Resize the browser window', + inputSchema: zodToJsonSchema(resizeSchema), + }, + handle: async (context, params) => { + const validatedParams = resizeSchema.parse(params); + + const tab = context.currentTab(); + return await tab.run( + tab => tab.page.setViewportSize({ width: validatedParams.width, height: validatedParams.height }), + { + status: `Resized browser window`, + captureSnapshot, + } + ); + }, +}); + +export default (captureSnapshot: boolean) => [ close, wait, + resize(captureSnapshot) ]; diff --git a/tests/basic.spec.ts b/tests/basic.spec.ts index 4113f36..13f5684 100644 --- a/tests/basic.spec.ts +++ b/tests/basic.spec.ts @@ -233,3 +233,22 @@ test('browser_type (slowly)', async ({ client }) => { ].join('\n'), }]); }); + +test('browser_resize', async ({ client }) => { + await client.callTool({ + name: 'browser_navigate', + arguments: { + url: 'data:text/html,Resize Test
Waiting for resize...
', + }, + }); + + const response = await client.callTool({ + name: 'browser_resize', + arguments: { + width: 390, + height: 780, + }, + }); + expect(response).toContainTextContent('Resized browser window'); + expect(response).toContainTextContent('Window size: 390x780'); +}); diff --git a/tests/capabilities.spec.ts b/tests/capabilities.spec.ts index 8301bc1..e3ee91f 100644 --- a/tests/capabilities.spec.ts +++ b/tests/capabilities.spec.ts @@ -32,6 +32,7 @@ test('test snapshot tool list', async ({ client }) => { 'browser_navigate', 'browser_pdf_save', 'browser_press_key', + 'browser_resize', 'browser_snapshot', 'browser_tab_close', 'browser_tab_list', @@ -53,6 +54,7 @@ test('test vision tool list', async ({ visionClient }) => { 'browser_navigate', 'browser_pdf_save', 'browser_press_key', + 'browser_resize', 'browser_screen_capture', 'browser_screen_click', 'browser_screen_drag',