@playwright/mcp 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -224,6 +224,11 @@ The Playwright MCP provides a set of tools for browser automation. Here are all
224
224
  - Description: Save page as PDF
225
225
  - Parameters: None
226
226
 
227
+ - **browser_take_screenshot**
228
+ - Description: Capture screenshot of the page
229
+ - Parameters:
230
+ - `raw` (string): Optionally returns lossless PNG screenshot. JPEG by default.
231
+
227
232
  - **browser_wait**
228
233
  - Description: Wait for a specified time in seconds
229
234
  - Parameters:
package/lib/context.js CHANGED
@@ -87,7 +87,7 @@ class Context {
87
87
  this._page = undefined;
88
88
  this._console.length = 0;
89
89
  }
90
- async existingPage() {
90
+ existingPage() {
91
91
  if (!this._page)
92
92
  throw new Error('Navigate to a location to create a page');
93
93
  return this._page;
package/lib/index.js CHANGED
@@ -69,6 +69,7 @@ const snapshotTools = [
69
69
  snapshot.hover,
70
70
  snapshot.type,
71
71
  snapshot.selectOption,
72
+ snapshot.screenshot,
72
73
  ...commonTools,
73
74
  ];
74
75
  const screenshotTools = [
package/lib/program.js CHANGED
@@ -39,6 +39,7 @@ commander_1.program
39
39
  const server = (0, index_1.createServer)({
40
40
  userDataDir: options.userDataDir ?? await userDataDir(),
41
41
  launchOptions,
42
+ vision: !!options.vision,
42
43
  });
43
44
  setupExitWatchdog(server);
44
45
  const transport = new stdio_js_1.StdioServerTransport();
@@ -118,7 +118,7 @@ exports.pdf = {
118
118
  inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(pdfSchema),
119
119
  },
120
120
  handle: async (context) => {
121
- const page = await context.existingPage();
121
+ const page = context.existingPage();
122
122
  const fileName = path_1.default.join(os_1.default.tmpdir(), `/page-${new Date().toISOString()}.pdf`);
123
123
  await page.pdf({ path: fileName });
124
124
  return {
@@ -26,7 +26,7 @@ exports.screenshot = {
26
26
  inputSchema: (0, zod_to_json_schema_1.zodToJsonSchema)(zod_1.z.object({})),
27
27
  },
28
28
  handle: async (context) => {
29
- const page = await context.existingPage();
29
+ const page = context.existingPage();
30
30
  const screenshot = await page.screenshot({ type: 'jpeg', quality: 50, scale: 'css' });
31
31
  return {
32
32
  content: [{ type: 'image', data: screenshot.toString('base64'), mimeType: 'image/jpeg' }],
@@ -48,7 +48,7 @@ exports.moveMouse = {
48
48
  },
49
49
  handle: async (context, params) => {
50
50
  const validatedParams = moveMouseSchema.parse(params);
51
- const page = await context.existingPage();
51
+ const page = context.existingPage();
52
52
  await page.mouse.move(validatedParams.x, validatedParams.y);
53
53
  return {
54
54
  content: [{ type: 'text', text: `Moved mouse to (${validatedParams.x}, ${validatedParams.y})` }],
@@ -18,7 +18,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
18
18
  return (mod && mod.__esModule) ? mod : { "default": mod };
19
19
  };
20
20
  Object.defineProperty(exports, "__esModule", { value: true });
21
- exports.selectOption = exports.type = exports.hover = exports.drag = exports.click = exports.snapshot = void 0;
21
+ exports.screenshot = exports.selectOption = exports.type = exports.hover = exports.drag = exports.click = exports.snapshot = void 0;
22
22
  const zod_1 = require("zod");
23
23
  const zod_to_json_schema_1 = __importDefault(require("zod-to-json-schema"));
24
24
  const utils_1 = require("./utils");
@@ -29,7 +29,7 @@ exports.snapshot = {
29
29
  inputSchema: (0, zod_to_json_schema_1.default)(zod_1.z.object({})),
30
30
  },
31
31
  handle: async (context) => {
32
- return await (0, utils_1.captureAriaSnapshot)(await context.existingPage());
32
+ return await (0, utils_1.captureAriaSnapshot)(context.existingPage());
33
33
  },
34
34
  };
35
35
  const elementSchema = zod_1.z.object({
@@ -116,6 +116,32 @@ exports.selectOption = {
116
116
  }, true);
117
117
  },
118
118
  };
119
+ const screenshotSchema = zod_1.z.object({
120
+ raw: zod_1.z.boolean().optional().describe('Whether to return without compression (in PNG format). Default is false, which returns a JPEG image.'),
121
+ });
122
+ exports.screenshot = {
123
+ schema: {
124
+ name: 'browser_take_screenshot',
125
+ description: `Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.`,
126
+ inputSchema: (0, zod_to_json_schema_1.default)(screenshotSchema),
127
+ },
128
+ handle: async (context, params) => {
129
+ const validatedParams = screenshotSchema.parse(params);
130
+ const page = context.existingPage();
131
+ const options = validatedParams.raw ? { type: 'png', scale: 'css' } : { type: 'jpeg', quality: 50, scale: 'css' };
132
+ const screenshot = await page.screenshot(options);
133
+ return {
134
+ content: [{ type: 'image', data: screenshot.toString('base64'), mimeType: validatedParams.raw ? 'image/png' : 'image/jpeg' }],
135
+ };
136
+ },
137
+ };
119
138
  function refLocator(page, ref) {
120
- return page.locator(`aria-ref=${ref}`);
139
+ let frame = page.frames()[0];
140
+ const match = ref.match(/^f(\d+)(.*)/);
141
+ if (match) {
142
+ const frameIndex = parseInt(match[1], 10);
143
+ frame = page.frames()[frameIndex];
144
+ ref = match[2];
145
+ }
146
+ return frame.locator(`aria-ref=${ref}`);
121
147
  }
@@ -16,6 +16,7 @@
16
16
  */
17
17
  Object.defineProperty(exports, "__esModule", { value: true });
18
18
  exports.runAndWait = runAndWait;
19
+ exports.captureAllFrameSnapshot = captureAllFrameSnapshot;
19
20
  exports.captureAriaSnapshot = captureAriaSnapshot;
20
21
  async function waitForCompletion(page, callback) {
21
22
  const requests = new Set();
@@ -65,21 +66,29 @@ async function waitForCompletion(page, callback) {
65
66
  }
66
67
  }
67
68
  async function runAndWait(context, status, callback, snapshot = false) {
68
- const page = await context.existingPage();
69
+ const page = context.existingPage();
69
70
  await waitForCompletion(page, () => callback(page));
70
71
  return snapshot ? captureAriaSnapshot(page, status) : {
71
72
  content: [{ type: 'text', text: status }],
72
73
  };
73
74
  }
75
+ async function captureAllFrameSnapshot(page) {
76
+ const snapshots = await Promise.all(page.frames().map(frame => frame.locator('html').ariaSnapshot({ ref: true })));
77
+ const scopedSnapshots = snapshots.map((snapshot, frameIndex) => {
78
+ if (frameIndex === 0)
79
+ return snapshot;
80
+ return snapshot.replaceAll('[ref=', `[ref=f${frameIndex}`);
81
+ });
82
+ return scopedSnapshots.join('\n');
83
+ }
74
84
  async function captureAriaSnapshot(page, status = '') {
75
- const snapshot = await page.locator('html').ariaSnapshot({ ref: true });
76
85
  return {
77
86
  content: [{ type: 'text', text: `${status ? `${status}\n` : ''}
78
87
  - Page URL: ${page.url()}
79
88
  - Page Title: ${await page.title()}
80
89
  - Page Snapshot
81
90
  \`\`\`yaml
82
- ${snapshot}
91
+ ${await captureAllFrameSnapshot(page)}
83
92
  \`\`\`
84
93
  `
85
94
  }],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@playwright/mcp",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Playwright Tools for MCP",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,7 +18,9 @@
18
18
  "build": "tsc",
19
19
  "lint": "eslint .",
20
20
  "watch": "tsc --watch",
21
- "test": "playwright test"
21
+ "test": "playwright test",
22
+ "clean": "rm -rf lib",
23
+ "publish": "npm run clean && npm run build && npm run test && npm publish"
22
24
  },
23
25
  "exports": {
24
26
  "./package.json": "./package.json",