patchright-mcp 0.0.54

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