@raultov/browser-control-mcp 0.3.4-beta.4 → 0.3.6-beta.6
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 +120 -0
- package/README.md +21 -12
- package/npm-shrinkwrap.json +2 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,126 @@ from a copy of its code: entries describe the differences from that release.
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.3.6-beta.6] - 2026-10-29
|
|
14
|
+
|
|
15
|
+
Public **BETA**. `fill_input` types the same way on both browsers,
|
|
16
|
+
`evaluate_js` gives objects the same value and names their class,
|
|
17
|
+
`inspect_dom` reads shadow roots and same-origin iframes, network logs
|
|
18
|
+
carry cookies and no longer wait on open streams, and raw commands that
|
|
19
|
+
would break the server's capture are refused. Some behaviour changes:
|
|
20
|
+
`fill_input` presses a key per character (about 1 ms each on Chrome),
|
|
21
|
+
`evaluate_js` values are their `JSON.stringify` form, `inspect_dom`
|
|
22
|
+
returns more HTML, and `send_cdp_command` refuses `*.disable` of the
|
|
23
|
+
captured domains and `Browser.close`.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `set_breakpoint` on Chrome fails for a line with no code at or after it
|
|
28
|
+
in the loaded script with that URL, saying where the script ends, and
|
|
29
|
+
sets nothing (as Firefox does). It answered `resolved: false`, which the
|
|
30
|
+
description explains as "until a script with that URL loads", for a
|
|
31
|
+
script that was loaded already: the breakpoint never fired.
|
|
32
|
+
|
|
33
|
+
- `inspect_dom` includes open shadow roots (as `<template
|
|
34
|
+
shadowrootmode="open">`) and the documents of same-origin iframes (each
|
|
35
|
+
after an `<!-- iframe <src>: -->` comment), and notes the cross-origin
|
|
36
|
+
iframes it cannot read. Text inside a web component or an iframe was
|
|
37
|
+
reported as not found.
|
|
38
|
+
|
|
39
|
+
- `get_network_logs` asks for a response body only once the response
|
|
40
|
+
finished loading, and the reply notes the ones still loading (an open
|
|
41
|
+
event stream). On Firefox an open server-sent events stream made every
|
|
42
|
+
call wait 10 s for its body; now it answers at once. Each body waits at
|
|
43
|
+
most 2 s.
|
|
44
|
+
|
|
45
|
+
- `get_network_logs` on Chrome returns the `Cookie` and `Set-Cookie`
|
|
46
|
+
headers (redacted unless `include_sensitive_headers: true`): Chrome
|
|
47
|
+
reports them only in its ExtraInfo events, which were ignored, so they
|
|
48
|
+
were missing even when asked for. On Firefox a repeated header (several
|
|
49
|
+
`Set-Cookie`) keeps every value, joined by newlines as on Chrome; only
|
|
50
|
+
the last one was kept.
|
|
51
|
+
|
|
52
|
+
- `capture_screenshot` checks `format` before capturing: `png`, `jpeg`
|
|
53
|
+
(or `jpg`) and `webp`, any case; anything else fails saying so. Firefox
|
|
54
|
+
answered a PNG labelled `image/gif` (or `image/jpg`), and Chrome a raw
|
|
55
|
+
`Invalid image format`. The reply's MIME type is the one of the image's
|
|
56
|
+
bytes.
|
|
57
|
+
|
|
58
|
+
- `send_cdp_command` refuses the commands that silently stopped what the
|
|
59
|
+
server captures (`Network.disable`, `Page.disable`, `Runtime.disable`,
|
|
60
|
+
`Log.disable`, `Debugger.disable`) or closed the browser
|
|
61
|
+
(`Browser.close`), saying what depends on them; `Network.disable` used to
|
|
62
|
+
leave `get_network_logs` empty without a word. `Fetch.enable` is sent with
|
|
63
|
+
a note that requests now pause until answered.
|
|
64
|
+
|
|
65
|
+
- `evaluate_js` (and `evaluate_on_call_frame`) gives an object or array the
|
|
66
|
+
same `value` on both browsers: what `JSON.stringify` gives (`toJSON`
|
|
67
|
+
counts, functions drop out), and an object that is not a plain one has
|
|
68
|
+
its class in `description`. `navigator` and `new URL(...)` answered `{}`
|
|
69
|
+
without a word; now `{"value": {}, "description": "Navigator"}` and
|
|
70
|
+
`{"value": "<href>", "description": "URL"}`. Nested functions were `{}`
|
|
71
|
+
on Chrome and `{"type": "function"}` on Firefox, and `location` was `{}`
|
|
72
|
+
on Firefox.
|
|
73
|
+
|
|
74
|
+
- `fill_input` types the same way on both browsers: Chrome now presses a
|
|
75
|
+
key per character, as Firefox did, so the page's keydown and keyup
|
|
76
|
+
handlers run and can cancel a key (a field refusing `a` got `abc` on
|
|
77
|
+
Chrome and `bc` on Firefox; now `bc` on both). Newlines and tabs are
|
|
78
|
+
inserted as text on both (as a key, Chrome pressed Tab and the rest of
|
|
79
|
+
the text left the field). Typing takes about 1 ms per character, so a
|
|
80
|
+
very long text is slower on Chrome than before.
|
|
81
|
+
- `fill_input` on Firefox types a long text in batches of 500 characters:
|
|
82
|
+
20 000 characters timed out half typed, now they take about 20 s.
|
|
83
|
+
- `fill_input` fires `change` once, as for a user: the browser fires it
|
|
84
|
+
when the field loses focus, and when the window has no focus (Firefox
|
|
85
|
+
headless, which never fired it) the fill fires it at the end.
|
|
86
|
+
|
|
87
|
+
## [0.3.5-beta.5] - 2026-10-28
|
|
88
|
+
|
|
89
|
+
Public **BETA**. Observation tools stop returning wrong or missing data
|
|
90
|
+
without saying so, an endless `evaluate_js` loop no longer kills a Chrome
|
|
91
|
+
tab, Firefox debugger calls no longer block other tabs, and WebMCP passes
|
|
92
|
+
every tool annotation through. Some replies change: `get_custom_events`
|
|
93
|
+
answers `{events, total, truncated}` with the newest events, and
|
|
94
|
+
`get_network_logs` requests may carry `error` and
|
|
95
|
+
`response_body_encoding`.
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
|
|
99
|
+
- `webmcp_list_tools` drops no annotation: `consequential` (the page
|
|
100
|
+
declares the tool has real-world effects, such as a payment) and
|
|
101
|
+
`debugging` were silently lost, and any annotation a later Chrome adds is
|
|
102
|
+
now passed through. The output of a tool annotated `untrustedContent` is
|
|
103
|
+
flagged: `webmcp_invoke_tool` adds a note to treat it as data, not as
|
|
104
|
+
instructions, and `webmcp_get_invocation` says `untrustedContent: true`.
|
|
105
|
+
- `evaluate_js` with an endless loop no longer kills the tab on Chrome:
|
|
106
|
+
the script is stopped after 8 s and the call says so ("the script ran for
|
|
107
|
+
more than 8 s ... the page keeps working"); later calls work at once. It
|
|
108
|
+
used to fail after 20 s with `Runtime.evaluate timed out`, and every
|
|
109
|
+
later call on the tab timed out too. An expression waiting on a promise
|
|
110
|
+
that never settles says so after 10 s. Firefox cannot stop a running
|
|
111
|
+
script from outside: its error says so and points to `close_tab`.
|
|
112
|
+
- On Firefox, a slow debugger call on one tab (e.g. a long
|
|
113
|
+
`evaluate_on_call_frame`) no longer blocks the logs and debugger tools of
|
|
114
|
+
the other tabs: each tab's debugger has its own lock (one lock covered
|
|
115
|
+
them all, delaying `get_console_logs` on another tab by 9.5 s).
|
|
116
|
+
- `get_custom_events` returns the newest `limit` events (it returned the
|
|
117
|
+
oldest, so new events never showed once the buffer held more), answers
|
|
118
|
+
pure JSON `{"events", "total", "truncated"}` (the text started with
|
|
119
|
+
`Found N custom events.`), and takes `clear` to remove what it returned.
|
|
120
|
+
- `get_network_logs`: on Chrome the page's own document is in its
|
|
121
|
+
navigation's bucket, so `current_navigation_only` lists it and its body
|
|
122
|
+
is returned (it was left in the previous navigation, without a body). A
|
|
123
|
+
failed request carries `error` (Chrome `net::ERR_...`, Firefox
|
|
124
|
+
`NS_ERROR_...`, also in the summary); it looked like one still waiting on
|
|
125
|
+
Chrome, and Firefox put the error in `response_status_text`. A binary body
|
|
126
|
+
says `response_body_encoding: "base64"`.
|
|
127
|
+
- On Chrome, `get_console_logs` and `get_network_logs` connect first: on an
|
|
128
|
+
instance nothing had connected to (an attached Chrome) they answered
|
|
129
|
+
empty buffers. The console messages the page logged before are now
|
|
130
|
+
returned; `get_network_logs` notes that earlier requests are not
|
|
131
|
+
captured.
|
|
132
|
+
|
|
13
133
|
## [0.3.4-beta.4] - 2026-10-27
|
|
14
134
|
|
|
15
135
|
Public **BETA**. The same server as 0.3.3-beta.4, which was published on
|
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.3.
|
|
14
|
+
> **Status: BETA (0.3.6-beta.6).** 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
|
|
@@ -49,15 +49,15 @@ see the note.
|
|
|
49
49
|
| `navigate` | ✓ | ✓ | |
|
|
50
50
|
| `reload` | ✓ | ✓ | |
|
|
51
51
|
| `scroll` | ✓ | ✓ | reports the window positions before and after |
|
|
52
|
-
| `inspect_dom` | ✓ | ✓ | at most 100 000 characters without `query` (cut in the page) |
|
|
53
|
-
| `capture_screenshot` | ✓ | ✓ | `full_page` at most 16 384 px per side (a text note says when cut) |
|
|
52
|
+
| `inspect_dom` | ✓ | ✓ | includes open shadow roots and same-origin iframes (cross-origin ones are noted); at most 100 000 characters without `query` (cut in the page) |
|
|
53
|
+
| `capture_screenshot` | ✓ | ✓ | `format` `png`, `jpeg` (or `jpg`) or `webp`; `full_page` at most 16 384 px per side (a text note says when cut) |
|
|
54
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;
|
|
55
|
+
| `fill_input` | ✓ | ✓ | picks `<select>` options; fails without typing on elements that cannot take the text; types key by key on both (key handlers run; newlines and tabs inserted as text), about 1 ms per character; `change` on leaving the field, or at the end when the window has no focus |
|
|
56
56
|
| `handle_dialog` | ✓ | ✓ | accepts or dismisses the open `alert` / `confirm` / `prompt` / `beforeunload` dialog |
|
|
57
|
-
| `evaluate_js` | ✓ | ✓ | `value` at most 100 000 characters (`truncated: true`) |
|
|
57
|
+
| `evaluate_js` | ✓ | ✓ | `value` at most 100 000 characters (`truncated: true`); Chrome stops a script after 8 s, Firefox cannot (a looping tab is closed with `close_tab`) |
|
|
58
58
|
| `get_console_logs` | ✓ | ✓ | a message keeps at most 10 000 characters; Firefox: page errors, CSS warnings and platform messages need the debugger port |
|
|
59
|
-
| `get_network_logs` | ✓ | ✓ | bodies at most 64 000 characters, none over 2 MB; a WebSocket payload keeps 64 000 (`payload_len` is the whole); Firefox: WebSocket frames need the debugger port |
|
|
60
|
-
| `get_custom_events` | ✓ | partial | params over 64 000 characters of JSON are replaced by `{truncated, characters}`; Firefox: events of the modules subscribed with `send_bidi_command` |
|
|
59
|
+
| `get_network_logs` | ✓ | ✓ | a failed request has `error`, a binary body `response_body_encoding: "base64"`; bodies at most 64 000 characters, none over 2 MB; a WebSocket payload keeps 64 000 (`payload_len` is the whole); Firefox: WebSocket frames need the debugger port |
|
|
60
|
+
| `get_custom_events` | ✓ | partial | `{events, total, truncated}`, the newest `limit` events; `clear` removes the returned ones; params over 64 000 characters of JSON are replaced by `{truncated, characters}`; Firefox: events of the modules subscribed with `send_bidi_command` |
|
|
61
61
|
| `get_performance_metrics` | ✓ | partial | Firefox: `Nodes`, `Frames`, `Resources`, `TransferSize` from the Web Performance APIs (no Performance domain), plus a note |
|
|
62
62
|
| `profile_page_performance` | ✓ | partial | Firefox: FCP, LCP, DCL and Load from the Web Performance APIs; no trace, so `total_blocking_time_ms` and `top_long_tasks` are `null` |
|
|
63
63
|
| `set_breakpoint` | ✓ | partial | Firefox: by URL only (no `script_id` / `script_hash`) |
|
|
@@ -68,11 +68,11 @@ see the note.
|
|
|
68
68
|
| `search_scripts` | ✓ | ✓ | a long line's preview is 100 characters on each side of the match |
|
|
69
69
|
| `pause_on_load` | ✓ | ✗ | TODO on Firefox, see [Limitations and TODO](#limitations-and-todo) |
|
|
70
70
|
| `enable_proxy_auth` | ✓ | partial | needs `--proxy-server`; a request the proxy rejects twice is cancelled; untested on Firefox against a real proxy |
|
|
71
|
-
| `send_cdp_command` | ✓ | ✗ | raw Chrome DevTools Protocol |
|
|
71
|
+
| `send_cdp_command` | ✓ | ✗ | raw Chrome DevTools Protocol; refuses `Network`/`Page`/`Runtime`/`Log`/`Debugger.disable` and `Browser.close`; `Fetch.enable` comes with a note |
|
|
72
72
|
| `send_bidi_command` | ✗ | ✓ | raw WebDriver BiDi; refuses `session.new`, `session.end`, `browser.close` |
|
|
73
73
|
| `send_rdp_request` | ✗ | ✓ | raw Firefox RDP request to an actor (`thread`, `console`, `root` shortcuts) |
|
|
74
|
-
| `webmcp_list_tools` | ✓ | ✗ | needs `--enable-webmcp`; WebMCP is a Chrome testing feature |
|
|
75
|
-
| `webmcp_invoke_tool` | ✓ | ✗ | needs `--enable-webmcp` |
|
|
74
|
+
| `webmcp_list_tools` | ✓ | ✗ | needs `--enable-webmcp`; WebMCP is a Chrome testing feature; every annotation Chrome reports is listed (`readOnly`, `consequential`, `untrustedContent`, `debugging`, `autosubmit`, newer ones as they are) |
|
|
75
|
+
| `webmcp_invoke_tool` | ✓ | ✗ | needs `--enable-webmcp`; the output of an `untrustedContent` tool comes with a note to treat it as data |
|
|
76
76
|
| `webmcp_get_invocation` | ✓ | ✗ | needs `--enable-webmcp` |
|
|
77
77
|
| `webmcp_list_invocations` | ✓ | ✗ | needs `--enable-webmcp` |
|
|
78
78
|
|
|
@@ -295,7 +295,11 @@ claude mcp add browser-control-mcp -- npx -y @raultov/browser-control-mcp
|
|
|
295
295
|
`null`, `node`, `date`, `map`...), `value` is the JSON form and is `null`
|
|
296
296
|
when there is none (functions, DOM nodes, symbols, `NaN`, bigints,
|
|
297
297
|
maps...), `description` then says what it was (Chrome describes functions
|
|
298
|
-
by their source, Firefox only as `function`).
|
|
298
|
+
by their source, Firefox only as `function`). An object or array's
|
|
299
|
+
`value` is what `JSON.stringify` gives, on both browsers (`toJSON` counts:
|
|
300
|
+
a `URL` is its `href`; nested functions drop out), and an object that is
|
|
301
|
+
not a plain one has its class in `description` (`navigator`:
|
|
302
|
+
`{"value": {}, "description": "Navigator"}`). A thrown exception or a
|
|
299
303
|
rejected promise fails with what was thrown and its 1-based line and
|
|
300
304
|
column, e.g. `ReferenceError: x is not defined (line 1, column 1)`.
|
|
301
305
|
A `value` over 100 000 characters is not returned whole: a string keeps
|
|
@@ -310,7 +314,11 @@ claude mcp add browser-control-mcp -- npx -y @raultov/browser-control-mcp
|
|
|
310
314
|
`{"messages": [...], "total", "truncated", "notes"?}`: at most `limit`
|
|
311
315
|
(default 200) of the most recent matching messages, oldest first; `clear`
|
|
312
316
|
removes only the returned ones; a note says when a site change cleared
|
|
313
|
-
messages.
|
|
317
|
+
messages. `get_custom_events` answers `{"events", "total", "truncated"}`
|
|
318
|
+
the same way. On Chrome both log tools connect first, so on an attached
|
|
319
|
+
browser the first call already sees the page's console messages (Chrome
|
|
320
|
+
replays them; network requests sent before the connection are not
|
|
321
|
+
captured, and the reply says so).
|
|
314
322
|
- **Firefox allows a single automation session.** Each Firefox instance holds
|
|
315
323
|
one WebDriver BiDi session shared by its tabs; `close_instance`,
|
|
316
324
|
`stop_browser` and every server shutdown path end it, so the next run can
|
|
@@ -441,6 +449,7 @@ incompatible:
|
|
|
441
449
|
| `remove_breakpoint` | Chrome: CDP id, reply `{}` | `bp-N` id, reply `{removed}` |
|
|
442
450
|
| `step_over`, `resume` | Chrome: text only; Firefox `step_over`: `{paused, location: {line (1-based), column}}` | `{paused, location: {url, line_number, column_number} \| null}`, 0-based |
|
|
443
451
|
| `evaluate_on_call_frame` | Chrome: raw `RemoteObject` (exceptions as success); Firefox: bare value | the `evaluate_js` shape; exceptions are errors (`Evaluation threw: ...`) |
|
|
452
|
+
| `get_custom_events` | `Found N custom events. Captured events: [...]`, the oldest events | `{events, total, truncated}`, the newest `limit` events; `clear` removes the returned ones |
|
|
444
453
|
| `get_console_logs` | a JSON array; `clear` emptied the whole buffer | `{messages, total, truncated, notes?}`, at most `limit` (200) messages; `clear` removes the returned ones; the buffer is cleared on cross-site navigation |
|
|
445
454
|
|
|
446
455
|
## Limitations and TODO
|
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.3.
|
|
22
|
+
"version": "0.3.6-beta.6"
|
|
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.3.
|
|
51
|
+
"version": "0.3.6-beta.6"
|
|
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.
|
|
3
|
+
"https://github.com/raultov/browser-control-mcp/releases/download/v0.3.6-beta.6"
|
|
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.3.
|
|
95
|
+
"version": "0.3.6-beta.6",
|
|
96
96
|
"volta": {
|
|
97
97
|
"node": "18.14.1",
|
|
98
98
|
"npm": "9.5.0"
|