@raultov/browser-control-mcp 0.2.0-beta.2 → 0.3.1-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 CHANGED
@@ -10,6 +10,201 @@ from a copy of its code: entries describe the differences from that release.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.3.1-beta.3] - 2026-10-25
14
+
15
+ Public **BETA**. Size limits: large pages, results, scripts, logs and
16
+ screenshots no longer flood the agent or drop the browser connection, and
17
+ Chrome reconnects by itself when a reply over 16 MB drops it. Some replies
18
+ change (cut texts end with a `[cut: ...]` or `[Truncated: ...]` note,
19
+ `evaluate_js` may say `truncated: true`, `inspect_dom` positions are
20
+ characters).
21
+
22
+ ### Fixed
23
+
24
+ - `capture_screenshot` with `full_page` captures at most 16 384 CSS pixels
25
+ per side, from the top left, and then adds a text note naming the
26
+ document's size (a 30 000 px page came back whole).
27
+ - Observation buffers keep a bounded copy of each item: a console message
28
+ keeps 10 000 characters, a WebSocket payload 64 000 (`payload_len` is
29
+ the whole length), custom event params over 64 000 characters of JSON
30
+ become `{"truncated": true, "characters": N}`, and `get_network_logs`
31
+ shows at most 64 000 characters of a request or response body. Each cut
32
+ text ends with `… [cut: the first N of M characters]`. Chrome no longer
33
+ fetches a response body whose `Content-Length` is over 2 MB (Firefox
34
+ keeps none larger). Two 3 MB console messages made a 6 MB reply.
35
+ - `search_scripts` previews a long line (minified code) as the match with
36
+ 100 characters on each side, `…` where it was cut: one hit in a 1.6 MB
37
+ one-line script returned the whole line.
38
+ - `evaluate_js` returns at most 100 000 characters of `value`: a longer
39
+ string is cut, and an object or array whose JSON form is longer is
40
+ measured in the page and only described ("too large to return (N
41
+ characters of JSON)"), so it never crosses the connection; the reply
42
+ says `"truncated": true`. A 3-million-element array used to time out on
43
+ Firefox and a 20 MB object to drop the connection. A string result over
44
+ 16 MB still drops it (the next call reconnects).
45
+ - `inspect_dom` searches and cuts in the page, so a large document no
46
+ longer crosses the connection (a 20 MB page used to drop it on Chrome).
47
+ Without `query` it returns at most 100 000 characters, after a
48
+ `[Truncated: ...]` note naming the total; `before`/`after` are capped at
49
+ 10 000. Positions are characters (they were bytes). On Chrome an
50
+ exception in the page is an error (it was an empty success).
51
+ - A reply over 16 MB (a huge `evaluate_js` result, a 20 MB page in
52
+ `inspect_dom`) makes the browser close the DevTools connection. Chrome
53
+ then answered `CDP Error: Connection lost` to every later call until
54
+ `restart_browser`; now the next call reconnects by itself (tab ids are
55
+ re-assigned). The failing call explains what happened on both browsers.
56
+
57
+ ## [0.3.0-beta.3] - 2026-10-25
58
+
59
+ Public **BETA**. Result of a tool-by-tool audit on real Chrome and Firefox:
60
+ tools that reported success for an action that did not happen now fail or
61
+ say what happened, secrets no longer leak into logs or replies, and a new
62
+ `handle_dialog` tool closes JavaScript dialogs. Some replies change (marked
63
+ in the entries below: `scroll`, `fill_input`, `click_element` errors,
64
+ Chrome `open_tab` ids).
65
+
66
+ ### Added
67
+
68
+ - `handle_dialog` (both browsers): accepts or dismisses the JavaScript
69
+ dialog (`alert`, `confirm`, `prompt` with `prompt_text`, `beforeunload`)
70
+ open on a tab, and replies with its type and message.
71
+
72
+ ### Changed
73
+
74
+ - Chrome: when the first call on an instance is `open_tab`, the browser's
75
+ own first page is now registered too (as on Firefox), so the new tab is
76
+ `tab-2` and stays inactive until `switch_tab`; before, it was `tab-1` and
77
+ active.
78
+
79
+ ### Fixed
80
+
81
+ - Chrome tracks popups (`window.open`) and tabs closed by the page or the
82
+ user when the first call on an instance is `open_tab`; it only did after
83
+ a call that used the instance's default page.
84
+ - `navigate` and `reload` keep their 30 s budget on slow pages (both
85
+ browsers). A server slow to answer, or a page slow to fire `load`, hit
86
+ the 10 s protocol command timeout and failed although the navigation went
87
+ on; now the call waits for `load` up to 30 s from its start and answers
88
+ then, with the not-loaded note when it did not come.
89
+ - `get_network_logs` `clear: true` removes only the requests and frames it
90
+ returned (with `url_filter`, `type_filter` or `current_navigation_only`
91
+ it used to empty everything, also what was never returned), as
92
+ `get_console_logs` does. WebSocket connections keep their URL after a
93
+ clear (later frames used to have `url: ""`).
94
+ - Chrome `pause_on_load` no longer leaves its `debugger;` script injected
95
+ (after which every later load paused): calling it again replaces the
96
+ previous script, and a `resume` Chrome refuses because the reload has not
97
+ paused yet keeps the script pending, so the next `resume` removes it.
98
+ - JavaScript dialogs no longer hang the tools. A call during which the page
99
+ opens a dialog (`evaluate_js` running `alert()`, a `click_element` on a
100
+ button that asks `confirm()`, a `navigate` stopped by `beforeunload`)
101
+ fails at once quoting the dialog instead of after a 10–20 s timeout, and
102
+ while a dialog is open the page tools fail naming it and pointing to
103
+ `handle_dialog`. On Chrome the tab used to stay blocked until a raw
104
+ `Page.handleJavaScriptDialog`. Chrome errors are worded with the
105
+ protocol's message instead of Rust debug output (`Timeout { method: ...
106
+ }`).
107
+
108
+ - Security: with `RUST_LOG=trace` the MCP transport logged every incoming
109
+ tool call in full, including the `enable_proxy_auth` password and raw
110
+ protocol params. Its logs are now capped at `info`, like `cdp-lite`'s.
111
+ - Security: copies of the user's cookies (`copy_cookies`) could stay in the
112
+ temp directory: when a launch failed, when a seed was replaced before
113
+ use, when a browser failed to stop, when a partial copy failed, and at
114
+ shutdown after the seeded Chrome had crashed. The seeded profile now
115
+ deletes itself whenever it is dropped, and shutdown drops the seed of an
116
+ instance that is no longer running.
117
+ - Security: `get_network_logs` returned request bodies (login forms with
118
+ passwords, token exchanges) and API-key headers such as `X-Api-Key` in
119
+ full by default. Request bodies and every header whose name contains
120
+ `token`, `secret`, `api-key`, `apikey`, `password`, `session`, `csrf` or
121
+ `xsrf` are now `<redacted>` unless `include_sensitive_headers: true`.
122
+ - `search_scripts` positions are right, so they can be passed to
123
+ `set_breakpoint` as they are. A match at the start of a line was reported
124
+ at the end of the previous line (both browsers); matches in inline scripts
125
+ were counted from the script, not the page (Chrome); columns now count
126
+ UTF-16 units, as the browsers do, instead of bytes.
127
+ - Firefox `set_breakpoint` no longer sets breakpoints that never fire. A
128
+ `column_number` Firefox cannot break on (it ignores those silently) moves
129
+ to the next breakable column of the line once the script is loaded, as on
130
+ Chrome, and the reply says where; a column past every breakable one is an
131
+ error. A second breakpoint at the same location is refused naming the
132
+ first: Firefox keeps one per location, so removing either id used to
133
+ remove both.
134
+ - Firefox `evaluate_js` no longer changes the type of nested values: `NaN`
135
+ and `±Infinity` inside objects and arrays were strings (`"NaN"`), `-0`
136
+ was `"-0"`, a BigInt was a string of digits, `undefined` was `null` in
137
+ objects and a cycle was `{}`. Nested values now follow JSON as on Chrome
138
+ (`null`, `0`, `undefined` left out); an object holding a BigInt or a
139
+ cycle has no JSON form and is described (`"Object"`, `value: null`), and
140
+ an object reached twice without a cycle is serialised both times.
141
+ - `webmcp_list_tools` no longer hides page tools registered without an
142
+ `inputSchema` (optional in WebMCP); they are listed without one and can
143
+ be invoked.
144
+ - Chrome `restart_browser` without `proxy_server` keeps the instance's own
145
+ proxy (the one given to `open_instance` or the previous restart), as on
146
+ Firefox; it used to fall back to `--proxy-server`, or none, silently.
147
+ - `get_console_logs`: `console.warn` is level `warning` on Firefox too (it
148
+ was `warn`, so `level_filter: "warning"` found nothing there and `"warn"`
149
+ nothing on Chrome); `level_filter` accepts `warn` as an alias.
150
+ - Chrome: the first call on a fresh instance (usually `navigate`) waits
151
+ for the browser's page to register as a tab and uses it. It used to run
152
+ on a session-level connection whose captured state stopped being read
153
+ once the tab registered a moment later, so the first page's network
154
+ requests were missing from `get_network_logs` and `search_scripts` found
155
+ nothing right after it.
156
+ - Chrome `enable_proxy_auth` no longer stops answering after falling behind
157
+ a burst of events (it left request interception on with nobody
158
+ continuing the tab's requests, so they hung); whatever ends the handler
159
+ turns interception off. It also subscribes before enabling interception,
160
+ so a request paused right away is not missed.
161
+ - A browser that crashed or was killed from outside is reported: every call
162
+ on that instance answers "The browser of this instance closed or crashed
163
+ ... Call 'restart_browser'", its dead tabs are forgotten, and nothing is
164
+ relaunched behind the agent's back. Chrome used to answer `CDP Error:
165
+ Disconnected` forever while silently starting an unused new Chrome (and
166
+ leaking the dead one's pool entry); Firefox answered "the browser was
167
+ stopped" forever. `restart_browser`, `stop_browser` and `close_instance`
168
+ work as usual afterwards. Chrome `open_tab` checks `--local` before it
169
+ starts a browser.
170
+ - A page's own `debugger;` statements no longer pause it while the tab has
171
+ no breakpoint (and, on Chrome, no `pause_on_load`). The debugger is
172
+ always attached, so anti-debugging pages (`setInterval(() => {debugger})`)
173
+ and a stray `debugger;` froze every tool on the tab until a timeout. The
174
+ first breakpoint turns them back on, removing the last one turns them off
175
+ (Chrome `Debugger.setSkipAllPauses`, re-applied after cross-process
176
+ navigations; Firefox `shouldPauseOnDebuggerStatement`). Chrome's
177
+ session-level connection drops its debugger once the page is a
178
+ registered tab, so it no longer resumes the tab's pauses.
179
+ - `fill_input` no longer types into the wrong element or reports a fill
180
+ that did not happen (both browsers). An element that cannot take the text
181
+ (a plain element, disabled, read-only, a non-text input such as a
182
+ checkbox, or one that cannot take focus) fails with the reason and nothing
183
+ is typed; before, the text went to whichever element had focus. A
184
+ `<select>` gets the option whose value or label equals the text (it used
185
+ to be emptied on Chrome). After typing, a field left empty (it rejected the
186
+ text, e.g. letters in a number field) is an error, and a field holding
187
+ something else (a mask, `maxlength`) succeeds with a note; the text is
188
+ never echoed back. The field is emptied through the native `value` setter,
189
+ which React-controlled inputs observe. On Chrome, an invalid selector
190
+ reports its `SyntaxError` instead of "Element not found". The description
191
+ no longer promises a `change` event: it fires when the field loses focus,
192
+ as for a user.
193
+ - `click_element` no longer reports a click that hit another element or
194
+ nothing (both browsers). The element is scrolled into view first (Chrome
195
+ used to click off-screen coordinates into the void; Firefox failed with
196
+ "move target out of bounds"), and the call fails without clicking when it
197
+ has no visible box (Chrome used to click the page corner at (0, 0)) or
198
+ when another element covers the point, naming it (an overlay used to get
199
+ the click on both). Both browsers click the same checked viewport point;
200
+ Firefox no longer leaves the pointer pressed when its actions fail.
201
+ - `scroll` no longer reports success when nothing moved (both browsers). The
202
+ reply adds the window positions as JSON `{before, after}` (plus
203
+ `element_in_view` for a selector) after its first line, which says why the
204
+ window did not move when it did not (at the edge, or the page scrolls an
205
+ inner element). Scrolling to a hidden element fails. `x` is no longer
206
+ dropped when scrolling by `pages`.
207
+
13
208
  ## [0.2.0-beta.2] - 2026-10-14
14
209
 
15
210
  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.2.0-beta.2).** This version contains known bugs and differences
14
+ > **Status: BETA (0.3.1-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,15 +48,16 @@ see the note.
48
48
  | `switch_tab` | ✓ | ✓ | |
49
49
  | `navigate` | ✓ | ✓ | |
50
50
  | `reload` | ✓ | ✓ | |
51
- | `scroll` | ✓ | ✓ | |
52
- | `inspect_dom` | ✓ | ✓ | |
53
- | `capture_screenshot` | ✓ | ✓ | |
54
- | `click_element` | ✓ | ✓ | |
55
- | `fill_input` | ✓ | ✓ | |
56
- | `evaluate_js` | ✓ | ✓ | |
57
- | `get_console_logs` | ✓ | ✓ | Firefox: page errors, CSS warnings and platform messages need the debugger port |
58
- | `get_network_logs` | ✓ | ✓ | Firefox: WebSocket frames need the debugger port |
59
- | `get_custom_events` | ✓ | partial | Firefox: events of the modules subscribed with `send_bidi_command` |
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) |
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 |
57
+ | `evaluate_js` | ✓ | ✓ | `value` at most 100 000 characters (`truncated: true`) |
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` |
60
61
  | `get_performance_metrics` | ✓ | partial | Firefox: `Nodes`, `Frames`, `Resources`, `TransferSize` from the Web Performance APIs (no Performance domain), plus a note |
