rae-playwright-mcp 0.0.1

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 ADDED
@@ -0,0 +1,1131 @@
1
+ ## Playwright MCP
2
+
3
+ A Model Context Protocol (MCP) server that provides browser automation capabilities using [Playwright](https://playwright.dev). This server enables LLMs to interact with web pages through structured accessibility snapshots, bypassing the need for screenshots or visually-tuned models.
4
+
5
+ ### Key Features
6
+
7
+ - **Fast and lightweight**. Uses Playwright's accessibility tree, not pixel-based input.
8
+ - **LLM-friendly**. No vision models needed, operates purely on structured data.
9
+ - **Deterministic tool application**. Avoids ambiguity common with screenshot-based approaches.
10
+
11
+ ### Requirements
12
+ - Node.js 18 or newer
13
+ - VS Code, Cursor, Windsurf, Claude Desktop, Goose or any other MCP client
14
+
15
+ <!--
16
+ // Generate using:
17
+ node utils/generate-links.js
18
+ -->
19
+
20
+ ### Getting started
21
+
22
+ First, install the Playwright MCP server with your client.
23
+
24
+ **Standard config** works in most of the tools:
25
+
26
+ ```js
27
+ {
28
+ "mcpServers": {
29
+ "playwright": {
30
+ "command": "npx",
31
+ "args": [
32
+ "@playwright/mcp@latest"
33
+ ]
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ [<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in VS Code">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) [<img alt="Install in VS Code Insiders" src="https://img.shields.io/badge/VS_Code_Insiders-VS_Code_Insiders?style=flat-square&label=Install%20Server&color=24bfa5">](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D)
40
+
41
+ <details>
42
+ <summary>Amp</summary>
43
+
44
+ Add via the Amp VS Code extension settings screen or by updating your settings.json file:
45
+
46
+ ```json
47
+ "amp.mcpServers": {
48
+ "playwright": {
49
+ "command": "npx",
50
+ "args": [
51
+ "@playwright/mcp@latest"
52
+ ]
53
+ }
54
+ }
55
+ ```
56
+
57
+ **Amp CLI Setup:**
58
+
59
+ Add via the `amp mcp add`command below
60
+
61
+ ```bash
62
+ amp mcp add playwright -- npx @playwright/mcp@latest
63
+ ```
64
+
65
+ </details>
66
+
67
+ <details>
68
+ <summary>Claude Code</summary>
69
+
70
+ Use the Claude Code CLI to add the Playwright MCP server:
71
+
72
+ ```bash
73
+ claude mcp add playwright npx @playwright/mcp@latest
74
+ ```
75
+ </details>
76
+
77
+ <details>
78
+ <summary>Claude Desktop</summary>
79
+
80
+ Follow the MCP install [guide](https://modelcontextprotocol.io/quickstart/user), use the standard config above.
81
+
82
+ </details>
83
+
84
+ <details>
85
+ <summary>Codex</summary>
86
+
87
+ Use the Codex CLI to add the Playwright MCP server:
88
+
89
+ ```bash
90
+ codex mcp add playwright npx "@playwright/mcp@latest"
91
+ ```
92
+
93
+ Alternatively, create or edit the configuration file `~/.codex/config.toml` and add:
94
+
95
+ ```toml
96
+ [mcp_servers.playwright]
97
+ command = "npx"
98
+ args = ["@playwright/mcp@latest"]
99
+ ```
100
+
101
+ For more information, see the [Codex MCP documentation](https://github.com/openai/codex/blob/main/codex-rs/config.md#mcp_servers).
102
+
103
+ </details>
104
+
105
+ <details>
106
+ <summary>Copilot</summary>
107
+
108
+ Use the Copilot CLI to interactively add the Playwright MCP server:
109
+
110
+ ```bash
111
+ /mcp add
112
+ ```
113
+
114
+ Alternatively, create or edit the configuration file `~/.copilot/mcp-config.json` and add:
115
+
116
+ ```json
117
+ {
118
+ "mcpServers": {
119
+ "playwright": {
120
+ "type": "local",
121
+ "command": "npx",
122
+ "tools": [
123
+ "*"
124
+ ],
125
+ "args": [
126
+ "@playwright/mcp@latest"
127
+ ]
128
+ }
129
+ }
130
+ }
131
+ ```
132
+
133
+ For more information, see the [Copilot CLI documentation](https://docs.github.com/en/copilot/concepts/agents/about-copilot-cli).
134
+
135
+ </details>
136
+
137
+ <details>
138
+ <summary>Cursor</summary>
139
+
140
+ #### Click the button to install:
141
+
142
+ [<img src="https://cursor.com/deeplink/mcp-install-dark.svg" alt="Install in Cursor">](https://cursor.com/en/install-mcp?name=Playwright&config=eyJjb21tYW5kIjoibnB4IEBwbGF5d3JpZ2h0L21jcEBsYXRlc3QifQ%3D%3D)
143
+
144
+ #### Or install manually:
145
+
146
+ Go to `Cursor Settings` -> `MCP` -> `Add new MCP Server`. Name to your liking, use `command` type with the command `npx @playwright/mcp@latest`. You can also verify config or add command like arguments via clicking `Edit`.
147
+
148
+ </details>
149
+
150
+ <details>
151
+ <summary>Factory</summary>
152
+
153
+ Use the Factory CLI to add the Playwright MCP server:
154
+
155
+ ```bash
156
+ droid mcp add playwright "npx @playwright/mcp@latest"
157
+ ```
158
+
159
+ Alternatively, type `/mcp` within Factory droid to open an interactive UI for managing MCP servers.
160
+
161
+ For more information, see the [Factory MCP documentation](https://docs.factory.ai/cli/configuration/mcp).
162
+
163
+ </details>
164
+
165
+ <details>
166
+ <summary>Gemini CLI</summary>
167
+
168
+ Follow the MCP install [guide](https://github.com/google-gemini/gemini-cli/blob/main/docs/tools/mcp-server.md#configure-the-mcp-server-in-settingsjson), use the standard config above.
169
+
170
+ </details>
171
+
172
+ <details>
173
+ <summary>Goose</summary>
174
+
175
+ #### Click the button to install:
176
+
177
+ [![Install in Goose](https://block.github.io/goose/img/extension-install-dark.svg)](https://block.github.io/goose/extension?cmd=npx&arg=%40playwright%2Fmcp%40latest&id=playwright&name=Playwright&description=Interact%20with%20web%20pages%20through%20structured%20accessibility%20snapshots%20using%20Playwright)
178
+
179
+ #### Or install manually:
180
+
181
+ Go to `Advanced settings` -> `Extensions` -> `Add custom extension`. Name to your liking, use type `STDIO`, and set the `command` to `npx @playwright/mcp`. Click "Add Extension".
182
+ </details>
183
+
184
+ <details>
185
+ <summary>Kiro</summary>
186
+
187
+ Follow the MCP Servers [documentation](https://kiro.dev/docs/mcp/). For example in `.kiro/settings/mcp.json`:
188
+
189
+ ```json
190
+ {
191
+ "mcpServers": {
192
+ "playwright": {
193
+ "command": "npx",
194
+ "args": [
195
+ "@playwright/mcp@latest"
196
+ ]
197
+ }
198
+ }
199
+ }
200
+ ```
201
+ </details>
202
+
203
+ <details>
204
+ <summary>LM Studio</summary>
205
+
206
+ #### Click the button to install:
207
+
208
+ [![Add MCP Server playwright to LM Studio](https://files.lmstudio.ai/deeplink/mcp-install-light.svg)](https://lmstudio.ai/install-mcp?name=playwright&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyJAcGxheXdyaWdodC9tY3BAbGF0ZXN0Il19)
209
+
210
+ #### Or install manually:
211
+
212
+ Go to `Program` in the right sidebar -> `Install` -> `Edit mcp.json`. Use the standard config above.
213
+ </details>
214
+
215
+ <details>
216
+ <summary>opencode</summary>
217
+
218
+ Follow the MCP Servers [documentation](https://opencode.ai/docs/mcp-servers/). For example in `~/.config/opencode/opencode.json`:
219
+
220
+ ```json
221
+ {
222
+ "$schema": "https://opencode.ai/config.json",
223
+ "mcp": {
224
+ "playwright": {
225
+ "type": "local",
226
+ "command": [
227
+ "npx",
228
+ "@playwright/mcp@latest"
229
+ ],
230
+ "enabled": true
231
+ }
232
+ }
233
+ }
234
+
235
+ ```
236
+ </details>
237
+
238
+ <details>
239
+ <summary>Qodo Gen</summary>
240
+
241
+ Open [Qodo Gen](https://docs.qodo.ai/qodo-documentation/qodo-gen) chat panel in VSCode or IntelliJ → Connect more tools → + Add new MCP → Paste the standard config above.
242
+
243
+ Click <code>Save</code>.
244
+ </details>
245
+
246
+ <details>
247
+ <summary>VS Code</summary>
248
+
249
+ #### Click the button to install:
250
+
251
+ [<img src="https://img.shields.io/badge/VS_Code-VS_Code?style=flat-square&label=Install%20Server&color=0098FF" alt="Install in VS Code">](https://insiders.vscode.dev/redirect?url=vscode%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D) [<img alt="Install in VS Code Insiders" src="https://img.shields.io/badge/VS_Code_Insiders-VS_Code_Insiders?style=flat-square&label=Install%20Server&color=24bfa5">](https://insiders.vscode.dev/redirect?url=vscode-insiders%3Amcp%2Finstall%3F%257B%2522name%2522%253A%2522playwright%2522%252C%2522command%2522%253A%2522npx%2522%252C%2522args%2522%253A%255B%2522%2540playwright%252Fmcp%2540latest%2522%255D%257D)
252
+
253
+ #### Or install manually:
254
+
255
+ Follow the MCP install [guide](https://code.visualstudio.com/docs/copilot/chat/mcp-servers#_add-an-mcp-server), use the standard config above. You can also install the Playwright MCP server using the VS Code CLI:
256
+
257
+ ```bash
258
+ # For VS Code
259
+ code --add-mcp '{"name":"playwright","command":"npx","args":["@playwright/mcp@latest"]}'
260
+ ```
261
+
262
+ After installation, the Playwright MCP server will be available for use with your GitHub Copilot agent in VS Code.
263
+ </details>
264
+
265
+ <details>
266
+ <summary>Warp</summary>
267
+
268
+ Go to `Settings` -> `AI` -> `Manage MCP Servers` -> `+ Add` to [add an MCP Server](https://docs.warp.dev/knowledge-and-collaboration/mcp#adding-an-mcp-server). Use the standard config above.
269
+
270
+ Alternatively, use the slash command `/add-mcp` in the Warp prompt and paste the standard config from above:
271
+ ```js
272
+ {
273
+ "mcpServers": {
274
+ "playwright": {
275
+ "command": "npx",
276
+ "args": [
277
+ "@playwright/mcp@latest"
278
+ ]
279
+ }
280
+ }
281
+ }
282
+ ```
283
+
284
+ </details>
285
+
286
+ <details>
287
+ <summary>Windsurf</summary>
288
+
289
+ Follow Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/mcp). Use the standard config above.
290
+
291
+ </details>
292
+
293
+ ### Configuration
294
+
295
+ Playwright MCP server supports following arguments. They can be provided in the JSON configuration above, as a part of the `"args"` list:
296
+
297
+ <!--- Options generated by update-readme.js -->
298
+
299
+ ```
300
+ > npx @playwright/mcp@latest --help
301
+ --allowed-hosts <hosts...> comma-separated list of hosts this
302
+ server is allowed to serve from.
303
+ Defaults to the host the server is bound
304
+ to. Pass '*' to disable the host check.
305
+ --allowed-origins <origins> semicolon-separated list of TRUSTED
306
+ origins to allow the browser to request.
307
+ Default is to allow all.
308
+ Important: *does not* serve as a
309
+ security boundary and *does not* affect
310
+ redirects.
311
+ --blocked-origins <origins> semicolon-separated list of origins to
312
+ block the browser from requesting.
313
+ Blocklist is evaluated before allowlist.
314
+ If used without the allowlist, requests
315
+ not matching the blocklist are still
316
+ allowed.
317
+ Important: *does not* serve as a
318
+ security boundary and *does not* affect
319
+ redirects.
320
+ --block-service-workers block service workers
321
+ --browser <browser> browser or chrome channel to use,
322
+ possible values: chrome, firefox,
323
+ webkit, msedge.
324
+ --caps <caps> comma-separated list of additional
325
+ capabilities to enable, possible values:
326
+ vision, pdf.
327
+ --cdp-endpoint <endpoint> CDP endpoint to connect to.
328
+ --cdp-header <headers...> CDP headers to send with the connect
329
+ request, multiple can be specified.
330
+ --config <path> path to the configuration file.
331
+ --console-level <level> level of console messages to return:
332
+ "error", "warning", "info", "debug".
333
+ Each level includes the messages of more
334
+ severe levels.
335
+ --device <device> device to emulate, for example: "iPhone
336
+ 15"
337
+ --executable-path <path> path to the browser executable.
338
+ --extension Connect to a running browser instance
339
+ (Edge/Chrome only). Requires the
340
+ "Playwright MCP Bridge" browser
341
+ extension to be installed.
342
+ --grant-permissions <permissions...> List of permissions to grant to the
343
+ browser context, for example
344
+ "geolocation", "clipboard-read",
345
+ "clipboard-write".
346
+ --headless run browser in headless mode, headed by
347
+ default
348
+ --host <host> host to bind server to. Default is
349
+ localhost. Use 0.0.0.0 to bind to all
350
+ interfaces.
351
+ --ignore-https-errors ignore https errors
352
+ --init-page <path...> path to TypeScript file to evaluate on
353
+ Playwright page object
354
+ --init-script <path...> path to JavaScript file to add as an
355
+ initialization script. The script will
356
+ be evaluated in every page before any of
357
+ the page's scripts. Can be specified
358
+ multiple times.
359
+ --isolated keep the browser profile in memory, do
360
+ not save it to disk.
361
+ --image-responses <mode> whether to send image responses to the
362
+ client. Can be "allow" or "omit",
363
+ Defaults to "allow".
364
+ --no-sandbox disable the sandbox for all process
365
+ types that are normally sandboxed.
366
+ --output-dir <path> path to the directory for output files.
367
+ --port <port> port to listen on for SSE transport.
368
+ --proxy-bypass <bypass> comma-separated domains to bypass proxy,
369
+ for example
370
+ ".com,chromium.org,.domain.com"
371
+ --proxy-server <proxy> specify proxy server, for example
372
+ "http://myproxy:3128" or
373
+ "socks5://myproxy:8080"
374
+ --save-session Whether to save the Playwright MCP
375
+ session into the output directory.
376
+ --save-trace Whether to save the Playwright Trace of
377
+ the session into the output directory.
378
+ --save-video <size> Whether to save the video of the session
379
+ into the output directory. For example
380
+ "--save-video=800x600"
381
+ --secrets <path> path to a file containing secrets in the
382
+ dotenv format
383
+ --shared-browser-context reuse the same browser context between
384
+ all connected HTTP clients.
385
+ --snapshot-mode <mode> when taking snapshots for responses,
386
+ specifies the mode to use. Can be
387
+ "incremental", "full", or "none".
388
+ Default is incremental.
389
+ --storage-state <path> path to the storage state file for
390
+ isolated sessions.
391
+ --test-id-attribute <attribute> specify the attribute to use for test
392
+ ids, defaults to "data-testid"
393
+ --timeout-action <timeout> specify action timeout in milliseconds,
394
+ defaults to 5000ms
395
+ --timeout-navigation <timeout> specify navigation timeout in
396
+ milliseconds, defaults to 60000ms
397
+ --user-agent <ua string> specify user agent string
398
+ --user-data-dir <path> path to the user data directory. If not
399
+ specified, a temporary directory will be
400
+ created.
401
+ --viewport-size <size> specify browser viewport size in pixels,
402
+ for example "1280x720"
403
+ ```
404
+
405
+ <!--- End of options generated section -->
406
+
407
+ ### User profile
408
+
409
+ You can run Playwright MCP with persistent profile like a regular browser (default), in isolated contexts for testing sessions, or connect to your existing browser using the browser extension.
410
+
411
+ **Persistent profile**
412
+
413
+ All the logged in information will be stored in the persistent profile, you can delete it between sessions if you'd like to clear the offline state.
414
+ Persistent profile is located at the following locations and you can override it with the `--user-data-dir` argument.
415
+
416
+ ```bash
417
+ # Windows
418
+ %USERPROFILE%\AppData\Local\ms-playwright\mcp-{channel}-profile
419
+
420
+ # macOS
421
+ - ~/Library/Caches/ms-playwright/mcp-{channel}-profile
422
+
423
+ # Linux
424
+ - ~/.cache/ms-playwright/mcp-{channel}-profile
425
+ ```
426
+
427
+ **Isolated**
428
+
429
+ In the isolated mode, each session is started in the isolated profile. Every time you ask MCP to close the browser,
430
+ the session is closed and all the storage state for this session is lost. You can provide initial storage state
431
+ to the browser via the config's `contextOptions` or via the `--storage-state` argument. Learn more about the storage
432
+ state [here](https://playwright.dev/docs/auth).
433
+
434
+ ```js
435
+ {
436
+ "mcpServers": {
437
+ "playwright": {
438
+ "command": "npx",
439
+ "args": [
440
+ "@playwright/mcp@latest",
441
+ "--isolated",
442
+ "--storage-state={path/to/storage.json}"
443
+ ]
444
+ }
445
+ }
446
+ }
447
+ ```
448
+
449
+ **Browser Extension**
450
+
451
+ The Playwright MCP Chrome Extension allows you to connect to existing browser tabs and leverage your logged-in sessions and browser state. See [extension/README.md](extension/README.md) for installation and setup instructions.
452
+
453
+ ### Initial state
454
+
455
+ There are multiple ways to provide the initial state to the browser context or a page.
456
+
457
+ For the storage state, you can either:
458
+ - Start with a user data directory using the `--user-data-dir` argument. This will persist all browser data between the sessions.
459
+ - Start with a storage state file using the `--storage-state` argument. This will load cookies and local storage from the file into an isolated browser context.
460
+
461
+ For the page state, you can use:
462
+
463
+ - `--init-page` to point to a TypeScript file that will be evaluated on the Playwright page object. This allows you to run arbitrary code to set up the page.
464
+
465
+ ```ts
466
+ // init-page.ts
467
+ export default async ({ page }) => {
468
+ await page.context().grantPermissions(['geolocation']);
469
+ await page.context().setGeolocation({ latitude: 37.7749, longitude: -122.4194 });
470
+ await page.setViewportSize({ width: 1280, height: 720 });
471
+ };
472
+ ```
473
+
474
+ - `--init-script` to point to a JavaScript file that will be added as an initialization script. The script will be evaluated in every page before any of the page's scripts.
475
+ This is useful for overriding browser APIs or setting up the environment.
476
+
477
+ ```js
478
+ // init-script.js
479
+ window.isPlaywrightMCP = true;
480
+ ```
481
+
482
+ ### Configuration file
483
+
484
+ The Playwright MCP server can be configured using a JSON configuration file. You can specify the configuration file
485
+ using the `--config` command line option:
486
+
487
+ ```bash
488
+ npx @playwright/mcp@latest --config path/to/config.json
489
+ ```
490
+
491
+ <details>
492
+ <summary>Configuration file schema</summary>
493
+
494
+ <!--- Config generated by update-readme.js -->
495
+
496
+ ```typescript
497
+ {
498
+ /**
499
+ * The browser to use.
500
+ */
501
+ browser?: {
502
+ /**
503
+ * The type of browser to use.
504
+ */
505
+ browserName?: 'chromium' | 'firefox' | 'webkit';
506
+
507
+ /**
508
+ * Keep the browser profile in memory, do not save it to disk.
509
+ */
510
+ isolated?: boolean;
511
+
512
+ /**
513
+ * Path to a user data directory for browser profile persistence.
514
+ * Temporary directory is created by default.
515
+ */
516
+ userDataDir?: string;
517
+
518
+ /**
519
+ * Launch options passed to
520
+ * @see https://playwright.dev/docs/api/class-browsertype#browser-type-launch-persistent-context
521
+ *
522
+ * This is useful for settings options like `channel`, `headless`, `executablePath`, etc.
523
+ */
524
+ launchOptions?: playwright.LaunchOptions;
525
+
526
+ /**
527
+ * Context options for the browser context.
528
+ *
529
+ * This is useful for settings options like `viewport`.
530
+ */
531
+ contextOptions?: playwright.BrowserContextOptions;
532
+
533
+ /**
534
+ * Chrome DevTools Protocol endpoint to connect to an existing browser instance in case of Chromium family browsers.
535
+ */
536
+ cdpEndpoint?: string;
537
+
538
+ /**
539
+ * CDP headers to send with the connect request.
540
+ */
541
+ cdpHeaders?: Record<string, string>;
542
+
543
+ /**
544
+ * Remote endpoint to connect to an existing Playwright server.
545
+ */
546
+ remoteEndpoint?: string;
547
+
548
+ /**
549
+ * Paths to TypeScript files to add as initialization scripts for Playwright page.
550
+ */
551
+ initPage?: string[];
552
+
553
+ /**
554
+ * Paths to JavaScript files to add as initialization scripts.
555
+ * The scripts will be evaluated in every page before any of the page's scripts.
556
+ */
557
+ initScript?: string[];
558
+ },
559
+
560
+ server?: {
561
+ /**
562
+ * The port to listen on for SSE or MCP transport.
563
+ */
564
+ port?: number;
565
+
566
+ /**
567
+ * The host to bind the server to. Default is localhost. Use 0.0.0.0 to bind to all interfaces.
568
+ */
569
+ host?: string;
570
+
571
+ /**
572
+ * The hosts this server is allowed to serve from. Defaults to the host server is bound to.
573
+ * This is not for CORS, but rather for the DNS rebinding protection.
574
+ */
575
+ allowedHosts?: string[];
576
+ },
577
+
578
+ /**
579
+ * List of enabled tool capabilities. Possible values:
580
+ * - 'core': Core browser automation features.
581
+ * - 'pdf': PDF generation and manipulation.
582
+ * - 'vision': Coordinate-based interactions.
583
+ */
584
+ capabilities?: ToolCapability[];
585
+
586
+ /**
587
+ * Whether to save the Playwright session into the output directory.
588
+ */
589
+ saveSession?: boolean;
590
+
591
+ /**
592
+ * Whether to save the Playwright trace of the session into the output directory.
593
+ */
594
+ saveTrace?: boolean;
595
+
596
+ /**
597
+ * If specified, saves the Playwright video of the session into the output directory.
598
+ */
599
+ saveVideo?: {
600
+ width: number;
601
+ height: number;
602
+ };
603
+
604
+ /**
605
+ * Reuse the same browser context between all connected HTTP clients.
606
+ */
607
+ sharedBrowserContext?: boolean;
608
+
609
+ /**
610
+ * Secrets are used to prevent LLM from getting sensitive data while
611
+ * automating scenarios such as authentication.
612
+ * Prefer the browser.contextOptions.storageState over secrets file as a more secure alternative.
613
+ */
614
+ secrets?: Record<string, string>;
615
+
616
+ /**
617
+ * The directory to save output files.
618
+ */
619
+ outputDir?: string;
620
+
621
+ console?: {
622
+ /**
623
+ * The level of console messages to return. Each level includes the messages of more severe levels. Defaults to "info".
624
+ */
625
+ level?: 'error' | 'warning' | 'info' | 'debug';
626
+ },
627
+
628
+ network?: {
629
+ /**
630
+ * List of origins to allow the browser to request. Default is to allow all. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
631
+ */
632
+ allowedOrigins?: string[];
633
+
634
+ /**
635
+ * List of origins to block the browser to request. Origins matching both `allowedOrigins` and `blockedOrigins` will be blocked.
636
+ */
637
+ blockedOrigins?: string[];
638
+ };
639
+
640
+ /**
641
+ * Specify the attribute to use for test ids, defaults to "data-testid".
642
+ */
643
+ testIdAttribute?: string;
644
+
645
+ timeouts?: {
646
+ /*
647
+ * Configures default action timeout: https://playwright.dev/docs/api/class-page#page-set-default-timeout. Defaults to 5000ms.
648
+ */
649
+ action?: number;
650
+
651
+ /*
652
+ * Configures default navigation timeout: https://playwright.dev/docs/api/class-page#page-set-default-navigation-timeout. Defaults to 60000ms.
653
+ */
654
+ navigation?: number;
655
+ };
656
+
657
+ /**
658
+ * Whether to send image responses to the client. Can be "allow", "omit", or "auto". Defaults to "auto", which sends images if the client can display them.
659
+ */
660
+ imageResponses?: 'allow' | 'omit';
661
+
662
+ snapshot?: {
663
+ /**
664
+ * When taking snapshots for responses, specifies the mode to use.
665
+ */
666
+ mode?: 'incremental' | 'full' | 'none';
667
+ };
668
+
669
+ /**
670
+ * External UUID to use for HAR directory. If not provided, a UUID will be generated.
671
+ */
672
+ runId?: string;
673
+ }
674
+ ```
675
+
676
+ <!--- End of config generated section -->
677
+
678
+ </details>
679
+
680
+ ### Standalone MCP server
681
+
682
+ When running headed browser on system w/o display or from worker processes of the IDEs,
683
+ run the MCP server from environment with the DISPLAY and pass the `--port` flag to enable HTTP transport.
684
+
685
+ ```bash
686
+ npx @playwright/mcp@latest --port 8931
687
+ ```
688
+
689
+ And then in MCP client config, set the `url` to the HTTP endpoint:
690
+
691
+ ```js
692
+ {
693
+ "mcpServers": {
694
+ "playwright": {
695
+ "url": "http://localhost:8931/mcp"
696
+ }
697
+ }
698
+ }
699
+ ```
700
+
701
+ <details>
702
+ <summary><b>Docker</b></summary>
703
+
704
+ **NOTE:** The Docker implementation only supports headless chromium at the moment.
705
+
706
+ ```js
707
+ {
708
+ "mcpServers": {
709
+ "playwright": {
710
+ "command": "docker",
711
+ "args": ["run", "-i", "--rm", "--init", "--pull=always", "mcr.microsoft.com/playwright/mcp"]
712
+ }
713
+ }
714
+ }
715
+ ```
716
+
717
+ Or If you prefer to run the container as a long-lived service instead of letting the MCP client spawn it, use:
718
+
719
+ ```
720
+ docker run -d -i --rm --init --pull=always \
721
+ --entrypoint node \
722
+ --name playwright \
723
+ -p 8931:8931 \
724
+ mcr.microsoft.com/playwright/mcp \
725
+ cli.js --headless --browser chromium --no-sandbox --port 8931
726
+ ```
727
+
728
+ The server will listen on host port **8931** and can be reached by any MCP client.
729
+
730
+ You can build the Docker image yourself.
731
+
732
+ ```
733
+ docker build -t mcr.microsoft.com/playwright/mcp .
734
+ ```
735
+ </details>
736
+
737
+ <details>
738
+ <summary><b>Programmatic usage</b></summary>
739
+
740
+ ```js
741
+ import http from 'http';
742
+
743
+ import { createConnection } from '@playwright/mcp';
744
+ import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
745
+
746
+ http.createServer(async (req, res) => {
747
+ // ...
748
+
749
+ // Creates a headless Playwright MCP server with SSE transport
750
+ const connection = await createConnection({ browser: { launchOptions: { headless: true } } });
751
+ const transport = new SSEServerTransport('/messages', res);
752
+ await connection.connect(transport);
753
+
754
+ // ...
755
+ });
756
+ ```
757
+ </details>
758
+
759
+ ### Tools
760
+
761
+ <!--- Tools generated by update-readme.js -->
762
+
763
+ <details>
764
+ <summary><b>Core automation</b></summary>
765
+
766
+ <!-- NOTE: This has been generated via update-readme.js -->
767
+
768
+ - **browser_click**
769
+ - Title: Click
770
+ - Description: Perform click on a web page
771
+ - Parameters:
772
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
773
+ - `ref` (string): Exact target element reference from the page snapshot
774
+ - `doubleClick` (boolean, optional): Whether to perform a double click instead of a single click
775
+ - `button` (string, optional): Button to click, defaults to left
776
+ - `modifiers` (array, optional): Modifier keys to press
777
+ - Read-only: **false**
778
+
779
+ <!-- NOTE: This has been generated via update-readme.js -->
780
+
781
+ - **browser_close**
782
+ - Title: Close browser
783
+ - Description: Close the page
784
+ - Parameters: None
785
+ - Read-only: **false**
786
+
787
+ <!-- NOTE: This has been generated via update-readme.js -->
788
+
789
+ - **browser_console_messages**
790
+ - Title: Get console messages
791
+ - Description: Returns all console messages
792
+ - Parameters:
793
+ - `level` (string, optional): Level of the console messages to return. Each level includes the messages of more severe levels. Defaults to "info".
794
+ - Read-only: **true**
795
+
796
+ <!-- NOTE: This has been generated via update-readme.js -->
797
+
798
+ - **browser_drag**
799
+ - Title: Drag mouse
800
+ - Description: Perform drag and drop between two elements
801
+ - Parameters:
802
+ - `startElement` (string): Human-readable source element description used to obtain the permission to interact with the element
803
+ - `startRef` (string): Exact source element reference from the page snapshot
804
+ - `endElement` (string): Human-readable target element description used to obtain the permission to interact with the element
805
+ - `endRef` (string): Exact target element reference from the page snapshot
806
+ - Read-only: **false**
807
+
808
+ <!-- NOTE: This has been generated via update-readme.js -->
809
+
810
+ - **browser_evaluate**
811
+ - Title: Evaluate JavaScript
812
+ - Description: Evaluate JavaScript expression on page or element
813
+ - Parameters:
814
+ - `function` (string): () => { /* code */ } or (element) => { /* code */ } when element is provided
815
+ - `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
816
+ - `ref` (string, optional): Exact target element reference from the page snapshot
817
+ - Read-only: **false**
818
+
819
+ <!-- NOTE: This has been generated via update-readme.js -->
820
+
821
+ - **browser_file_upload**
822
+ - Title: Upload files
823
+ - Description: Upload one or multiple files
824
+ - Parameters:
825
+ - `paths` (array, optional): The absolute paths to the files to upload. Can be single file or multiple files. If omitted, file chooser is cancelled.
826
+ - Read-only: **false**
827
+
828
+ <!-- NOTE: This has been generated via update-readme.js -->
829
+
830
+ - **browser_fill_form**
831
+ - Title: Fill form
832
+ - Description: Fill multiple form fields
833
+ - Parameters:
834
+ - `fields` (array): Fields to fill in
835
+ - Read-only: **false**
836
+
837
+ <!-- NOTE: This has been generated via update-readme.js -->
838
+
839
+ - **browser_handle_dialog**
840
+ - Title: Handle a dialog
841
+ - Description: Handle a dialog
842
+ - Parameters:
843
+ - `accept` (boolean): Whether to accept the dialog.
844
+ - `promptText` (string, optional): The text of the prompt in case of a prompt dialog.
845
+ - Read-only: **false**
846
+
847
+ <!-- NOTE: This has been generated via update-readme.js -->
848
+
849
+ - **browser_hover**
850
+ - Title: Hover mouse
851
+ - Description: Hover over element on page
852
+ - Parameters:
853
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
854
+ - `ref` (string): Exact target element reference from the page snapshot
855
+ - Read-only: **false**
856
+
857
+ <!-- NOTE: This has been generated via update-readme.js -->
858
+
859
+ - **browser_navigate**
860
+ - Title: Navigate to a URL
861
+ - Description: Navigate to a URL
862
+ - Parameters:
863
+ - `url` (string): The URL to navigate to
864
+ - Read-only: **false**
865
+
866
+ <!-- NOTE: This has been generated via update-readme.js -->
867
+
868
+ - **browser_navigate_back**
869
+ - Title: Go back
870
+ - Description: Go back to the previous page
871
+ - Parameters: None
872
+ - Read-only: **false**
873
+
874
+ <!-- NOTE: This has been generated via update-readme.js -->
875
+
876
+ - **browser_network_requests**
877
+ - Title: List network requests
878
+ - Description: Returns all network requests since loading the page
879
+ - Parameters:
880
+ - `includeStatic` (boolean, optional): Whether to include successful static resources like images, fonts, scripts, etc. Defaults to false.
881
+ - Read-only: **true**
882
+
883
+ <!-- NOTE: This has been generated via update-readme.js -->
884
+
885
+ - **browser_press_key**
886
+ - Title: Press a key
887
+ - Description: Press a key on the keyboard
888
+ - Parameters:
889
+ - `key` (string): Name of the key to press or a character to generate, such as `ArrowLeft` or `a`
890
+ - Read-only: **false**
891
+
892
+ <!-- NOTE: This has been generated via update-readme.js -->
893
+
894
+ - **browser_resize**
895
+ - Title: Resize browser window
896
+ - Description: Resize the browser window
897
+ - Parameters:
898
+ - `width` (number): Width of the browser window
899
+ - `height` (number): Height of the browser window
900
+ - Read-only: **false**
901
+
902
+ <!-- NOTE: This has been generated via update-readme.js -->
903
+
904
+ - **browser_run_code**
905
+ - Title: Run Playwright code
906
+ - Description: Run Playwright code snippet
907
+ - Parameters:
908
+ - `code` (string): A JavaScript function containing Playwright code to execute. It will be invoked with a single argument, page, which you can use for any page interaction. For example: `async (page) => { await page.getByRole('button', { name: 'Submit' }).click(); return await page.title(); }`
909
+ - Read-only: **false**
910
+
911
+ <!-- NOTE: This has been generated via update-readme.js -->
912
+
913
+ - **browser_select_option**
914
+ - Title: Select option
915
+ - Description: Select an option in a dropdown
916
+ - Parameters:
917
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
918
+ - `ref` (string): Exact target element reference from the page snapshot
919
+ - `values` (array): Array of values to select in the dropdown. This can be a single value or multiple values.
920
+ - Read-only: **false**
921
+
922
+ <!-- NOTE: This has been generated via update-readme.js -->
923
+
924
+ - **browser_snapshot**
925
+ - Title: Page snapshot
926
+ - Description: Capture accessibility snapshot of the current page, this is better than screenshot
927
+ - Parameters:
928
+ - `filename` (string, optional): Save snapshot to markdown file instead of returning it in the response.
929
+ - Read-only: **true**
930
+
931
+ <!-- NOTE: This has been generated via update-readme.js -->
932
+
933
+ - **browser_take_screenshot**
934
+ - Title: Take a screenshot
935
+ - Description: Take a screenshot of the current page. You can't perform actions based on the screenshot, use browser_snapshot for actions.
936
+ - Parameters:
937
+ - `type` (string, optional): Image format for the screenshot. Default is png.
938
+ - `filename` (string, optional): File name to save the screenshot to. Defaults to `page-{timestamp}.{png|jpeg}` if not specified. Prefer relative file names to stay within the output directory.
939
+ - `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.
940
+ - `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.
941
+ - `fullPage` (boolean, optional): When true, takes a screenshot of the full scrollable page, instead of the currently visible viewport. Cannot be used with element screenshots.
942
+ - Read-only: **true**
943
+
944
+ <!-- NOTE: This has been generated via update-readme.js -->
945
+
946
+ - **browser_type**
947
+ - Title: Type text
948
+ - Description: Type text into editable element
949
+ - Parameters:
950
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
951
+ - `ref` (string): Exact target element reference from the page snapshot
952
+ - `text` (string): Text to type into the element
953
+ - `submit` (boolean, optional): Whether to submit entered text (press Enter after)
954
+ - `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.
955
+ - Read-only: **false**
956
+
957
+ <!-- NOTE: This has been generated via update-readme.js -->
958
+
959
+ - **browser_wait_for**
960
+ - Title: Wait for
961
+ - Description: Wait for text to appear or disappear or a specified time to pass
962
+ - Parameters:
963
+ - `time` (number, optional): The time to wait in seconds
964
+ - `text` (string, optional): The text to wait for
965
+ - `textGone` (string, optional): The text to wait for to disappear
966
+ - Read-only: **false**
967
+
968
+ </details>
969
+
970
+ <details>
971
+ <summary><b>Tab management</b></summary>
972
+
973
+ <!-- NOTE: This has been generated via update-readme.js -->
974
+
975
+ - **browser_tabs**
976
+ - Title: Manage tabs
977
+ - Description: List, create, close, or select a browser tab.
978
+ - Parameters:
979
+ - `action` (string): Operation to perform
980
+ - `index` (number, optional): Tab index, used for close/select. If omitted for close, current tab is closed.
981
+ - Read-only: **false**
982
+
983
+ </details>
984
+
985
+ <details>
986
+ <summary><b>Browser installation</b></summary>
987
+
988
+ <!-- NOTE: This has been generated via update-readme.js -->
989
+
990
+ - **browser_install**
991
+ - Title: Install the browser specified in the config
992
+ - Description: Install the browser specified in the config. Call this if you get an error about the browser not being installed.
993
+ - Parameters: None
994
+ - Read-only: **false**
995
+
996
+ </details>
997
+
998
+ <details>
999
+ <summary><b>Coordinate-based (opt-in via --caps=vision)</b></summary>
1000
+
1001
+ <!-- NOTE: This has been generated via update-readme.js -->
1002
+
1003
+ - **browser_mouse_click_xy**
1004
+ - Title: Click
1005
+ - Description: Click left mouse button at a given position
1006
+ - Parameters:
1007
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
1008
+ - `x` (number): X coordinate
1009
+ - `y` (number): Y coordinate
1010
+ - Read-only: **false**
1011
+
1012
+ <!-- NOTE: This has been generated via update-readme.js -->
1013
+
1014
+ - **browser_mouse_drag_xy**
1015
+ - Title: Drag mouse
1016
+ - Description: Drag left mouse button to a given position
1017
+ - Parameters:
1018
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
1019
+ - `startX` (number): Start X coordinate
1020
+ - `startY` (number): Start Y coordinate
1021
+ - `endX` (number): End X coordinate
1022
+ - `endY` (number): End Y coordinate
1023
+ - Read-only: **false**
1024
+
1025
+ <!-- NOTE: This has been generated via update-readme.js -->
1026
+
1027
+ - **browser_mouse_move_xy**
1028
+ - Title: Move mouse
1029
+ - Description: Move mouse to a given position
1030
+ - Parameters:
1031
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
1032
+ - `x` (number): X coordinate
1033
+ - `y` (number): Y coordinate
1034
+ - Read-only: **false**
1035
+
1036
+ </details>
1037
+
1038
+ <details>
1039
+ <summary><b>PDF generation (opt-in via --caps=pdf)</b></summary>
1040
+
1041
+ <!-- NOTE: This has been generated via update-readme.js -->
1042
+
1043
+ - **browser_pdf_save**
1044
+ - Title: Save as PDF
1045
+ - Description: Save page as PDF
1046
+ - Parameters:
1047
+ - `filename` (string, optional): File name to save the pdf to. Defaults to `page-{timestamp}.pdf` if not specified. Prefer relative file names to stay within the output directory.
1048
+ - Read-only: **true**
1049
+
1050
+ </details>
1051
+
1052
+ <details>
1053
+ <summary><b>Test assertions (opt-in via --caps=testing)</b></summary>
1054
+
1055
+ <!-- NOTE: This has been generated via update-readme.js -->
1056
+
1057
+ - **browser_generate_locator**
1058
+ - Title: Create locator for element
1059
+ - Description: Generate locator for the given element to use in tests
1060
+ - Parameters:
1061
+ - `element` (string): Human-readable element description used to obtain permission to interact with the element
1062
+ - `ref` (string): Exact target element reference from the page snapshot
1063
+ - Read-only: **true**
1064
+
1065
+ <!-- NOTE: This has been generated via update-readme.js -->
1066
+
1067
+ - **browser_verify_element_visible**
1068
+ - Title: Verify element visible
1069
+ - Description: Verify element is visible on the page
1070
+ - Parameters:
1071
+ - `role` (string): ROLE of the element. Can be found in the snapshot like this: `- {ROLE} "Accessible Name":`
1072
+ - `accessibleName` (string): ACCESSIBLE_NAME of the element. Can be found in the snapshot like this: `- role "{ACCESSIBLE_NAME}"`
1073
+ - Read-only: **false**
1074
+
1075
+ <!-- NOTE: This has been generated via update-readme.js -->
1076
+
1077
+ - **browser_verify_list_visible**
1078
+ - Title: Verify list visible
1079
+ - Description: Verify list is visible on the page
1080
+ - Parameters:
1081
+ - `element` (string): Human-readable list description
1082
+ - `ref` (string): Exact target element reference that points to the list
1083
+ - `items` (array): Items to verify
1084
+ - Read-only: **false**
1085
+
1086
+ <!-- NOTE: This has been generated via update-readme.js -->
1087
+
1088
+ - **browser_verify_text_visible**
1089
+ - Title: Verify text visible
1090
+ - Description: Verify text is visible on the page. Prefer browser_verify_element_visible if possible.
1091
+ - Parameters:
1092
+ - `text` (string): TEXT to verify. Can be found in the snapshot like this: `- role "Accessible Name": {TEXT}` or like this: `- text: {TEXT}`
1093
+ - Read-only: **false**
1094
+
1095
+ <!-- NOTE: This has been generated via update-readme.js -->
1096
+
1097
+ - **browser_verify_value**
1098
+ - Title: Verify value
1099
+ - Description: Verify element value
1100
+ - Parameters:
1101
+ - `type` (string): Type of the element
1102
+ - `element` (string): Human-readable element description
1103
+ - `ref` (string): Exact target element reference that points to the element
1104
+ - `value` (string): Value to verify. For checkbox, use "true" or "false".
1105
+ - Read-only: **false**
1106
+
1107
+ </details>
1108
+
1109
+ <details>
1110
+ <summary><b>Tracing (opt-in via --caps=tracing)</b></summary>
1111
+
1112
+ <!-- NOTE: This has been generated via update-readme.js -->
1113
+
1114
+ - **browser_start_tracing**
1115
+ - Title: Start tracing
1116
+ - Description: Start trace recording
1117
+ - Parameters: None
1118
+ - Read-only: **true**
1119
+
1120
+ <!-- NOTE: This has been generated via update-readme.js -->
1121
+
1122
+ - **browser_stop_tracing**
1123
+ - Title: Stop tracing
1124
+ - Description: Stop trace recording
1125
+ - Parameters: None
1126
+ - Read-only: **true**
1127
+
1128
+ </details>
1129
+
1130
+
1131
+ <!--- End of tools generated section -->