diff --git a/docs/tool-reference.md b/docs/tool-reference.md index 517cb75..ea77dd0 100644 --- a/docs/tool-reference.md +++ b/docs/tool-reference.md @@ -307,9 +307,9 @@ so returned values have to JSON-serializable. **Parameters:** - **filePath** (string) _(optional)_: The absolute path, or a path relative to the current working directory, to save the screenshot to instead of attaching it to the response. -- **format** (enum: "png", "jpeg") _(optional)_: Type of format to save the screenshot as. Default is "png" +- **format** (enum: "png", "jpeg", "webp") _(optional)_: Type of format to save the screenshot as. Default is "png" - **fullPage** (boolean) _(optional)_: If set to true takes a screenshot of the full page instead of the currently visible viewport. Incompatible with uid. -- **quality** (number) _(optional)_: Compression quality for JPEG format (0-100). Higher values mean better quality but larger file sizes. Ignored for PNG format. +- **quality** (number) _(optional)_: Compression quality for JPEG and WebP formats (0-100). Higher values mean better quality but larger file sizes. Ignored for PNG format. - **uid** (string) _(optional)_: The uid of an element on the page from the page content snapshot. If omitted takes a pages screenshot. --- diff --git a/src/McpContext.ts b/src/McpContext.ts index 57fab79..ce98076 100644 --- a/src/McpContext.ts +++ b/src/McpContext.ts @@ -340,17 +340,20 @@ export class McpContext implements Context { async saveTemporaryFile( data: Uint8Array, - mimeType: 'image/png' | 'image/jpeg', + mimeType: 'image/png' | 'image/jpeg' | 'image/webp', ): Promise<{filename: string}> { try { const dir = await fs.mkdtemp( path.join(os.tmpdir(), 'chrome-devtools-mcp-'), ); - const filename = path.join( - dir, - mimeType == 'image/png' ? `screenshot.png` : 'screenshot.jpg', - ); - await fs.writeFile(path.join(dir, `screenshot.png`), data); + const ext = + mimeType === 'image/png' + ? 'png' + : mimeType === 'image/jpeg' + ? 'jpg' + : 'webp'; + const filename = path.join(dir, `screenshot.${ext}`); + await fs.writeFile(filename, data); return {filename}; } catch (err) { this.logger(err); diff --git a/src/tools/ToolDefinition.ts b/src/tools/ToolDefinition.ts index a0741f4..c617e8d 100644 --- a/src/tools/ToolDefinition.ts +++ b/src/tools/ToolDefinition.ts @@ -72,7 +72,7 @@ export type Context = Readonly<{ setCpuThrottlingRate(rate: number): void; saveTemporaryFile( data: Uint8Array, - mimeType: 'image/png' | 'image/jpeg', + mimeType: 'image/png' | 'image/jpeg' | 'image/webp', ): Promise<{filename: string}>; waitForEventsAfterAction(action: () => Promise): Promise; }>; diff --git a/src/tools/screenshot.ts b/src/tools/screenshot.ts index f92f800..1a24eff 100644 --- a/src/tools/screenshot.ts +++ b/src/tools/screenshot.ts @@ -21,7 +21,7 @@ export const screenshot = defineTool({ }, schema: { format: z - .enum(['png', 'jpeg']) + .enum(['png', 'jpeg', 'webp']) .default('png') .describe('Type of format to save the screenshot as. Default is "png"'), quality: z @@ -30,7 +30,7 @@ export const screenshot = defineTool({ .max(100) .optional() .describe( - 'Compression quality for JPEG format (0-100). Higher values mean better quality but larger file sizes. Ignored for PNG format.', + 'Compression quality for JPEG and WebP formats (0-100). Higher values mean better quality but larger file sizes. Ignored for PNG format.', ), uid: z .string() diff --git a/tests/tools/screenshot.test.ts b/tests/tools/screenshot.test.ts index 6902737..d369f2c 100644 --- a/tests/tools/screenshot.test.ts +++ b/tests/tools/screenshot.test.ts @@ -42,6 +42,18 @@ describe('screenshot', () => { ); }); }); + it('with webp', async () => { + await withBrowser(async (response, context) => { + await screenshot.handler({params: {format: 'webp'}}, response, context); + + assert.equal(response.images.length, 1); + assert.equal(response.images[0].mimeType, 'image/webp'); + assert.equal( + response.responseLines.at(0), + "Took a screenshot of the current page's viewport.", + ); + }); + }); it('with full page', async () => { await withBrowser(async (response, context) => { const fixture = screenshots.viewportOverflow;