61
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` |
62
63
  | `set_breakpoint` | ✓ | partial | Firefox: by URL only (no `script_id` / `script_hash`) |
@@ -64,7 +65,7 @@ see the note.
64
65
  | `resume` | ✓ | ✓ | |
65
66
  | `step_over` | ✓ | ✓ | |
66
67
  | `evaluate_on_call_frame` | ✓ | ✓ | |
67
- | `search_scripts` | ✓ | ✓ | |
68
+ | `search_scripts` | ✓ | ✓ | a long line's preview is 100 characters on each side of the match |
68
69
  | `pause_on_load` | ✓ | ✗ | TODO on Firefox, see [Limitations and TODO](#limitations-and-todo) |
69
70
  | `enable_proxy_auth` | ✓ | partial | needs `--proxy-server`; untested on Firefox against a real proxy |
70
71
  | `send_cdp_command` | ✓ | ✗ | raw Chrome DevTools Protocol |
@@ -291,6 +292,9 @@ claude mcp add browser-control-mcp -- npx -y @raultov/browser-control-mcp
291
292
  by their source, Firefox only as `function`). A thrown exception or a
292
293
  rejected promise fails with what was thrown and its 1-based line and
293
294
  column, e.g. `ReferenceError: x is not defined (line 1, column 1)`.
295
+ A `value` over 100 000 characters is not returned whole: a string keeps
296
+ its first 100 000, an object or array is measured in the page and only
297
+ described; the reply then carries `"truncated": true`.
294
298
  - **Per-tab state.** Console logs, network traffic, breakpoints and custom
295
299
  events are kept per tab, in bounded buffers. A tab's console buffer (last
296
300
  1000 messages) is cleared when the tab moves to another site (registrable
@@ -383,6 +387,11 @@ Both browsers answer the same replies, with 0-based lines everywhere:
383
387
 
384
388
  Breakpoint ids are per tab and MCP-level (`bp-1`, `bp-2`...), like tab ids.
385
389
 
390
+ While a tab has no breakpoint (and, on Chrome, no pending `pause_on_load`),
391
+ the page's own `debugger;` statements do not pause it: the debugger is
392
+ always attached, and anti-debugging pages loop on `debugger;` to freeze
393
+ every tool. The first breakpoint turns them back on.
394
+
386
395
  Chrome also offers `pause_on_load` (pause on the first statement of the next
387
396
  load). Firefox notes: breakpoints by URL only; without `column_number` the
388
397
  breakpoint binds to the first breakable column of the line, in whichever of
@@ -479,8 +488,11 @@ incompatible:
479
488
  - The Firefox debugger port needs `devtools.chrome.enabled`: any local
480
489
  process that reaches that port gets chrome (privileged) access to the
481
490
  browser. Use `--no-firefox-debugger` when you do not need the debugger.
482
- - Credential headers (`Authorization`, `Cookie`, `Set-Cookie`, ...) are
483
- redacted in `get_network_logs` unless `include_sensitive_headers: true`.
491
+ - Credential headers (`Authorization`, `Cookie`, `Set-Cookie`, and any
492
+ header whose name contains `token`, `secret`, `api-key`, `password`,
493
+ `session` or `csrf`) and request bodies are redacted in
494
+ `get_network_logs` unless `include_sensitive_headers: true`. URLs and
495
+ response bodies are returned as they are.
484
496
  - Logs carry tool names, ids, protocol method names and sizes, never
485
497
  payloads, cookies or URLs with queries.
486
498
 
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT",
21
21
  "name": "@raultov/browser-control-mcp",
22
- "version": "0.2.0-beta.2"
22
+ "version": "0.3.1-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.2.0-beta.2"
51
+ "version": "0.3.1-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.2.0-beta.2"
3
+ "https://github.com/raultov/browser-control-mcp/releases/download/v0.3.1-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.2.0-beta.2",
95
+ "version": "0.3.1-beta.3",
96
96
  "volta": {
97
97
  "node": "18.14.1",
98
98
  "npm": "9.5.0"