moltbrowser-mcp 0.0.1 → 0.0.2
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 +49 -155
- package/cli.js +2 -2
- package/package.json +3 -4
- package/src/README.md +9 -2
- package/src/execution-translator.js +2 -2
- package/src/proxy-server.js +17 -0
package/README.md
CHANGED
|
@@ -1,58 +1,26 @@
|
|
|
1
|
-
|
|
1
|
+

|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
<div align="center">
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 🦞 MoltBrowser-MCP 🦞
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
Browser agents land on a page and have to figure out the DOM from scratch every time. They guess at selectors, explore the page, and often get it wrong. Meanwhile, [WebMCP Hub](https://webmcp-hub.com) already has community-contributed configs with exact CSS selectors, step sequences, and extraction rules for sites — but agents don't use them.
|
|
10
|
-
|
|
11
|
-
### The Solution
|
|
12
|
-
|
|
13
|
-
This fork adds a **proxy layer** that sits between the agent and upstream Playwright MCP. On every navigation, the proxy checks the hub. If configs exist, it dynamically registers site-specific tools. The agent sees `hub_search-repos(query, language)` as a first-class callable tool — not a JSON blob it has to interpret.
|
|
14
|
-
|
|
15
|
-
**Before (vanilla Playwright MCP):**
|
|
16
|
-
> "Here's a browser. Figure out the page yourself."
|
|
17
|
-
|
|
18
|
-
**After (with hub integration):**
|
|
19
|
-
> "Here's a browser. You're on geogridgame.com — here's `hub_get-rows`, `hub_guess-cell`, `hub_get-columns`. Those just work."
|
|
7
|
+
*A community-driven contribution space where agents and the humans behind them share browser configs so every agent navigates the web faster and cheaper than the last.*
|
|
20
8
|
|
|
21
|
-
|
|
9
|
+
[](https://github.com/Joakim-Sael/moltbrowser-mcp/actions/workflows/ci.yml)
|
|
10
|
+
[](https://www.npmjs.com/package/moltbrowser-mcp)
|
|
11
|
+
[](LICENSE)
|
|
22
12
|
|
|
23
|
-
|
|
13
|
+
</div>
|
|
24
14
|
|
|
25
|
-
|
|
26
|
-
- **Community-powered**. Tools come from [WebMCP Hub](https://webmcp-hub.com) configs with tested CSS selectors.
|
|
27
|
-
- **Full Playwright MCP compatibility**. All 22+ upstream tools work unchanged.
|
|
28
|
-
- **Graceful fallback**. If the hub is down or has no config, behaves as vanilla Playwright MCP.
|
|
29
|
-
- **Agents teach agents**. Use `hub_upload-config` to share what you learn with the next agent.
|
|
15
|
+
### The Problem
|
|
30
16
|
|
|
31
|
-
|
|
32
|
-
- Node.js 18 or newer
|
|
33
|
-
- VS Code, Cursor, Windsurf, Claude Desktop, Goose or any other MCP client
|
|
17
|
+
Every time an agent opens a browser, it starts from zero. It stares at the DOM, guesses at selectors, wastes tokens figuring out how the page works — and still gets it wrong half the time. This happens on every site, for every agent, every single run. Even when a thousand agents before it already solved the exact same page.
|
|
34
18
|
|
|
35
|
-
|
|
36
|
-
// Generate using:
|
|
37
|
-
node utils/generate-links.js
|
|
38
|
-
-->
|
|
19
|
+
MoltBrowser-MCP fixes that. When an agent lands on x.com it gets `hub_post-tweet`, `hub_like-post`, `hub_follow-user` as ready-to-call tools. When it lands on GitHub it gets `hub_search-repos`, `hub_open-pr`. Contributed by the community, tested on real pages. No guessing. No wasted tokens.
|
|
39
20
|
|
|
40
21
|
### Getting started
|
|
41
22
|
|
|
42
|
-
**
|
|
43
|
-
|
|
44
|
-
```json
|
|
45
|
-
{
|
|
46
|
-
"mcpServers": {
|
|
47
|
-
"moltbrowser-mcp": {
|
|
48
|
-
"command": "npx",
|
|
49
|
-
"args": ["moltbrowser-mcp"]
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
**With hub API key** (for uploading configs):
|
|
23
|
+
**[Get started at webmcp-hub.com](https://webmcp-hub.com)** — create an account, grab your API key, and add this to your MCP client settings:
|
|
56
24
|
|
|
57
25
|
```json
|
|
58
26
|
{
|
|
@@ -68,36 +36,6 @@ node utils/generate-links.js
|
|
|
68
36
|
}
|
|
69
37
|
```
|
|
70
38
|
|
|
71
|
-
**Hub-specific options:**
|
|
72
|
-
|
|
73
|
-
| Option | Description |
|
|
74
|
-
|--------|-------------|
|
|
75
|
-
| `--hub-url=<url>` | Override hub URL (default: `https://webmcp-hub.com`) |
|
|
76
|
-
| `--hub-api-key=<key>` | API key for write operations (also `HUB_API_KEY` env var) |
|
|
77
|
-
| `--no-hub` | Disable hub integration entirely (behaves as vanilla Playwright MCP) |
|
|
78
|
-
|
|
79
|
-
All standard Playwright MCP options (`--headless`, `--browser`, `--caps`, etc.) are passed through to the upstream server.
|
|
80
|
-
|
|
81
|
-
<details>
|
|
82
|
-
<summary>Claude Code</summary>
|
|
83
|
-
|
|
84
|
-
```bash
|
|
85
|
-
claude mcp add moltbrowser-mcp npx moltbrowser-mcp
|
|
86
|
-
```
|
|
87
|
-
</details>
|
|
88
|
-
|
|
89
|
-
<details>
|
|
90
|
-
<summary>Cursor</summary>
|
|
91
|
-
|
|
92
|
-
Go to `Cursor Settings` -> `MCP` -> `Add new MCP Server`. Use `command` type with the command `npx moltbrowser-mcp`.
|
|
93
|
-
</details>
|
|
94
|
-
|
|
95
|
-
<details>
|
|
96
|
-
<summary>Claude Desktop / Other MCP clients</summary>
|
|
97
|
-
|
|
98
|
-
Use the standard config above in your MCP client's settings file.
|
|
99
|
-
</details>
|
|
100
|
-
|
|
101
39
|
### How It Works
|
|
102
40
|
|
|
103
41
|
```
|
|
@@ -105,14 +43,14 @@ Agent (Claude, Cursor, etc.)
|
|
|
105
43
|
|
|
|
106
44
|
| MCP protocol (stdio)
|
|
107
45
|
v
|
|
108
|
-
|
|
46
|
+
moltbrowser-mcp (hub proxy)
|
|
109
47
|
|-- On navigate: queries WebMCP Hub REST API
|
|
110
48
|
|-- Dynamically adds hub tools to tool list
|
|
111
49
|
|-- Hub tool calls -> translates to Playwright code -> browser_run_code
|
|
112
50
|
|
|
|
113
51
|
| MCP protocol (stdio, child process)
|
|
114
52
|
v
|
|
115
|
-
|
|
53
|
+
Playwright browser automation
|
|
116
54
|
|
|
|
117
55
|
v
|
|
118
56
|
Browser (Chrome, Firefox, WebKit)
|
|
@@ -135,7 +73,7 @@ Hub tools are prefixed with `hub_` and appear/disappear as the agent navigates b
|
|
|
135
73
|
|
|
136
74
|
### Configuration
|
|
137
75
|
|
|
138
|
-
All standard
|
|
76
|
+
All standard browser automation options are supported:
|
|
139
77
|
|
|
140
78
|
<!--- Options generated by update-readme.js -->
|
|
141
79
|
|
|
@@ -147,11 +85,9 @@ All standard Playwright MCP options are supported and passed through to the upst
|
|
|
147
85
|
| --blocked-origins <origins> | semicolon-separated list of origins to block the browser from requesting. Blocklist is evaluated before allowlist. If used without the allowlist, requests not matching the blocklist are still allowed. Important: *does not* serve as a security boundary and *does not* affect redirects.<br>*env* `PLAYWRIGHT_MCP_BLOCKED_ORIGINS` |
|
|
148
86
|
| --block-service-workers | block service workers<br>*env* `PLAYWRIGHT_MCP_BLOCK_SERVICE_WORKERS` |
|
|
149
87
|
| --browser <browser> | browser or chrome channel to use, possible values: chrome, firefox, webkit, msedge.<br>*env* `PLAYWRIGHT_MCP_BROWSER` |
|
|
150
|
-
| --caps <caps> | comma-separated list of additional capabilities to enable, possible values: vision, pdf
|
|
88
|
+
| --caps <caps> | comma-separated list of additional capabilities to enable, possible values: vision, pdf.<br>*env* `PLAYWRIGHT_MCP_CAPS` |
|
|
151
89
|
| --cdp-endpoint <endpoint> | CDP endpoint to connect to.<br>*env* `PLAYWRIGHT_MCP_CDP_ENDPOINT` |
|
|
152
90
|
| --cdp-header <headers...> | CDP headers to send with the connect request, multiple can be specified.<br>*env* `PLAYWRIGHT_MCP_CDP_HEADER` |
|
|
153
|
-
| --cdp-timeout <timeout> | timeout in milliseconds for connecting to CDP endpoint, defaults to 30000ms<br>*env* `PLAYWRIGHT_MCP_CDP_TIMEOUT` |
|
|
154
|
-
| --codegen <lang> | specify the language to use for code generation, possible values: "typescript", "none". Default is "typescript".<br>*env* `PLAYWRIGHT_MCP_CODEGEN` |
|
|
155
91
|
| --config <path> | path to the configuration file.<br>*env* `PLAYWRIGHT_MCP_CONFIG` |
|
|
156
92
|
| --console-level <level> | level of console messages to return: "error", "warning", "info", "debug". Each level includes the messages of more severe levels.<br>*env* `PLAYWRIGHT_MCP_CONSOLE_LEVEL` |
|
|
157
93
|
| --device <device> | device to emulate, for example: "iPhone 15"<br>*env* `PLAYWRIGHT_MCP_DEVICE` |
|
|
@@ -171,7 +107,6 @@ All standard Playwright MCP options are supported and passed through to the upst
|
|
|
171
107
|
| --port <port> | port to listen on for SSE transport.<br>*env* `PLAYWRIGHT_MCP_PORT` |
|
|
172
108
|
| --proxy-bypass <bypass> | comma-separated domains to bypass proxy, for example ".com,chromium.org,.domain.com"<br>*env* `PLAYWRIGHT_MCP_PROXY_BYPASS` |
|
|
173
109
|
| --proxy-server <proxy> | specify proxy server, for example "http://myproxy:3128" or "socks5://myproxy:8080"<br>*env* `PLAYWRIGHT_MCP_PROXY_SERVER` |
|
|
174
|
-
| --sandbox | enable the sandbox for all process types that are normally not sandboxed.<br>*env* `PLAYWRIGHT_MCP_SANDBOX` |
|
|
175
110
|
| --save-session | Whether to save the Playwright MCP session into the output directory.<br>*env* `PLAYWRIGHT_MCP_SAVE_SESSION` |
|
|
176
111
|
| --save-trace | Whether to save the Playwright Trace of the session into the output directory.<br>*env* `PLAYWRIGHT_MCP_SAVE_TRACE` |
|
|
177
112
|
| --save-video <size> | Whether to save the video of the session into the output directory. For example "--save-video=800x600"<br>*env* `PLAYWRIGHT_MCP_SAVE_VIDEO` |
|
|
@@ -185,12 +120,16 @@ All standard Playwright MCP options are supported and passed through to the upst
|
|
|
185
120
|
| --user-agent <ua string> | specify user agent string<br>*env* `PLAYWRIGHT_MCP_USER_AGENT` |
|
|
186
121
|
| --user-data-dir <path> | path to the user data directory. If not specified, a temporary directory will be created.<br>*env* `PLAYWRIGHT_MCP_USER_DATA_DIR` |
|
|
187
122
|
| --viewport-size <size> | specify browser viewport size in pixels, for example "1280x720"<br>*env* `PLAYWRIGHT_MCP_VIEWPORT_SIZE` |
|
|
123
|
+
| --codegen <lang> | specify the language to use for code generation, possible values: "typescript", "none". Default is "typescript".<br>*env* `PLAYWRIGHT_MCP_CODEGEN` |
|
|
188
124
|
|
|
189
125
|
<!--- End of options generated section -->
|
|
190
126
|
|
|
127
|
+
<details>
|
|
128
|
+
<summary><b>Advanced configuration</b></summary>
|
|
129
|
+
|
|
191
130
|
### User profile
|
|
192
131
|
|
|
193
|
-
You can run
|
|
132
|
+
You can run with a persistent profile like a regular browser (default), in isolated contexts for testing sessions, or connect to your existing browser using the browser extension.
|
|
194
133
|
|
|
195
134
|
**Persistent profile**
|
|
196
135
|
|
|
@@ -221,7 +160,7 @@ state [here](https://playwright.dev/docs/auth).
|
|
|
221
160
|
"playwright": {
|
|
222
161
|
"command": "npx",
|
|
223
162
|
"args": [
|
|
224
|
-
"
|
|
163
|
+
"moltbrowser-mcp",
|
|
225
164
|
"--isolated",
|
|
226
165
|
"--storage-state={path/to/storage.json}"
|
|
227
166
|
]
|
|
@@ -230,10 +169,6 @@ state [here](https://playwright.dev/docs/auth).
|
|
|
230
169
|
}
|
|
231
170
|
```
|
|
232
171
|
|
|
233
|
-
**Browser Extension**
|
|
234
|
-
|
|
235
|
-
The Playwright MCP Chrome Extension allows you to connect to existing browser tabs and leverage your logged-in sessions and browser state. See [packages/extension/README.md](packages/extension/README.md) for installation and setup instructions.
|
|
236
|
-
|
|
237
172
|
### Initial state
|
|
238
173
|
|
|
239
174
|
There are multiple ways to provide the initial state to the browser context or a page.
|
|
@@ -265,11 +200,11 @@ window.isPlaywrightMCP = true;
|
|
|
265
200
|
|
|
266
201
|
### Configuration file
|
|
267
202
|
|
|
268
|
-
The
|
|
203
|
+
The server can be configured using a JSON configuration file. You can specify the configuration file
|
|
269
204
|
using the `--config` command line option:
|
|
270
205
|
|
|
271
206
|
```bash
|
|
272
|
-
npx
|
|
207
|
+
npx moltbrowser-mcp --config path/to/config.json
|
|
273
208
|
```
|
|
274
209
|
|
|
275
210
|
<details>
|
|
@@ -499,7 +434,7 @@ When running headed browser on system w/o display or from worker processes of th
|
|
|
499
434
|
run the MCP server from environment with the DISPLAY and pass the `--port` flag to enable HTTP transport.
|
|
500
435
|
|
|
501
436
|
```bash
|
|
502
|
-
npx
|
|
437
|
+
npx moltbrowser-mcp --port 8931
|
|
503
438
|
```
|
|
504
439
|
|
|
505
440
|
And then in MCP client config, set the `url` to the HTTP endpoint:
|
|
@@ -514,40 +449,6 @@ And then in MCP client config, set the `url` to the HTTP endpoint:
|
|
|
514
449
|
}
|
|
515
450
|
```
|
|
516
451
|
|
|
517
|
-
<details>
|
|
518
|
-
<summary><b>Docker</b></summary>
|
|
519
|
-
|
|
520
|
-
**NOTE:** The Docker implementation only supports headless chromium at the moment.
|
|
521
|
-
|
|
522
|
-
```js
|
|
523
|
-
{
|
|
524
|
-
"mcpServers": {
|
|
525
|
-
"playwright": {
|
|
526
|
-
"command": "docker",
|
|
527
|
-
"args": ["run", "-i", "--rm", "--init", "--pull=always", "mcr.microsoft.com/playwright/mcp"]
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
```
|
|
532
|
-
|
|
533
|
-
Or If you prefer to run the container as a long-lived service instead of letting the MCP client spawn it, use:
|
|
534
|
-
|
|
535
|
-
```
|
|
536
|
-
docker run -d -i --rm --init --pull=always \
|
|
537
|
-
--entrypoint node \
|
|
538
|
-
--name playwright \
|
|
539
|
-
-p 8931:8931 \
|
|
540
|
-
mcr.microsoft.com/playwright/mcp \
|
|
541
|
-
cli.js --headless --browser chromium --no-sandbox --port 8931
|
|
542
|
-
```
|
|
543
|
-
|
|
544
|
-
The server will listen on host port **8931** and can be reached by any MCP client.
|
|
545
|
-
|
|
546
|
-
You can build the Docker image yourself.
|
|
547
|
-
|
|
548
|
-
```
|
|
549
|
-
docker build -t mcr.microsoft.com/playwright/mcp .
|
|
550
|
-
```
|
|
551
452
|
</details>
|
|
552
453
|
|
|
553
454
|
<details>
|
|
@@ -556,13 +457,13 @@ docker build -t mcr.microsoft.com/playwright/mcp .
|
|
|
556
457
|
```js
|
|
557
458
|
import http from 'http';
|
|
558
459
|
|
|
559
|
-
import { createConnection } from '
|
|
460
|
+
import { createConnection } from 'moltbrowser-mcp';
|
|
560
461
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
561
462
|
|
|
562
463
|
http.createServer(async (req, res) => {
|
|
563
464
|
// ...
|
|
564
465
|
|
|
565
|
-
// Creates a headless
|
|
466
|
+
// Creates a headless MCP server with SSE transport
|
|
566
467
|
const connection = await createConnection({ browser: { launchOptions: { headless: true } } });
|
|
567
468
|
const transport = new SSEServerTransport('/messages', res);
|
|
568
469
|
await connection.connect(transport);
|
|
@@ -631,6 +532,7 @@ http.createServer(async (req, res) => {
|
|
|
631
532
|
- `function` (string): () => { /* code */ } or (element) => { /* code */ } when element is provided
|
|
632
533
|
- `element` (string, optional): Human-readable element description used to obtain permission to interact with the element
|
|
633
534
|
- `ref` (string, optional): Exact target element reference from the page snapshot
|
|
535
|
+
- `filename` (string, optional): Filename to save the result to. If not provided, result is returned as JSON string.
|
|
634
536
|
- Read-only: **false**
|
|
635
537
|
|
|
636
538
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
@@ -684,7 +586,7 @@ http.createServer(async (req, res) => {
|
|
|
684
586
|
|
|
685
587
|
- **browser_navigate_back**
|
|
686
588
|
- Title: Go back
|
|
687
|
-
- Description: Go back to the previous page
|
|
589
|
+
- Description: Go back to the previous page
|
|
688
590
|
- Parameters: None
|
|
689
591
|
- Read-only: **false**
|
|
690
592
|
|
|
@@ -724,6 +626,7 @@ http.createServer(async (req, res) => {
|
|
|
724
626
|
- Description: Run Playwright code snippet
|
|
725
627
|
- Parameters:
|
|
726
628
|
- `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(); }`
|
|
629
|
+
- `filename` (string, optional): Filename to save the result to. If not provided, result is returned as JSON string.
|
|
727
630
|
- Read-only: **false**
|
|
728
631
|
|
|
729
632
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
@@ -822,25 +725,18 @@ http.createServer(async (req, res) => {
|
|
|
822
725
|
- Title: Click
|
|
823
726
|
- Description: Click left mouse button at a given position
|
|
824
727
|
- Parameters:
|
|
728
|
+
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
825
729
|
- `x` (number): X coordinate
|
|
826
730
|
- `y` (number): Y coordinate
|
|
827
731
|
- Read-only: **false**
|
|
828
732
|
|
|
829
733
|
<!-- NOTE: This has been generated via update-readme.js -->
|
|
830
734
|
|
|
831
|
-
- **browser_mouse_down**
|
|
832
|
-
- Title: Press mouse down
|
|
833
|
-
- Description: Press mouse down
|
|
834
|
-
- Parameters:
|
|
835
|
-
- `button` (string, optional): Button to press, defaults to left
|
|
836
|
-
- Read-only: **false**
|
|
837
|
-
|
|
838
|
-
<!-- NOTE: This has been generated via update-readme.js -->
|
|
839
|
-
|
|
840
735
|
- **browser_mouse_drag_xy**
|
|
841
736
|
- Title: Drag mouse
|
|
842
737
|
- Description: Drag left mouse button to a given position
|
|
843
738
|
- Parameters:
|
|
739
|
+
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
844
740
|
- `startX` (number): Start X coordinate
|
|
845
741
|
- `startY` (number): Start Y coordinate
|
|
846
742
|
- `endX` (number): End X coordinate
|
|
@@ -853,29 +749,11 @@ http.createServer(async (req, res) => {
|
|
|
853
749
|
- Title: Move mouse
|
|
854
750
|
- Description: Move mouse to a given position
|
|
855
751
|
- Parameters:
|
|
752
|
+
- `element` (string): Human-readable element description used to obtain permission to interact with the element
|
|
856
753
|
- `x` (number): X coordinate
|
|
857
754
|
- `y` (number): Y coordinate
|
|
858
755
|
- Read-only: **false**
|
|
859
756
|
|
|
860
|
-
<!-- NOTE: This has been generated via update-readme.js -->
|
|
861
|
-
|
|
862
|
-
- **browser_mouse_up**
|
|
863
|
-
- Title: Press mouse up
|
|
864
|
-
- Description: Press mouse up
|
|
865
|
-
- Parameters:
|
|
866
|
-
- `button` (string, optional): Button to press, defaults to left
|
|
867
|
-
- Read-only: **false**
|
|
868
|
-
|
|
869
|
-
<!-- NOTE: This has been generated via update-readme.js -->
|
|
870
|
-
|
|
871
|
-
- **browser_mouse_wheel**
|
|
872
|
-
- Title: Scroll mouse wheel
|
|
873
|
-
- Description: Scroll mouse wheel
|
|
874
|
-
- Parameters:
|
|
875
|
-
- `deltaX` (number): X delta
|
|
876
|
-
- `deltaY` (number): Y delta
|
|
877
|
-
- Read-only: **false**
|
|
878
|
-
|
|
879
757
|
</details>
|
|
880
758
|
|
|
881
759
|
<details>
|
|
@@ -952,6 +830,22 @@ http.createServer(async (req, res) => {
|
|
|
952
830
|
<details>
|
|
953
831
|
<summary><b>Tracing (opt-in via --caps=tracing)</b></summary>
|
|
954
832
|
|
|
833
|
+
<!-- NOTE: This has been generated via update-readme.js -->
|
|
834
|
+
|
|
835
|
+
- **browser_start_tracing**
|
|
836
|
+
- Title: Start tracing
|
|
837
|
+
- Description: Start trace recording
|
|
838
|
+
- Parameters: None
|
|
839
|
+
- Read-only: **true**
|
|
840
|
+
|
|
841
|
+
<!-- NOTE: This has been generated via update-readme.js -->
|
|
842
|
+
|
|
843
|
+
- **browser_stop_tracing**
|
|
844
|
+
- Title: Stop tracing
|
|
845
|
+
- Description: Stop trace recording
|
|
846
|
+
- Parameters: None
|
|
847
|
+
- Read-only: **true**
|
|
848
|
+
|
|
955
849
|
</details>
|
|
956
850
|
|
|
957
851
|
|
package/cli.js
CHANGED
|
@@ -16,9 +16,9 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
const { program } = require('playwright-core/lib/utilsBundle');
|
|
19
|
-
const {
|
|
19
|
+
const { decorateCommand } = require('playwright/lib/mcp/program');
|
|
20
20
|
|
|
21
21
|
const packageJSON = require('./package.json');
|
|
22
22
|
const p = program.version('Version ' + packageJSON.version).name('Playwright MCP');
|
|
23
|
-
|
|
23
|
+
decorateCommand(p, packageJSON.version)
|
|
24
24
|
void program.parseAsync(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moltbrowser-mcp",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Playwright MCP with WebMCP Hub integration — dynamic, per-site tools for browser agents",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -20,7 +20,6 @@
|
|
|
20
20
|
"ctest": "playwright test --project=chrome",
|
|
21
21
|
"ftest": "playwright test --project=firefox",
|
|
22
22
|
"wtest": "playwright test --project=webkit",
|
|
23
|
-
"dtest": "MCP_IN_DOCKER=1 playwright test --project=chromium-docker",
|
|
24
23
|
"build": "echo OK",
|
|
25
24
|
"npm-publish": "npm run lint && npm run test && npm publish"
|
|
26
25
|
},
|
|
@@ -32,8 +31,8 @@
|
|
|
32
31
|
}
|
|
33
32
|
},
|
|
34
33
|
"dependencies": {
|
|
35
|
-
"playwright": "1.
|
|
36
|
-
"playwright-core": "1.
|
|
34
|
+
"playwright": "^1.58.2",
|
|
35
|
+
"playwright-core": "^1.58.2"
|
|
37
36
|
},
|
|
38
37
|
"bin": {
|
|
39
38
|
"playwright-mcp": "cli.js",
|
package/src/README.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Hub integration source
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This directory contains moltbrowser-mcp's WebMCP Hub integration layer:
|
|
4
|
+
|
|
5
|
+
- **`hub-client.js`** — fetches per-site tool definitions from the WebMCP Hub API
|
|
6
|
+
- **`hub-tools.js`** — registers and deregisters dynamic tools as the browser navigates
|
|
7
|
+
- **`proxy-server.js`** — MCP proxy that wraps the upstream Playwright MCP server and injects hub tools
|
|
8
|
+
- **`execution-translator.js`** — translates hub tool calls into Playwright actions
|
|
9
|
+
|
|
10
|
+
The upstream Playwright MCP source lives in the [Playwright monorepo](https://github.com/microsoft/playwright/blob/main/packages/playwright/src/mcp).
|
|
@@ -441,11 +441,11 @@ function addResultWait(phases, execution) {
|
|
|
441
441
|
|
|
442
442
|
/**
|
|
443
443
|
* Add top-level result extraction.
|
|
444
|
-
* If no resultSelector, returns a
|
|
444
|
+
* If no resultSelector, returns a neutral acknowledgment without prompting the agent to snapshot.
|
|
445
445
|
*/
|
|
446
446
|
function addExtraction(phases, selector, extractMode, attribute) {
|
|
447
447
|
if (!selector) {
|
|
448
|
-
phases.push(`return '[
|
|
448
|
+
phases.push(`return '[action ran — no result selector configured]';`);
|
|
449
449
|
return;
|
|
450
450
|
}
|
|
451
451
|
addStepExtraction(phases, selector, extractMode, attribute);
|
package/src/proxy-server.js
CHANGED
|
@@ -138,6 +138,7 @@ async function startProxy(options) {
|
|
|
138
138
|
description: [
|
|
139
139
|
'Access generic Playwright browser tools as a fallback when hub tools are insufficient.',
|
|
140
140
|
'Call without arguments to list all available tools.',
|
|
141
|
+
'Before calling an unfamiliar tool, use peek: true to inspect its full input schema first.',
|
|
141
142
|
'Common tools: browser_snapshot (see page accessibility tree), browser_click (click element by ref),',
|
|
142
143
|
'browser_fill_form (fill multiple fields), browser_type (type text),',
|
|
143
144
|
'browser_evaluate (run JS on page), browser_take_screenshot (capture page image).',
|
|
@@ -149,6 +150,10 @@ async function startProxy(options) {
|
|
|
149
150
|
type: 'string',
|
|
150
151
|
description: 'The Playwright tool name to run (e.g. "browser_click", "browser_snapshot"). Omit to list available tools.',
|
|
151
152
|
},
|
|
153
|
+
peek: {
|
|
154
|
+
type: 'boolean',
|
|
155
|
+
description: 'Set to true to inspect the full input schema of the specified tool without executing it. Use this before calling an unfamiliar tool to avoid schema errors.',
|
|
156
|
+
},
|
|
152
157
|
arguments: {
|
|
153
158
|
type: 'object',
|
|
154
159
|
description: 'Arguments for the Playwright tool.',
|
|
@@ -240,6 +245,18 @@ async function startProxy(options) {
|
|
|
240
245
|
};
|
|
241
246
|
}
|
|
242
247
|
|
|
248
|
+
// Peek — return the full inputSchema for the named tool without executing it.
|
|
249
|
+
if (toolArgs.peek === true) {
|
|
250
|
+
const tools = await getUpstreamTools();
|
|
251
|
+
const match = tools.find(t => t.name === innerTool);
|
|
252
|
+
if (!match) {
|
|
253
|
+
return { content: [{ type: 'text', text: `Unknown tool: "${innerTool}". Call browser_fallback without arguments to list available tools.` }] };
|
|
254
|
+
}
|
|
255
|
+
return {
|
|
256
|
+
content: [{ type: 'text', text: `Schema for ${innerTool}:\n\n${JSON.stringify(match.inputSchema, null, 2)}\n\nDescription: ${match.description || '(none)'}` }],
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
243
260
|
// Any real action tool (not list-tools, not snapshot) counts as "fallback was used".
|
|
244
261
|
// This triggers the one-shot contribution nudge on the next browser_snapshot.
|
|
245
262
|
if (innerTool !== 'browser_snapshot') {
|