Skip to content

Commit 74c6d6d

Browse files
refactor: use context agnostic write to file (#250)
Similar to the write to temporary file we should hide the implementation behind the Context
1 parent 639d57d commit 74c6d6d

File tree

3 files changed

+37
-14
lines changed

3 files changed

+37
-14
lines changed

src/McpContext.ts

Lines changed: 31 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,18 @@ function getNetworkMultiplierFromString(condition: string | null): number {
5858
return 1;
5959
}
6060

61+
function getExtensionFromMimeType(mimeType: string) {
62+
switch (mimeType) {
63+
case 'image/png':
64+
return 'png';
65+
case 'image/jpeg':
66+
return 'jpeg';
67+
case 'image/webp':
68+
return 'webp';
69+
}
70+
throw new Error(`No mapping for Mime type ${mimeType}.`);
71+
}
72+
6173
export class McpContext implements Context {
6274
browser: Browser;
6375
logger: Debugger;
@@ -346,18 +358,29 @@ export class McpContext implements Context {
346358
const dir = await fs.mkdtemp(
347359
path.join(os.tmpdir(), 'chrome-devtools-mcp-'),
348360
);
349-
const ext =
350-
mimeType === 'image/png'
351-
? 'png'
352-
: mimeType === 'image/jpeg'
353-
? 'jpg'
354-
: 'webp';
355-
const filename = path.join(dir, `screenshot.${ext}`);
361+
362+
const filename = path.join(
363+
dir,
364+
`screenshot.${getExtensionFromMimeType(mimeType)}`,
365+
);
356366
await fs.writeFile(filename, data);
357367
return {filename};
358368
} catch (err) {
359369
this.logger(err);
360-
throw new Error('Could not save a screenshot to a file');
370+
throw new Error('Could not save a screenshot to a file', {cause: err});
371+
}
372+
}
373+
async saveFile(
374+
data: Uint8Array<ArrayBufferLike>,
375+
filename: string,
376+
): Promise<{filename: string}> {
377+
try {
378+
const filePath = path.resolve(filename);
379+
await fs.writeFile(filePath, data);
380+
return {filename};
381+
} catch (err) {
382+
this.logger(err);
383+
throw new Error('Could not save a screenshot to a file', {cause: err});
361384
}
362385
}
363386

src/tools/ToolDefinition.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ export type Context = Readonly<{
7474
data: Uint8Array<ArrayBufferLike>,
7575
mimeType: 'image/png' | 'image/jpeg' | 'image/webp',
7676
): Promise<{filename: string}>;
77+
saveFile(
78+
data: Uint8Array<ArrayBufferLike>,
79+
filename: string,
80+
): Promise<{filename: string}>;
7781
waitForEventsAfterAction(action: () => Promise<unknown>): Promise<void>;
7882
}>;
7983

src/tools/screenshot.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

7-
import {writeFile} from 'node:fs/promises';
8-
97
import type {ElementHandle, Page} from 'puppeteer-core';
108
import z from 'zod';
119

@@ -85,10 +83,8 @@ export const screenshot = defineTool({
8583
}
8684

8785
if (request.params.filePath) {
88-
await writeFile(request.params.filePath, screenshot);
89-
response.appendResponseLine(
90-
`Saved screenshot to ${request.params.filePath}.`,
91-
);
86+
const file = await context.saveFile(screenshot, request.params.filePath);
87+
response.appendResponseLine(`Saved screenshot to ${file.filename}.`);
9288
} else if (screenshot.length >= 2_000_000) {
9389
const {filename} = await context.saveTemporaryFile(
9490
screenshot,

0 commit comments

Comments
 (0)