Skip to content

Commit f0bf89e

Browse files
committed
chore: use playwright-mcp flag to omit images
1 parent 287d15f commit f0bf89e

File tree

4 files changed

+75
-121
lines changed

4 files changed

+75
-121
lines changed

src/_internal/browser-eval-manager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export async function startBrowserEvalMCP(options?: {
6363
console.error("[Browser Eval Manager] Starting playwright-mcp server with verbose logging...")
6464

6565
// Build args for playwright-mcp
66-
const args: string[] = ["@playwright/mcp@latest"]
66+
const args: string[] = ["@playwright/mcp@latest", "--image-responses", "omit"]
6767

6868
if (options?.browser) {
6969
args.push("--browser", options.browser)

src/tools/browser-eval.ts

Lines changed: 1 addition & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -149,45 +149,6 @@ type BrowserEvalArgs = {
149149
files?: string[]
150150
}
151151

152-
/**
153-
* Filter out base64 image data from the `screenshot` result to reduce context usage.
154-
* Extract file paths from text content and attach guidance.
155-
*/
156-
export function filterImageDataFromResult(result: unknown): unknown {
157-
if (typeof result !== "object" || result === null) {
158-
return result
159-
}
160-
161-
const typedResult = result as { content?: { type: string; text?: string; data?: string }[] }
162-
163-
if (!Array.isArray(typedResult.content)) {
164-
return result
165-
}
166-
167-
const filteredContent = typedResult.content.filter((block) => block.type !== "image")
168-
169-
const textBlock = filteredContent.find((block) => block.type === "text")
170-
let screenshotPath: string | null = null
171-
172-
if (textBlock?.text) {
173-
// Extract file path from text like "saved it as /path/to/screenshot.png"
174-
const pathMatch = textBlock.text.match(/(?:saved (?:it )?as|saved to) (.+\.png)/i)
175-
if (pathMatch) {
176-
screenshotPath = pathMatch[1]
177-
}
178-
}
179-
180-
// Add helpful message about reading the screenshot
181-
if (screenshotPath && textBlock) {
182-
filteredContent.push({
183-
type: "text",
184-
text: `\n\nTo view this screenshot, use the "read" tool with the file path: ${screenshotPath}`,
185-
})
186-
}
187-
188-
return { ...typedResult, content: filteredContent }
189-
}
190-
191152
export async function handler(args: BrowserEvalArgs): Promise<string> {
192153
try {
193154
if (args.action === "start") {
@@ -327,13 +288,10 @@ export async function handler(args: BrowserEvalArgs): Promise<string> {
327288

328289
const result = await callServerTool(connection, toolName, toolArgs)
329290

330-
const formattedResult =
331-
args.action === "screenshot" ? filterImageDataFromResult(result) : result
332-
333291
return JSON.stringify({
334292
success: true,
335293
action: args.action,
336-
result: formattedResult,
294+
result,
337295
})
338296
} catch (error) {
339297
const errorMessage = error instanceof Error ? error.message : String(error)

test/unit/browser-eval-filter.test.ts

Lines changed: 0 additions & 77 deletions
This file was deleted.
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
2+
3+
// Mock the mcp-client module before importing browser-eval-manager
4+
vi.mock("../../src/_internal/mcp-client.js", () => ({
5+
connectToMCPServer: vi.fn(),
6+
callServerTool: vi.fn(),
7+
listServerTools: vi.fn(),
8+
}))
9+
10+
// Mock the exec function to skip installation check
11+
vi.mock("child_process", () => ({
12+
exec: vi.fn((cmd, callback) => {
13+
callback(null, { stdout: "@playwright/[email protected]" })
14+
}),
15+
}))
16+
17+
import { connectToMCPServer, callServerTool } from "../../src/_internal/mcp-client.js"
18+
import {
19+
startBrowserEvalMCP,
20+
stopBrowserEvalMCP,
21+
} from "../../src/_internal/browser-eval-manager.js"
22+
import { handler } from "../../src/tools/browser-eval.js"
23+
24+
describe("browser-eval playwright-mcp screenshot tool", () => {
25+
beforeEach(() => {
26+
vi.clearAllMocks()
27+
vi.mocked(connectToMCPServer).mockResolvedValue({
28+
client: { close: vi.fn() },
29+
transport: { close: vi.fn() },
30+
} as never)
31+
})
32+
33+
afterEach(async () => {
34+
await stopBrowserEvalMCP()
35+
})
36+
37+
it("should pass --image-responses omit flag to playwright-mcp", async () => {
38+
await startBrowserEvalMCP()
39+
40+
expect(connectToMCPServer).toHaveBeenCalledWith(
41+
"npx",
42+
expect.arrayContaining(["--image-responses", "omit"]),
43+
expect.any(Object)
44+
)
45+
})
46+
47+
it("should return screenshot file path without base64 image data", async () => {
48+
await startBrowserEvalMCP()
49+
50+
const screenshotPath = "/var/folders/tmp/screenshot-1234.png"
51+
vi.mocked(callServerTool).mockResolvedValue({
52+
content: [{ type: "text", text: `Screenshot saved to ${screenshotPath}` }],
53+
})
54+
55+
const result = await handler({ action: "screenshot" })
56+
const parsed = JSON.parse(result)
57+
58+
expect(parsed.success).toBe(true)
59+
expect(parsed.action).toBe("screenshot")
60+
61+
// Verify response contains file path
62+
const textContent = parsed.result.content.find(
63+
(block: { type: string }) => block.type === "text"
64+
)
65+
expect(textContent.text).toContain(screenshotPath)
66+
67+
// Verify no base64 image data in response
68+
const imageContent = parsed.result.content.find(
69+
(block: { type: string }) => block.type === "image"
70+
)
71+
expect(imageContent).toBeUndefined()
72+
})
73+
})

0 commit comments

Comments
 (0)