@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 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.2.0-beta.2).** This version contains known bugs and differences
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`, ...) are
483
- redacted in `get_network_logs` unless `include_sensitive_headers: true`.
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
 
@@ -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.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.2.0-beta.2"
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.2.0-beta.2"
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.2.0-beta.2",
95
+ "version": "0.3.0-beta.3",
96
96
  "volta": {
97
97
  "node": "18.14.1",
98
98
  "npm": "9.5.0"