@playwright/mcp 0.0.20 → 0.0.24
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 +95 -16
- package/config.d.ts +15 -15
- package/index.d.ts +8 -2
- package/index.js +2 -2
- package/lib/config.js +16 -18
- package/lib/{server.js → connection.js} +31 -28
- package/lib/context.js +37 -3
- package/lib/index.js +3 -51
- package/lib/pageSnapshot.js +8 -55
- package/lib/program.js +15 -9
- package/lib/tab.js +24 -10
- package/lib/tools/common.js +30 -5
- package/lib/tools/console.js +3 -1
- package/lib/tools/dialogs.js +2 -0
- package/lib/tools/files.js +2 -0
- package/lib/tools/install.js +7 -5
- package/lib/tools/keyboard.js +2 -0
- package/lib/tools/navigate.js +6 -0
- package/lib/tools/network.js +2 -0
- package/lib/tools/pdf.js +8 -3
- package/lib/tools/screen.js +10 -0
- package/lib/tools/snapshot.js +17 -2
- package/lib/tools/tabs.js +8 -0
- package/lib/tools/testing.js +2 -0
- package/lib/tools.js +56 -0
- package/lib/transport.js +23 -15
- package/package.json +5 -6
package/README.md
CHANGED
|
@@ -76,7 +76,10 @@ The Playwright MCP server supports the following command-line options:
|
|
|
76
76
|
- `--user-data-dir <path>`: Path to the user data directory
|
|
77
77
|
- `--port <port>`: Port to listen on for SSE transport
|
|
78
78
|
- `--host <host>`: Host to bind server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.
|
|
79
|
+
- `--allowed-origins <origins>`: Semicolon-separated list of origins to allow the browser to request. Default is to allow all. Origins matching both `--allowed-origins` and `--blocked-origins` will be blocked.
|
|
80
|
+
- `--blocked-origins <origins>`: Semicolon-separated list of origins to block the browser to request. Origins matching both `--allowed-origins` and `--blocked-origins` will be blocked.
|
|
79
81
|
- `--vision`: Run server that uses screenshots (Aria snapshots are used by default)
|
|
82
|
+
- `--output-dir`: Directory for output files
|
|
80
83
|
- `--config <path>`: Path to the configuration file
|
|
81
84
|
|
|
82
85
|
### User profile
|
|
@@ -152,13 +155,19 @@ The Playwright MCP server can be configured using a JSON configuration file. Her
|
|
|
152
155
|
// Directory for output files
|
|
153
156
|
outputDir?: string;
|
|
154
157
|
|
|
155
|
-
//
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
158
|
+
// Network configuration
|
|
159
|
+
network?: {
|
|
160
|
+
// List of origins to allow the browser to request. Default is to allow all. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
|
|
161
|
+
allowedOrigins?: string[];
|
|
162
|
+
|
|
163
|
+
// List of origins to block the browser to request. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
|
|
164
|
+
blockedOrigins?: string[];
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Do not send image responses to the client.
|
|
169
|
+
*/
|
|
170
|
+
noImageResponses?: boolean;
|
|
162
171
|
}
|
|
163
172
|
```
|
|
164
173
|
|
|
@@ -198,7 +207,7 @@ And then in MCP client config, set the `url` to the SSE endpoint:
|
|
|
198
207
|
"mcpServers": {
|
|
199
208
|
"playwright": {
|
|
200
209
|
"command": "docker",
|
|
201
|
-
"args": ["run", "-i", "--rm", "--init", "
|
|
210
|
+
"args": ["run", "-i", "--rm", "--init", "--pull=always", "mcr.microsoft.com/playwright/mcp"]
|
|
202
211
|
}
|
|
203
212
|
}
|
|
204
213
|
}
|
|
@@ -207,7 +216,7 @@ And then in MCP client config, set the `url` to the SSE endpoint:
|
|
|
207
216
|
You can build the Docker image yourself.
|
|
208
217
|
|
|
209
218
|
```
|
|
210
|
-
docker build -t
|
|
219
|
+
docker build -t mcr.microsoft.com/playwright/mcp .
|
|
211
220
|
```
|
|
212
221
|
|
|
213
222
|
### Programmatic usage
|
|
@@ -215,16 +224,16 @@ docker build -t mcp/playwright .
|
|
|
215
224
|
```js
|
|
216
225
|
import http from 'http';
|
|
217
226
|
|
|
218
|
-
import {
|
|
227
|
+
import { createConnection } from '@playwright/mcp';
|
|
219
228
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
220
229
|
|
|
221
230
|
http.createServer(async (req, res) => {
|
|
222
231
|
// ...
|
|
223
232
|
|
|
224
233
|
// Creates a headless Playwright MCP server with SSE transport
|
|
225
|
-
const
|
|
234
|
+
const connection = await createConnection({ browser: { launchOptions: { headless: true } } });
|
|
226
235
|
const transport = new SSEServerTransport('/messages', res);
|
|
227
|
-
await
|
|
236
|
+
await connection.connect(transport);
|
|
228
237
|
|
|
229
238
|
// ...
|
|
230
239
|
});
|
|
@@ -264,38 +273,47 @@ X Y coordinate space, based on the provided screenshot.
|
|
|
264
273
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
265
274
|
|
|
266
275
|
- **browser_snapshot**
|
|
276
|
+
- Title: Page snapshot
|
|
267
277
|
- Description: Capture accessibility snapshot of the current page, this is better than screenshot
|
|
268
278
|
- Parameters: None
|
|
279
|
+
- Read-only: **true**
|
|
269
280
|
|
|
270
281
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
271
282
|
|
|
272
283
|
- **browser_click**
|
|
284
|
+
- Title: Click
|
|
273
285
|
- Description: Perform click on a web page
|
|
274
286
|
- Parameters:
|
|
275
287
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
276
288
|
- `ref` (string): Exact target element reference from the page snapshot
|
|
289
|
+
- Read-only: **false**
|
|
277
290
|
|
|
278
291
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
279
292
|
|
|
280
293
|
- **browser_drag**
|
|
294
|
+
- Title: Drag mouse
|
|
281
295
|
- Description: Perform drag and drop between two elements
|
|
282
296
|
- Parameters:
|
|
283
297
|
- `startElement` (string): Human-readable source element description used to obtain the permission to interact with the element
|
|
284
298
|
- `startRef` (string): Exact source element reference from the page snapshot
|
|
285
299
|
- `endElement` (string): Human-readable target element description used to obtain the permission to interact with the element
|
|
286
300
|
- `endRef` (string): Exact target element reference from the page snapshot
|
|
301
|
+
- Read-only: **false**
|
|
287
302
|
|
|
288
303
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
289
304
|
|
|
290
305
|
- **browser_hover**
|
|
306
|
+
- Title: Hover mouse
|
|
291
307
|
- Description: Hover over element on page
|
|
292
308
|
- Parameters:
|
|
293
309
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
294
310
|
- `ref` (string): Exact target element reference from the page snapshot
|
|
311
|
+
- Read-only: **true**
|
|
295
312
|
|
|
296
313
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
297
314
|
|
|
298
315
|
- **browser_type**
|
|
316
|
+
- Title: Type text
|
|
299
317
|
- Description: Type text into editable element
|
|
300
318
|
- Parameters:
|
|
301
319
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
@@ -303,54 +321,67 @@ X Y coordinate space, based on the provided screenshot.
|
|
|
303
321
|
- `text` (string): Text to type into the element
|
|
304
322
|
- `submit` (boolean, optional): Whether to submit entered text (press Enter after)
|
|
305
323
|
- `slowly` (boolean, optional): Whether to type one character at a time. Useful for triggering key handlers in the page. By default entire text is filled in at once.
|
|
324
|
+
- Read-only: **false**
|
|
306
325
|
|
|
307
326
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
308
327
|
|
|
309
328
|
- **browser_select_option**
|
|
329
|
+
- Title: Select option
|
|
310
330
|
- Description: Select an option in a dropdown
|
|
311
331
|
- Parameters:
|
|
312
332
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
313
333
|
- `ref` (string): Exact target element reference from the page snapshot
|
|
314
334
|
- `values` (array): Array of values to select in the dropdown. This can be a single value or multiple values.
|
|
335
|
+
- Read-only: **false**
|
|
315
336
|
|
|
316
337
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
317
338
|
|
|
318
339
|
- **browser_take_screenshot**
|
|
340
|
+
- Title: Take a screenshot
|
|
319
341
|
- Description: Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.
|
|
320
342
|
- Parameters:
|
|
321
343
|
- `raw` (boolean, optional): Whether to return without compression (in PNG format). Default is false, which returns a JPEG image.
|
|
344
|
+
- `filename` (string, optional): File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified.
|
|
322
345
|
- `element` (string, optional): Human-readable element description used to obtain permission to screenshot the element. If not provided, the screenshot will be taken of viewport. If element is provided, ref must be provided too.
|
|
323
346
|
- `ref` (string, optional): Exact target element reference from the page snapshot. If not provided, the screenshot will be taken of viewport. If ref is provided, element must be provided too.
|
|
347
|
+
- Read-only: **true**
|
|
324
348
|
|
|
325
349
|
### Vision-based Interactions
|
|
326
350
|
|
|
327
351
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
328
352
|
|
|
329
353
|
- **browser_screen_capture**
|
|
354
|
+
- Title: Take a screenshot
|
|
330
355
|
- Description: Take a screenshot of the current page
|
|
331
356
|
- Parameters: None
|
|
357
|
+
- Read-only: **true**
|
|
332
358
|
|
|
333
359
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
334
360
|
|
|
335
361
|
- **browser_screen_move_mouse**
|
|
362
|
+
- Title: Move mouse
|
|
336
363
|
- Description: Move mouse to a given position
|
|
337
364
|
- Parameters:
|
|
338
365
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
339
366
|
- `x` (number): X coordinate
|
|
340
367
|
- `y` (number): Y coordinate
|
|
368
|
+
- Read-only: **true**
|
|
341
369
|
|
|
342
370
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
343
371
|
|
|
344
372
|
- **browser_screen_click**
|
|
373
|
+
- Title: Click
|
|
345
374
|
- Description: Click left mouse button
|
|
346
375
|
- Parameters:
|
|
347
376
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
348
377
|
- `x` (number): X coordinate
|
|
349
378
|
- `y` (number): Y coordinate
|
|
379
|
+
- Read-only: **false**
|
|
350
380
|
|
|
351
381
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
352
382
|
|
|
353
383
|
- **browser_screen_drag**
|
|
384
|
+
- Title: Drag mouse
|
|
354
385
|
- Description: Drag left mouse button
|
|
355
386
|
- Parameters:
|
|
356
387
|
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
@@ -358,143 +389,191 @@ X Y coordinate space, based on the provided screenshot.
|
|
|
358
389
|
- `startY` (number): Start Y coordinate
|
|
359
390
|
- `endX` (number): End X coordinate
|
|
360
391
|
- `endY` (number): End Y coordinate
|
|
392
|
+
- Read-only: **false**
|
|
361
393
|
|
|
362
394
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
363
395
|
|
|
364
396
|
- **browser_screen_type**
|
|
397
|
+
- Title: Type text
|
|
365
398
|
- Description: Type text
|
|
366
399
|
- Parameters:
|
|
367
400
|
- `text` (string): Text to type into the element
|
|
368
401
|
- `submit` (boolean, optional): Whether to submit entered text (press Enter after)
|
|
402
|
+
- Read-only: **false**
|
|
369
403
|
|
|
370
404
|
### Tab Management
|
|
371
405
|
|
|
372
406
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
373
407
|
|
|
374
408
|
- **browser_tab_list**
|
|
409
|
+
- Title: List tabs
|
|
375
410
|
- Description: List browser tabs
|
|
376
411
|
- Parameters: None
|
|
412
|
+
- Read-only: **true**
|
|
377
413
|
|
|
378
414
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
379
415
|
|
|
380
416
|
- **browser_tab_new**
|
|
417
|
+
- Title: Open a new tab
|
|
381
418
|
- Description: Open a new tab
|
|
382
419
|
- Parameters:
|
|
383
420
|
- `url` (string, optional): The URL to navigate to in the new tab. If not provided, the new tab will be blank.
|
|
421
|
+
- Read-only: **true**
|
|
384
422
|
|
|
385
423
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
386
424
|
|
|
387
425
|
- **browser_tab_select**
|
|
426
|
+
- Title: Select a tab
|
|
388
427
|
- Description: Select a tab by index
|
|
389
428
|
- Parameters:
|
|
390
429
|
- `index` (number): The index of the tab to select
|
|
430
|
+
- Read-only: **true**
|
|
391
431
|
|
|
392
432
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
393
433
|
|
|
394
434
|
- **browser_tab_close**
|
|
435
|
+
- Title: Close a tab
|
|
395
436
|
- Description: Close a tab
|
|
396
437
|
- Parameters:
|
|
397
438
|
- `index` (number, optional): The index of the tab to close. Closes current tab if not provided.
|
|
439
|
+
- Read-only: **false**
|
|
398
440
|
|
|
399
441
|
### Navigation
|
|
400
442
|
|
|
401
443
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
402
444
|
|
|
403
445
|
- **browser_navigate**
|
|
446
|
+
- Title: Navigate to a URL
|
|
404
447
|
- Description: Navigate to a URL
|
|
405
448
|
- Parameters:
|
|
406
449
|
- `url` (string): The URL to navigate to
|
|
450
|
+
- Read-only: **false**
|
|
407
451
|
|
|
408
452
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
409
453
|
|
|
410
454
|
- **browser_navigate_back**
|
|
455
|
+
- Title: Go back
|
|
411
456
|
- Description: Go back to the previous page
|
|
412
457
|
- Parameters: None
|
|
458
|
+
- Read-only: **true**
|
|
413
459
|
|
|
414
460
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
415
461
|
|
|
416
462
|
- **browser_navigate_forward**
|
|
463
|
+
- Title: Go forward
|
|
417
464
|
- Description: Go forward to the next page
|
|
418
465
|
- Parameters: None
|
|
466
|
+
- Read-only: **true**
|
|
419
467
|
|
|
420
468
|
### Keyboard
|
|
421
469
|
|
|
422
470
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
423
471
|
|
|
424
472
|
- **browser_press_key**
|
|
473
|
+
- Title: Press a key
|
|
425
474
|
- Description: Press a key on the keyboard
|
|
426
475
|
- Parameters:
|
|
427
476
|
- `key` (string): Name of the key to press or a character to generate, such as `ArrowLeft` or `a`
|
|
477
|
+
- Read-only: **false**
|
|
428
478
|
|
|
429
479
|
### Console
|
|
430
480
|
|
|
431
481
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
432
482
|
|
|
433
483
|
- **browser_console_messages**
|
|
484
|
+
- Title: Get console messages
|
|
434
485
|
- Description: Returns all console messages
|
|
435
486
|
- Parameters: None
|
|
487
|
+
- Read-only: **true**
|
|
436
488
|
|
|
437
489
|
### Files and Media
|
|
438
490
|
|
|
439
491
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
440
492
|
|
|
441
493
|
- **browser_file_upload**
|
|
494
|
+
- Title: Upload files
|
|
442
495
|
- Description: Upload one or multiple files
|
|
443
496
|
- Parameters:
|
|
444
497
|
- `paths` (array): The absolute paths to the files to upload. Can be a single file or multiple files.
|
|
498
|
+
- Read-only: **false**
|
|
445
499
|
|
|
446
500
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
447
501
|
|
|
448
502
|
- **browser_pdf_save**
|
|
503
|
+
- Title: Save as PDF
|
|
449
504
|
- Description: Save page as PDF
|
|
450
|
-
- Parameters:
|
|
505
|
+
- Parameters:
|
|
506
|
+
- `filename` (string, optional): File name to save the pdf to. Defaults to `page-{timestamp}.pdf` if not specified.
|
|
507
|
+
- Read-only: **true**
|
|
451
508
|
|
|
452
509
|
### Utilities
|
|
453
510
|
|
|
454
511
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
455
512
|
|
|
456
513
|
- **browser_close**
|
|
514
|
+
- Title: Close browser
|
|
457
515
|
- Description: Close the page
|
|
458
516
|
- Parameters: None
|
|
517
|
+
- Read-only: **true**
|
|
459
518
|
|
|
460
519
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
461
520
|
|
|
462
|
-
- **
|
|
463
|
-
-
|
|
521
|
+
- **browser_wait_for**
|
|
522
|
+
- Title: Wait for
|
|
523
|
+
- Description: Wait for text to appear or disappear or a specified time to pass
|
|
464
524
|
- Parameters:
|
|
465
|
-
- `time` (number): The time to wait in seconds
|
|
525
|
+
- `time` (number, optional): The time to wait in seconds
|
|
526
|
+
- `text` (string, optional): The text to wait for
|
|
527
|
+
- `textGone` (string, optional): The text to wait for to disappear
|
|
528
|
+
- Read-only: **true**
|
|
466
529
|
|
|
467
530
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
468
531
|
|
|
469
532
|
- **browser_resize**
|
|
533
|
+
- Title: Resize browser window
|
|
470
534
|
- Description: Resize the browser window
|
|
471
535
|
- Parameters:
|
|
472
536
|
- `width` (number): Width of the browser window
|
|
473
537
|
- `height` (number): Height of the browser window
|
|
538
|
+
- Read-only: **true**
|
|
474
539
|
|
|
475
540
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
476
541
|
|
|
477
542
|
- **browser_install**
|
|
543
|
+
- Title: Install the browser specified in the config
|
|
478
544
|
- Description: Install the browser specified in the config. Call this if you get an error about the browser not being installed.
|
|
479
545
|
- Parameters: None
|
|
546
|
+
- Read-only: **false**
|
|
480
547
|
|
|
481
548
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
482
549
|
|
|
483
550
|
- **browser_handle_dialog**
|
|
551
|
+
- Title: Handle a dialog
|
|
484
552
|
- Description: Handle a dialog
|
|
485
553
|
- Parameters:
|
|
486
554
|
- `accept` (boolean): Whether to accept the dialog.
|
|
487
555
|
- `promptText` (string, optional): The text of the prompt in case of a prompt dialog.
|
|
556
|
+
- Read-only: **false**
|
|
557
|
+
|
|
558
|
+
<!-- NOTE: This has been generated via update-readme.js -->
|
|
559
|
+
|
|
560
|
+
- **browser_network_requests**
|
|
561
|
+
- Title: List network requests
|
|
562
|
+
- Description: Returns all network requests since loading the page
|
|
563
|
+
- Parameters: None
|
|
564
|
+
- Read-only: **true**
|
|
488
565
|
|
|
489
566
|
### Testing
|
|
490
567
|
|
|
491
568
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
492
569
|
|
|
493
570
|
- **browser_generate_playwright_test**
|
|
571
|
+
- Title: Generate a Playwright test
|
|
494
572
|
- Description: Generate a Playwright test for given scenario
|
|
495
573
|
- Parameters:
|
|
496
574
|
- `name` (string): The name of the test
|
|
497
575
|
- `description` (string): The description of the test
|
|
498
576
|
- `steps` (array): The steps of the test
|
|
577
|
+
- Read-only: **true**
|
|
499
578
|
|
|
500
579
|
<!--- End of generated section -->
|
package/config.d.ts
CHANGED
|
@@ -40,7 +40,7 @@ export type Config = {
|
|
|
40
40
|
*
|
|
41
41
|
* This is useful for settings options like `channel`, `headless`, `executablePath`, etc.
|
|
42
42
|
*/
|
|
43
|
-
launchOptions?: playwright.
|
|
43
|
+
launchOptions?: playwright.LaunchOptions;
|
|
44
44
|
|
|
45
45
|
/**
|
|
46
46
|
* Context options for the browser context.
|
|
@@ -94,20 +94,20 @@ export type Config = {
|
|
|
94
94
|
*/
|
|
95
95
|
outputDir?: string;
|
|
96
96
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
97
|
+
network?: {
|
|
98
|
+
/**
|
|
99
|
+
* List of origins to allow the browser to request. Default is to allow all. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
|
|
100
|
+
*/
|
|
101
|
+
allowedOrigins?: string[];
|
|
102
|
+
|
|
101
103
|
/**
|
|
102
|
-
*
|
|
104
|
+
* List of origins to block the browser to request. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
|
|
103
105
|
*/
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
}
|
|
112
|
-
}
|
|
106
|
+
blockedOrigins?: string[];
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Do not send image responses to the client.
|
|
111
|
+
*/
|
|
112
|
+
noImageResponses?: boolean;
|
|
113
113
|
};
|
package/index.d.ts
CHANGED
|
@@ -16,8 +16,14 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
19
|
-
|
|
20
19
|
import type { Config } from './config';
|
|
20
|
+
import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
|
|
21
|
+
|
|
22
|
+
export type Connection = {
|
|
23
|
+
server: Server;
|
|
24
|
+
connect(transport: Transport): Promise<void>;
|
|
25
|
+
close(): Promise<void>;
|
|
26
|
+
};
|
|
21
27
|
|
|
22
|
-
export declare function
|
|
28
|
+
export declare function createConnection(config?: Config): Promise<Connection>;
|
|
23
29
|
export {};
|
package/index.js
CHANGED
package/lib/config.js
CHANGED
|
@@ -22,7 +22,6 @@ import { sanitizeForFilePath } from './tools/utils.js';
|
|
|
22
22
|
const defaultConfig = {
|
|
23
23
|
browser: {
|
|
24
24
|
browserName: 'chromium',
|
|
25
|
-
userDataDir: os.tmpdir(),
|
|
26
25
|
launchOptions: {
|
|
27
26
|
channel: 'chrome',
|
|
28
27
|
headless: os.platform() === 'linux' && !process.env.DISPLAY,
|
|
@@ -31,6 +30,10 @@ const defaultConfig = {
|
|
|
31
30
|
viewport: null,
|
|
32
31
|
},
|
|
33
32
|
},
|
|
33
|
+
network: {
|
|
34
|
+
allowedOrigins: undefined,
|
|
35
|
+
blockedOrigins: undefined,
|
|
36
|
+
},
|
|
34
37
|
};
|
|
35
38
|
export async function resolveConfig(cliOptions) {
|
|
36
39
|
const config = await loadConfig(cliOptions.config);
|
|
@@ -69,12 +72,12 @@ export async function configFromCLIOptions(cliOptions) {
|
|
|
69
72
|
headless: cliOptions.headless,
|
|
70
73
|
};
|
|
71
74
|
if (browserName === 'chromium')
|
|
72
|
-
launchOptions.
|
|
75
|
+
launchOptions.cdpPort = await findFreePort();
|
|
73
76
|
const contextOptions = cliOptions.device ? devices[cliOptions.device] : undefined;
|
|
74
77
|
return {
|
|
75
78
|
browser: {
|
|
76
79
|
browserName,
|
|
77
|
-
userDataDir: cliOptions.userDataDir
|
|
80
|
+
userDataDir: cliOptions.userDataDir,
|
|
78
81
|
launchOptions,
|
|
79
82
|
contextOptions,
|
|
80
83
|
cdpEndpoint: cliOptions.cdpEndpoint,
|
|
@@ -85,6 +88,11 @@ export async function configFromCLIOptions(cliOptions) {
|
|
|
85
88
|
},
|
|
86
89
|
capabilities: cliOptions.caps?.split(',').map((c) => c.trim()),
|
|
87
90
|
vision: !!cliOptions.vision,
|
|
91
|
+
network: {
|
|
92
|
+
allowedOrigins: cliOptions.allowedOrigins,
|
|
93
|
+
blockedOrigins: cliOptions.blockedOrigins,
|
|
94
|
+
},
|
|
95
|
+
outputDir: cliOptions.outputDir,
|
|
88
96
|
};
|
|
89
97
|
}
|
|
90
98
|
async function findFreePort() {
|
|
@@ -107,20 +115,6 @@ async function loadConfig(configFile) {
|
|
|
107
115
|
throw new Error(`Failed to load config file: ${configFile}, ${error}`);
|
|
108
116
|
}
|
|
109
117
|
}
|
|
110
|
-
async function createUserDataDir(options) {
|
|
111
|
-
let cacheDirectory;
|
|
112
|
-
if (process.platform === 'linux')
|
|
113
|
-
cacheDirectory = process.env.XDG_CACHE_HOME || path.join(os.homedir(), '.cache');
|
|
114
|
-
else if (process.platform === 'darwin')
|
|
115
|
-
cacheDirectory = path.join(os.homedir(), 'Library', 'Caches');
|
|
116
|
-
else if (process.platform === 'win32')
|
|
117
|
-
cacheDirectory = process.env.LOCALAPPDATA || path.join(os.homedir(), 'AppData', 'Local');
|
|
118
|
-
else
|
|
119
|
-
throw new Error('Unsupported platform: ' + process.platform);
|
|
120
|
-
const result = path.join(cacheDirectory, 'ms-playwright', `mcp-${options.channel ?? options.browserName}-profile`);
|
|
121
|
-
await fs.promises.mkdir(result, { recursive: true });
|
|
122
|
-
return result;
|
|
123
|
-
}
|
|
124
118
|
export async function outputFile(config, name) {
|
|
125
119
|
const result = config.outputDir ?? os.tmpdir();
|
|
126
120
|
await fs.promises.mkdir(result, { recursive: true });
|
|
@@ -144,11 +138,15 @@ function mergeConfig(base, overrides) {
|
|
|
144
138
|
...pickDefined(overrides.browser?.contextOptions),
|
|
145
139
|
},
|
|
146
140
|
};
|
|
147
|
-
if (browser.browserName !== 'chromium')
|
|
141
|
+
if (browser.browserName !== 'chromium' && browser.launchOptions)
|
|
148
142
|
delete browser.launchOptions.channel;
|
|
149
143
|
return {
|
|
150
144
|
...pickDefined(base),
|
|
151
145
|
...pickDefined(overrides),
|
|
152
146
|
browser,
|
|
147
|
+
network: {
|
|
148
|
+
...pickDefined(base.network),
|
|
149
|
+
...pickDefined(overrides.network),
|
|
150
|
+
},
|
|
153
151
|
};
|
|
154
152
|
}
|
|
@@ -16,11 +16,13 @@
|
|
|
16
16
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
17
17
|
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
18
18
|
import { zodToJsonSchema } from 'zod-to-json-schema';
|
|
19
|
-
import { Context } from './context.js';
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
import { Context, packageJSON } from './context.js';
|
|
20
|
+
import { snapshotTools, screenshotTools } from './tools.js';
|
|
21
|
+
export async function createConnection(config) {
|
|
22
|
+
const allTools = config.vision ? screenshotTools : snapshotTools;
|
|
23
|
+
const tools = allTools.filter(tool => !config.capabilities || tool.capability === 'core' || config.capabilities.includes(tool.capability));
|
|
22
24
|
const context = new Context(tools, config);
|
|
23
|
-
const server = new Server({ name, version }, {
|
|
25
|
+
const server = new Server({ name: 'Playwright', version: packageJSON.version }, {
|
|
24
26
|
capabilities: {
|
|
25
27
|
tools: {},
|
|
26
28
|
}
|
|
@@ -30,7 +32,13 @@ export function createServerWithTools(serverOptions, config) {
|
|
|
30
32
|
tools: tools.map(tool => ({
|
|
31
33
|
name: tool.schema.name,
|
|
32
34
|
description: tool.schema.description,
|
|
33
|
-
inputSchema: zodToJsonSchema(tool.schema.inputSchema)
|
|
35
|
+
inputSchema: zodToJsonSchema(tool.schema.inputSchema),
|
|
36
|
+
annotations: {
|
|
37
|
+
title: tool.schema.title,
|
|
38
|
+
readOnlyHint: tool.schema.type === 'readOnly',
|
|
39
|
+
destructiveHint: tool.schema.type === 'destructive',
|
|
40
|
+
openWorldHint: true,
|
|
41
|
+
},
|
|
34
42
|
})),
|
|
35
43
|
};
|
|
36
44
|
});
|
|
@@ -54,31 +62,26 @@ export function createServerWithTools(serverOptions, config) {
|
|
|
54
62
|
return errorResult(String(error));
|
|
55
63
|
}
|
|
56
64
|
});
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
await oldClose();
|
|
60
|
-
await context.close();
|
|
61
|
-
};
|
|
62
|
-
return server;
|
|
65
|
+
const connection = new Connection(server, context);
|
|
66
|
+
return connection;
|
|
63
67
|
}
|
|
64
|
-
export class
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
constructor(
|
|
68
|
-
this.
|
|
68
|
+
export class Connection {
|
|
69
|
+
server;
|
|
70
|
+
context;
|
|
71
|
+
constructor(server, context) {
|
|
72
|
+
this.server = server;
|
|
73
|
+
this.context = context;
|
|
69
74
|
}
|
|
70
|
-
async
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if (index !== -1)
|
|
78
|
-
this._servers.splice(index, 1);
|
|
79
|
-
await server.close();
|
|
75
|
+
async connect(transport) {
|
|
76
|
+
await this.server.connect(transport);
|
|
77
|
+
await new Promise(resolve => {
|
|
78
|
+
this.server.oninitialized = () => resolve();
|
|
79
|
+
});
|
|
80
|
+
if (this.server.getClientVersion()?.name.includes('cursor'))
|
|
81
|
+
this.context.config.noImageResponses = true;
|
|
80
82
|
}
|
|
81
|
-
async
|
|
82
|
-
await
|
|
83
|
+
async close() {
|
|
84
|
+
await this.server.close();
|
|
85
|
+
await this.context.close();
|
|
83
86
|
}
|
|
84
87
|
}
|