@raultov/browser-control-mcp 0.2.0-beta.2 → 0.3.0-beta.3
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/CHANGELOG.md +151 -0
- package/README.md +15 -6
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,157 @@ from a copy of its code: entries describe the differences from that release.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.3.0-beta.3] - 2026-10-25
|
|
14
|
+
|
|
15
|
+
Public **BETA**. Result of a tool-by-tool audit on real Chrome and Firefox:
|
|
16
|
+
tools that reported success for an action that did not happen now fail or
|
|
17
|
+
say what happened, secrets no longer leak into logs or replies, and a new
|
|
18
|
+
`handle_dialog` tool closes JavaScript dialogs. Some replies change (marked
|
|
19
|
+
in the entries below: `scroll`, `fill_input`, `click_element` errors,
|
|
20
|
+
Chrome `open_tab` ids).
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- `handle_dialog` (both browsers): accepts or dismisses the JavaScript
|
|
25
|
+
dialog (`alert`, `confirm`, `prompt` with `prompt_text`, `beforeunload`)
|
|
26
|
+
open on a tab, and replies with its type and message.
|
|
27
|
+
|
|
28
|
+
### Changed
|
|
29
|
+
|
|
30
|
+
- Chrome: when the first call on an instance is `open_tab`, the browser's
|
|
31
|
+
own first page is now registered too (as on Firefox), so the new tab is
|
|
32
|
+
`tab-2` and stays inactive until `switch_tab`; before, it was `tab-1` and
|
|
33
|
+
active.
|
|
34
|
+
|
|
35
|
+
### Fixed
|
|
36
|
+
|
|
37
|
+
- Chrome tracks popups (`window.open`) and tabs closed by the page or the
|
|
38
|
+
user when the first call on an instance is `open_tab`; it only did after
|
|
39
|
+
a call that used the instance's default page.
|
|
40
|
+
- `navigate` and `reload` keep their 30 s budget on slow pages (both
|
|
41
|
+
browsers). A server slow to answer, or a page slow to fire `load`, hit
|
|
42
|
+
the 10 s protocol command timeout and failed although the navigation went
|
|
43
|
+
on; now the call waits for `load` up to 30 s from its start and answers
|
|
44
|
+
then, with the not-loaded note when it did not come.
|
|
45
|
+
- `get_network_logs` `clear: true` removes only the requests and frames it
|
|
46
|
+
returned (with `url_filter`, `type_filter` or `current_navigation_only`
|
|
47
|
+
it used to empty everything, also what was never returned), as
|
|
48
|
+
`get_console_logs` does. WebSocket connections keep their URL after a
|
|
49
|
+
clear (later frames used to have `url: ""`).
|
|
50
|
+
- Chrome `pause_on_load` no longer leaves its `debugger;` script injected
|
|
51
|
+
(after which every later load paused): calling it again replaces the
|
|
52
|
+
previous script, and a `resume` Chrome refuses because the reload has not
|
|
53
|
+
paused yet keeps the script pending, so the next `resume` removes it.
|
|
54
|
+
- JavaScript dialogs no longer hang the tools. A call during which the page
|
|
55
|
+
opens a dialog (`evaluate_js` running `alert()`, a `click_element` on a
|
|
56
|
+
button that asks `confirm()`, a `navigate` stopped by `beforeunload`)
|
|
57
|
+
fails at once quoting the dialog instead of after a 10–20 s timeout, and
|
|
58
|
+
while a dialog is open the page tools fail naming it and pointing to
|
|
59
|
+
`handle_dialog`. On Chrome the tab used to stay blocked until a raw
|
|
60
|
+
`Page.handleJavaScriptDialog`. Chrome errors are worded with the
|
|
61
|
+
protocol's message instead of Rust debug output (`Timeout { method: ...
|
|
62
|
+
}`).
|
|
63
|
+
|
|
64
|
+
- Security: with `RUST_LOG=trace` the MCP transport logged every incoming
|
|
65
|
+
tool call in full, including the `enable_proxy_auth` password and raw
|
|
66
|
+
protocol params. Its logs are now capped at `info`, like `cdp-lite`'s.
|
|
67
|
+
- Security: copies of the user's cookies (`copy_cookies`) could stay in the
|
|
68
|
+
temp directory: when a launch failed, when a seed was replaced before
|
|
69
|
+
use, when a browser failed to stop, when a partial copy failed, and at
|
|
70
|
+
shutdown after the seeded Chrome had crashed. The seeded profile now
|
|
71
|
+
deletes itself whenever it is dropped, and shutdown drops the seed of an
|
|
72
|
+
instance that is no longer running.
|
|
73
|
+
- Security: `get_network_logs` returned request bodies (login forms with
|
|
74
|
+
passwords, token exchanges) and API-key headers such as `X-Api-Key` in
|
|
75
|
+
full by default. Request bodies and every header whose name contains
|
|
76
|
+
`token`, `secret`, `api-key`, `apikey`, `password`, `session`, `csrf` or
|
|
77
|
+
`xsrf` are now `<redacted>` unless `include_sensitive_headers: true`.
|
|
78
|
+
- `search_scripts` positions are right, so they can be passed to
|
|
79
|
+
`set_breakpoint` as they are. A match at the start of a line was reported
|
|
80
|
+
at the end of the previous line (both browsers); matches in inline scripts
|
|
81
|
+
were counted from the script, not the page (Chrome); columns now count
|
|
82
|
+
UTF-16 units, as the browsers do, instead of bytes.
|
|
83
|
+
- Firefox `set_breakpoint` no longer sets breakpoints that never fire. A
|
|
84
|
+
`column_number` Firefox cannot break on (it ignores those silently) moves
|
|
85
|
+
to the next breakable column of the line once the script is loaded, as on
|
|
86
|
+
Chrome, and the reply says where; a column past every breakable one is an
|
|
87
|
+
error. A second breakpoint at the same location is refused naming the
|
|
88
|
+
first: Firefox keeps one per location, so removing either id used to
|
|
89
|
+
remove both.
|
|
90
|
+
- Firefox `evaluate_js` no longer changes the type of nested values: `NaN`
|
|
91
|
+
and `±Infinity` inside objects and arrays were strings (`"NaN"`), `-0`
|
|
92
|
+
was `"-0"`, a BigInt was a string of digits, `undefined` was `null` in
|
|
93
|
+
objects and a cycle was `{}`. Nested values now follow JSON as on Chrome
|
|
94
|
+
(`null`, `0`, `undefined` left out); an object holding a BigInt or a
|
|
95
|
+
cycle has no JSON form and is described (`"Object"`, `value: null`), and
|
|
96
|
+
an object reached twice without a cycle is serialised both times.
|
|
97
|
+
- `webmcp_list_tools` no longer hides page tools registered without an
|
|
98
|
+
`inputSchema` (optional in WebMCP); they are listed without one and can
|
|
99
|
+
be invoked.
|
|
100
|
+
- Chrome `restart_browser` without `proxy_server` keeps the instance's own
|
|
101
|
+
proxy (the one given to `open_instance` or the previous restart), as on
|
|
102
|
+
Firefox; it used to fall back to `--proxy-server`, or none, silently.
|
|
103
|
+
- `get_console_logs`: `console.warn` is level `warning` on Firefox too (it
|
|
104
|
+
was `warn`, so `level_filter: "warning"` found nothing there and `"warn"`
|
|
105
|
+
nothing on Chrome); `level_filter` accepts `warn` as an alias.
|
|
106
|
+
- Chrome: the first call on a fresh instance (usually `navigate`) waits
|
|
107
|
+
for the browser's page to register as a tab and uses it. It used to run
|
|
108
|
+
on a session-level connection whose captured state stopped being read
|
|
109
|
+
once the tab registered a moment later, so the first page's network
|
|
110
|
+
requests were missing from `get_network_logs` and `search_scripts` found
|
|
111
|
+
nothing right after it.
|
|
112
|
+
- Chrome `enable_proxy_auth` no longer stops answering after falling behind
|
|
113
|
+
a burst of events (it left request interception on with nobody
|
|
114
|
+
continuing the tab's requests, so they hung); whatever ends the handler
|
|
115
|
+
turns interception off. It also subscribes before enabling interception,
|
|
116
|
+
so a request paused right away is not missed.
|
|
117
|
+
- A browser that crashed or was killed from outside is reported: every call
|
|
118
|
+
on that instance answers "The browser of this instance closed or crashed
|
|
119
|
+
... Call 'restart_browser'", its dead tabs are forgotten, and nothing is
|
|
120
|
+
relaunched behind the agent's back. Chrome used to answer `CDP Error:
|
|
121
|
+
Disconnected` forever while silently starting an unused new Chrome (and
|
|
122
|
+
leaking the dead one's pool entry); Firefox answered "the browser was
|
|
123
|
+
stopped" forever. `restart_browser`, `stop_browser` and `close_instance`
|
|
124
|
+
work as usual afterwards. Chrome `open_tab` checks `--local` before it
|
|
125
|
+
starts a browser.
|
|
126
|
+
- A page's own `debugger;` statements no longer pause it while the tab has
|
|
127
|
+
no breakpoint (and, on Chrome, no `pause_on_load`). The debugger is
|
|
128
|
+
always attached, so anti-debugging pages (`setInterval(() => {debugger})`)
|
|
129
|
+
and a stray `debugger;` froze every tool on the tab until a timeout. The
|
|
130
|
+
first breakpoint turns them back on, removing the last one turns them off
|
|
131
|
+
(Chrome `Debugger.setSkipAllPauses`, re-applied after cross-process
|
|
132
|
+
navigations; Firefox `shouldPauseOnDebuggerStatement`). Chrome's
|
|
133
|
+
session-level connection drops its debugger once the page is a
|
|
134
|
+
registered tab, so it no longer resumes the tab's pauses.
|
|
135
|
+
- `fill_input` no longer types into the wrong element or reports a fill
|
|
136
|
+
that did not happen (both browsers). An element that cannot take the text
|
|
137
|
+
(a plain element, disabled, read-only, a non-text input such as a
|
|
138
|
+
checkbox, or one that cannot take focus) fails with the reason and nothing
|
|
139
|
+
is typed; before, the text went to whichever element had focus. A
|
|
140
|
+
`<select>` gets the option whose value or label equals the text (it used
|
|
141
|
+
to be emptied on Chrome). After typing, a field left empty (it rejected the
|
|
142
|
+
text, e.g. letters in a number field) is an error, and a field holding
|
|
143
|
+
something else (a mask, `maxlength`) succeeds with a note; the text is
|
|
144
|
+
never echoed back. The field is emptied through the native `value` setter,
|
|
145
|
+
which React-controlled inputs observe. On Chrome, an invalid selector
|
|
146
|
+
reports its `SyntaxError` instead of "Element not found". The description
|
|
147
|
+
no longer promises a `change` event: it fires when the field loses focus,
|
|
148
|
+
as for a user.
|
|
149
|
+
- `click_element` no longer reports a click that hit another element or
|
|
150
|
+
nothing (both browsers). The element is scrolled into view first (Chrome
|
|
151
|
+
used to click off-screen coordinates into the void; Firefox failed with
|
|
152
|
+
"move target out of bounds"), and the call fails without clicking when it
|
|
153
|
+
has no visible box (Chrome used to click the page corner at (0, 0)) or
|
|
154
|
+
when another element covers the point, naming it (an overlay used to get
|
|
155
|
+
the click on both). Both browsers click the same checked viewport point;
|
|
156
|
+
Firefox no longer leaves the pointer pressed when its actions fail.
|
|
157
|
+
- `scroll` no longer reports success when nothing moved (both browsers). The
|
|
158
|
+
reply adds the window positions as JSON `{before, after}` (plus
|
|
159
|
+
`element_in_view` for a selector) after its first line, which says why the
|
|
160
|
+
window did not move when it did not (at the edge, or the page scrolls an
|
|
161
|
+
inner element). Scrolling to a hidden element fails. `x` is no longer
|
|
162
|
+
dropped when scrolling by `pages`.
|
|
163
|
+
|
|
13
164
|
## [0.2.0-beta.2] - 2026-10-14
|
|
14
165
|
|
|
15
166
|
Public **BETA**. Firefox debugger internals only; tool replies are the same
|
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ It is the successor of
|
|
|
11
11
|
from a copy of its code) and complements Playwright MCP or
|
|
12
12
|
chrome-devtools-mcp with runtime JavaScript debugging on both browsers.
|
|
13
13
|
|
|
14
|
-
> **Status: BETA (0.
|
|
14
|
+
> **Status: BETA (0.3.0-beta.3).** This version contains known bugs and differences
|
|
15
15
|
> between Chrome and Firefox (see [Limitations and TODO](#limitations-and-todo))
|
|
16
16
|
> and parts that have not been verified (see [Untested](#untested)). Tool
|
|
17
17
|
> replies may change in incompatible ways before 1.0. Please report problems
|
|
@@ -48,11 +48,12 @@ see the note.
|
|
|
48
48
|
| `switch_tab` | ✓ | ✓ | |
|
|
49
49
|
| `navigate` | ✓ | ✓ | |
|
|
50
50
|
| `reload` | ✓ | ✓ | |
|
|
51
|
-
| `scroll` | ✓ | ✓ | |
|
|
51
|
+
| `scroll` | ✓ | ✓ | reports the window positions before and after |
|
|
52
52
|
| `inspect_dom` | ✓ | ✓ | |
|
|
53
53
|
| `capture_screenshot` | ✓ | ✓ | |
|
|
54
|
-
| `click_element` | ✓ | ✓ | |
|
|
55
|
-
| `fill_input` | ✓ | ✓ | |
|
|
54
|
+
| `click_element` | ✓ | ✓ | scrolls the element into view; fails without clicking when it is hidden or covered |
|
|
55
|
+
| `fill_input` | ✓ | ✓ | picks `<select>` options; fails without typing on elements that cannot take the text; Chrome inserts the text, Firefox types keys |
|
|
56
|
+
| `handle_dialog` | ✓ | ✓ | accepts or dismisses the open `alert` / `confirm` / `prompt` / `beforeunload` dialog |
|
|
56
57
|
| `evaluate_js` | ✓ | ✓ | |
|
|
57
58
|
| `get_console_logs` | ✓ | ✓ | Firefox: page errors, CSS warnings and platform messages need the debugger port |
|
|
58
59
|
| `get_network_logs` | ✓ | ✓ | Firefox: WebSocket frames need the debugger port |
|
|
@@ -383,6 +384,11 @@ Both browsers answer the same replies, with 0-based lines everywhere:
|
|
|
383
384
|
|
|
384
385
|
Breakpoint ids are per tab and MCP-level (`bp-1`, `bp-2`...), like tab ids.
|
|
385
386
|
|
|
387
|
+
While a tab has no breakpoint (and, on Chrome, no pending `pause_on_load`),
|
|
388
|
+
the page's own `debugger;` statements do not pause it: the debugger is
|
|
389
|
+
always attached, and anti-debugging pages loop on `debugger;` to freeze
|
|
390
|
+
every tool. The first breakpoint turns them back on.
|
|
391
|
+
|
|
386
392
|
Chrome also offers `pause_on_load` (pause on the first statement of the next
|
|
387
393
|
load). Firefox notes: breakpoints by URL only; without `column_number` the
|
|
388
394
|
breakpoint binds to the first breakable column of the line, in whichever of
|
|
@@ -479,8 +485,11 @@ incompatible:
|
|
|
479
485
|
- The Firefox debugger port needs `devtools.chrome.enabled`: any local
|
|
480
486
|
process that reaches that port gets chrome (privileged) access to the
|
|
481
487
|
browser. Use `--no-firefox-debugger` when you do not need the debugger.
|
|
482
|
-
- Credential headers (`Authorization`, `Cookie`, `Set-Cookie`,
|
|
483
|
-
|
|
488
|
+
- Credential headers (`Authorization`, `Cookie`, `Set-Cookie`, and any
|
|
489
|
+
header whose name contains `token`, `secret`, `api-key`, `password`,
|
|
490
|
+
`session` or `csrf`) and request bodies are redacted in
|
|
491
|
+
`get_network_logs` unless `include_sensitive_headers: true`. URLs and
|
|
492
|
+
response bodies are returned as they are.
|
|
484
493
|
- Logs carry tool names, ids, protocol method names and sizes, never
|
|
485
494
|
payloads, cookies or URLs with queries.
|
|
486
495
|
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"hasInstallScript": true,
|
|
20
20
|
"license": "MIT",
|
|
21
21
|
"name": "@raultov/browser-control-mcp",
|
|
22
|
-
"version": "0.
|
|
22
|
+
"version": "0.3.0-beta.3"
|
|
23
23
|
},
|
|
24
24
|
"node_modules/detect-libc": {
|
|
25
25
|
"engines": {
|
|
@@ -48,5 +48,5 @@
|
|
|
48
48
|
}
|
|
49
49
|
},
|
|
50
50
|
"requires": true,
|
|
51
|
-
"version": "0.
|
|
51
|
+
"version": "0.3.0-beta.3"
|
|
52
52
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"artifactDownloadUrls": [
|
|
3
|
-
"https://github.com/raultov/browser-control-mcp/releases/download/v0.
|
|
3
|
+
"https://github.com/raultov/browser-control-mcp/releases/download/v0.3.0-beta.3"
|
|
4
4
|
],
|
|
5
5
|
"author": "raultov <raultov@protonmail.com>",
|
|
6
6
|
"bin": {
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"zipExt": ".tar.xz"
|
|
93
93
|
}
|
|
94
94
|
},
|
|
95
|
-
"version": "0.
|
|
95
|
+
"version": "0.3.0-beta.3",
|
|
96
96
|
"volta": {
|
|
97
97
|
"node": "18.14.1",
|
|
98
98
|
"npm": "9.5.0"
|