From ced4f9a0223aea0ab29d129ed73d961272f68b92 Mon Sep 17 00:00:00 2001 From: aberemia24 Date: Tue, 30 Sep 2025 11:25:13 +0300 Subject: [PATCH 1/3] feat(screenshot): add WebP format support with quality parameter Add WebP format to screenshot tool, providing superior compression compared to JPEG. Also fixes bug where saveTemporaryFile always saved files with .png extension regardless of format. --- docs/tool-reference.md | 6 +++++- src/McpContext.ts | 15 +++++++++------ src/tools/ToolDefinition.ts | 2 +- src/tools/screenshot.ts | 4 ++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/tool-reference.md b/docs/tool-reference.md index 517cb75..58ea525 100644 --- a/docs/tool-reference.md +++ b/docs/tool-reference.md @@ -306,10 +306,14 @@ so returned values have to JSON-serializable. **Parameters:** +<<<<<<< HEAD - **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" +>>>>>>> 9b0e51e (feat(screenshot): add WebP format support with quality parameter) - **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() From 3fbc04b8b0be38640b18b34972f0a00324f5bae8 Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Wed, 1 Oct 2025 09:30:30 +0200 Subject: [PATCH 2/3] chore: rebase --- docs/tool-reference.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/tool-reference.md b/docs/tool-reference.md index 58ea525..ea77dd0 100644 --- a/docs/tool-reference.md +++ b/docs/tool-reference.md @@ -306,12 +306,8 @@ so returned values have to JSON-serializable. **Parameters:** -<<<<<<< HEAD - **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" ->>>>>>> 9b0e51e (feat(screenshot): add WebP format support with quality parameter) - **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 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. From e71f820812142260e31ea3f7bbce095753f8b38b Mon Sep 17 00:00:00 2001 From: Alex Rudenko Date: Wed, 1 Oct 2025 09:33:38 +0200 Subject: [PATCH 3/3] test: add atest --- tests/tools/screenshot.test.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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;