@raultov/browser-control-mcp 0.4.0-beta.7 → 0.5.0-beta.8

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,68 @@ from a copy of its code: entries describe the differences from that release.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.5.0-beta.8] - 2026-10-31
14
+
15
+ Public **BETA**. Closes the rest of the Playwright MCP comparison: the new
16
+ `network` tool group mocks requests (`mock_route`, `list_routes`,
17
+ `remove_route`) and takes a tab offline (`set_offline`), `save_pdf` prints
18
+ a tab to PDF, and `--secrets` keeps known values out of what the agent
19
+ reads. Debugging a paused page works better: `evaluate_js` answers at once
20
+ on Chrome, a pause names its script, and the input tools fail at once
21
+ naming the pause instead of reporting a click or a text that has not
22
+ happened (a behaviour change: they used to "succeed").
23
+
24
+ ### Added
25
+
26
+ - `--secrets <file>` (dotenv): every tool result and error shows the
27
+ file's values as `<secret:NAME>` (as is or escaped in JSON), and
28
+ `fill_input` / `fill_form` type the value of a `<secret:NAME>` they are
29
+ given, so the agent can fill a password without reading it. A
30
+ convenience, not a security boundary: images are not masked and a page
31
+ can transform a value. Values never reach the logs. (#14)
32
+ - `save_pdf`, in the `files` tool group: prints the tab to PDF
33
+ (`landscape`, `print_background`, `scale`, `page_ranges`) and writes it to
34
+ `path`, an absolute `.pdf` under the upload roots, answering `{path,
35
+ bytes, pages}`; without `path` the PDF comes back as an embedded
36
+ `application/pdf` resource (at most 5 MB). Chrome `Page.printToPDF`,
37
+ Firefox `browsingContext.print`. (#13)
38
+ - `mock_route`, `list_routes`, `remove_route` and `set_offline`, in the new
39
+ `network` tool group (`--tool-groups network`). A route answers the tab's
40
+ requests whose URL matches a glob with a mocked status, body, content
41
+ type and headers, without reaching the network; the latest matching
42
+ route wins and `list_routes` counts its hits. Chrome uses the `Fetch`
43
+ domain (not while `enable_proxy_auth` is active), Firefox a
44
+ `beforeRequestSent` network intercept. `set_offline` takes the tab
45
+ offline or back online (Chrome still serves its HTTP cache). (#12)
46
+
47
+ ### Fixed
48
+
49
+ - The input tools (`click_element`, `hover`, `fill_input`, `fill_form`,
50
+ `press_key`) fail at once, naming the pause, when the page is already
51
+ paused in the debugger, and send nothing: the page handles input events
52
+ only once it resumes. Chrome reported a click or a key as done, and
53
+ both browsers blamed the field ("rejected the text") or, on Firefox, a
54
+ covering `html` element. (#17)
55
+ - On Chrome `evaluate_js` answers at once while the page is paused in the
56
+ debugger: it waited 10 s and failed with "no result after 10 s", even
57
+ for `1 + 1`, because Chrome cannot await an evaluation while no
58
+ microtask runs. It now evaluates without awaiting, reads a settled promise from
59
+ its state, and fails at once on a pending one, saying to `resume` or use
60
+ `evaluate_on_call_frame`. (#16)
61
+ - On Chrome a pause's location names its script: `resume`, `step_over`,
62
+ the `{paused, location}` of `click_element` and `press_key`, and the
63
+ "The page paused in the debugger at ..." message of an interrupted call
64
+ gave `url: null`, because Chrome leaves the deprecated
65
+ `callFrames[].url` empty. The URL now comes from the tab's parsed
66
+ scripts, and the location also carries `script_id` (what
67
+ `set_breakpoint` takes). (#10)
68
+
69
+ ### Changed
70
+
71
+ - The package description (crates.io, npm, Homebrew `desc`) is 79
72
+ characters instead of 213, within Homebrew's 80, so `brew style` no
73
+ longer flags the formula's `desc` line as too long.
74
+
13
75
  ## [0.4.0-beta.7] - 2026-10-31
14
76
 
15
77
  Public **BETA**. Closes the gaps a comparison with Playwright MCP showed:
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.4.0-beta.7).** This version contains known bugs and differences
14
+ > **Status: BETA (0.5.0-beta.8).** 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
@@ -37,10 +37,11 @@ tools are off by default and listed only with `--tool-groups`:
37
37
  | Group | Tools | Why it is opt-in |
38
38
  | --- | --- | --- |
39
39
  | `storage` | `cookies`, `web_storage` | reads and changes session tokens |
40
- | `files` | `upload_file` | hands a page files of the machine |
40
+ | `files` | `upload_file`, `save_pdf` | reads and writes files of the machine |
41
41
  | `raw` | `send_cdp_command`, `send_bidi_command`, `send_rdp_request`, `get_custom_events` | anything the protocol allows |
42
42
  | `perf` | `get_performance_metrics`, `profile_page_performance` | niche |
43
43
  | `emulation` | `emulate` | niche |
44
+ | `network` | `mock_route`, `list_routes`, `remove_route`, `set_offline` | changes what the page receives |
44
45
 
45
46
  `--tool-groups all` lists every group. The page, input, observation and
46
47
  debugger tools are always listed (33 tools), plus `enable_proxy_auth` with
@@ -73,6 +74,7 @@ see the note.
73
74
  | `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) |
74
75
  | `snapshot` | ✓ | ✓ | outline of the page: role, name, states, value and a ref (`e12`) per element, through open shadow roots and same-origin iframes; at most 50 000 characters (`selector` and `depth` narrow it); the same JavaScript on both browsers |
75
76
  | `find_in_snapshot` | ✓ | ✓ | `text` (case-insensitive) or `regex` over the whole outline; matching lines under their ancestors, at most 20 |
77
+ | `save_pdf` | ✓ | ✓ | `files` group; prints the tab as the browser's print does (`landscape`, `print_background`, `scale` 0.1–2, `page_ranges` like `1-3, 5`); with `path` (an absolute `.pdf` under the upload roots) writes the file and answers `{path, bytes, pages}`, else returns the PDF as an embedded `application/pdf` resource (at most 5 MB); Chrome `Page.printToPDF`, Firefox `browsingContext.print` |
76
78
  | `capture_screenshot` | ✓ | ✓ | `format` `png`, `jpeg` (or `jpg`) or `webp`; `full_page` at most 16 384 px per side (a text note says when cut) |
77
79
  | `click_element` | ✓ | ✓ | scrolls the element into view; `button` (left/right/middle), `click_count` (2 = double click) and `modifiers`; fails without clicking when it is hidden or covered; `host >>> inner` selectors reach open shadow roots and same-origin iframes (also in `fill_input`, `scroll`, `wait_for`); a dialog or debugger pause the click causes is noted in a successful reply (`{dialog}` or `{paused, location}`) |
78
80
  | `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 |
@@ -86,6 +88,10 @@ see the note.
86
88
  | `web_storage` | ✓ | ✓ | `storage` group; `get` / `set` / `delete` / `clear` on the page's `localStorage` or `sessionStorage`; values hidden unless `show_values: true` |
87
89
  | `get_console_logs` | ✓ | ✓ | a message keeps at most 10 000 characters; Firefox: page errors, CSS warnings and platform messages need the debugger port |
88
90
  | `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 |
91
+ | `mock_route` | ✓ | ✓ | `network` group; requests whose URL matches a glob (`*`, `?`, `\` escapes) get a mocked `status`, `body` (text, at most 1 MB), `content_type` and `headers` without reaching the network; the latest matching route wins; at most 50 routes per tab, kept until `remove_route` or the tab closes (Chrome `Fetch`, not while `enable_proxy_auth` is active; Firefox a `network` intercept) |
92
+ | `list_routes` | ✓ | ✓ | `network` group; the tab's routes with the `hits` each answered |
93
+ | `remove_route` | ✓ | ✓ | `network` group; one route by id, or all |
94
+ | `set_offline` | ✓ | ✓ | `network` group; requests fail as without a network and `navigator.onLine` is false, until set back (Chrome `Network.emulateNetworkConditions`, Firefox `emulation.setNetworkConditions`); mocked routes still answer; Chrome still serves what its HTTP cache holds, as an offline browser does, Firefox fails every request |
89
95
  | `get_custom_events` | ✓ | partial | `raw` group; `{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` |
90
96
  | `get_performance_metrics` | ✓ | partial | `perf` group; Firefox: `Nodes`, `Frames`, `Resources`, `TransferSize` from the Web Performance APIs (no Performance domain), plus a note |
91
97
  | `profile_page_performance` | ✓ | partial | `perf` group; Firefox: FCP, LCP, DCL and Load from the Web Performance APIs; no trace, so `total_blocking_time_ms` and `top_long_tasks` are `null` |
@@ -379,8 +385,9 @@ claude mcp add browser-control-mcp -- npx -y @raultov/browser-control-mcp
379
385
  | `--enable-automation` | off | shows the automation infobar | ignored; `list_instances` shows a warning |
380
386
  | `--user-profile` | off | your default profile (no `--user-data-dir`) | only with `--firefox-port` (attach to your running Firefox) |
381
387
  | `--allow-cookie-import` | off | exposes `copy_cookies` | capability error |
382
- | `--tool-groups <GROUPS>` | none | lists the opt-in tool groups, comma separated: `storage`, `files`, `raw`, `perf`, `emulation` or `all` (see [Tool groups](#tool-groups)) | same |
383
- | `--upload-root <DIR>` | working + temp dir | directory `upload_file` may read files from (repeatable; replaces the defaults) | same |
388
+ | `--secrets <FILE>` | none | dotenv file (`NAME=value`, at least 4 characters per value) whose values every tool result and error shows as `<secret:NAME>`; `fill_input` and `fill_form` type the value of a `<secret:NAME>` (see [Security notes](#security-notes)) | same |
389
+ | `--tool-groups <GROUPS>` | none | lists the opt-in tool groups, comma separated: `storage`, `files`, `raw`, `perf`, `emulation`, `network` or `all` (see [Tool groups](#tool-groups)) | same |
390
+ | `--upload-root <DIR>` | working + temp dir | directory `upload_file` may read files from and `save_pdf` may write PDFs to (repeatable; replaces the defaults) | same |
384
391
  | `--enable-webmcp` | off | WebMCP switches and `webmcp_*` tools | capability error |
385
392
  | `--proxy-server <URL>` | none | proxy for every instance; exposes `enable_proxy_auth` | `http://` and `socks5://` proxies |
386
393
  | `--proxy-username <USER>` | none | answers proxy (407) challenges | same (untested) |
@@ -441,7 +448,13 @@ Chrome and Firefox take the same calls:
441
448
  unfinished (`evaluate_js`, `fill_input`, `navigate`...) fails at once
442
449
  with that location.
443
450
  5. `evaluate_on_call_frame` reads locals of the paused frame; `step_over`
444
- moves one statement; `resume` continues.
451
+ moves one statement; `resume` continues. While paused, the input tools
452
+ (`click_element`, `hover`, `fill_input`, `fill_form`, `press_key`) fail
453
+ at once naming the pause and do nothing: the page would handle their
454
+ events only after `resume`. `evaluate_js` still answers
455
+ while paused, in the page's global scope. A promise it returns cannot
456
+ always settle meanwhile: Chrome reads a settled one and fails at once on
457
+ a pending one; Firefox settles it when its microtasks can run.
445
458
  6. `remove_breakpoint` with the id `set_breakpoint` returned.
446
459
 
447
460
  Both browsers answer the same replies, with 0-based lines everywhere:
@@ -450,7 +463,7 @@ Both browsers answer the same replies, with 0-based lines everywhere:
450
463
  | --- | --- |
451
464
  | `set_breakpoint` | `{"breakpoint_id": "bp-N", "url", "line_number", "column_number", "resolved"}`: where the browser bound it; `resolved` is false until a script with that URL loads |
452
465
  | `remove_breakpoint` | `{"removed": "bp-N"}`; an unknown id fails listing the tab's ids |
453
- | `step_over`, `resume` | `{"paused", "location": {"url", "line_number", "column_number"} \| null}`: where the thread stopped next (`step_over` waits up to 2 s; `resume` reports a pause only if one follows within 250 ms) |
466
+ | `step_over`, `resume` | `{"paused", "location": {"url", "script_id"?, "line_number", "column_number"} \| null}`: where the thread stopped next (`script_id` on Chrome, for `set_breakpoint`) (`step_over` waits up to 2 s; `resume` reports a pause only if one follows within 250 ms) |
454
467
  | `evaluate_on_call_frame` | the `evaluate_js` shape; an exception fails with `Evaluation threw: <what was thrown>` |
455
468
 
456
469
  Breakpoint ids are per tab and MCP-level (`bp-1`, `bp-2`...), like tab ids.
@@ -558,6 +571,19 @@ incompatible:
558
571
  the upload roots (the server's working directory and the system temp
559
572
  directory, or the `--upload-root` directories), resolved so `..` and
560
573
  symlinks cannot leave them. Paths are never logged.
574
+ - `--secrets <file>` keeps known values (test passwords, API keys) out of
575
+ what the agent reads: every tool result and error (text, embedded text,
576
+ structured content) shows them as `<secret:NAME>`, also when escaped
577
+ inside JSON, and `fill_input` / `fill_form` type the value of a
578
+ `<secret:NAME>` they are given, so the agent can log in without seeing
579
+ the password. It is a convenience, not a security boundary: the page can
580
+ transform a value (encode it, split it) past the masking, images
581
+ (screenshots, PDFs) are not masked, and the server stops at start-up if
582
+ the file has a malformed line, a value shorter than 4 characters or a
583
+ name defined twice (the error names the line, never a value). Values
584
+ never reach the logs.
585
+ - `save_pdf` writes only `.pdf` files, under the same upload roots and
586
+ resolved the same way; it overwrites an existing `.pdf` there.
561
587
  - The proxy password is never logged and is given only to proxy (407)
562
588
  challenges, never to a site's own authentication.
563
589
  - The Firefox debugger port needs `devtools.chrome.enabled`: any local
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT",
21
21
  "name": "@raultov/browser-control-mcp",
22
- "version": "0.4.0-beta.7"
22
+ "version": "0.5.0-beta.8"
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.4.0-beta.7"
51
+ "version": "0.5.0-beta.8"
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.4.0-beta.7"
3
+ "https://github.com/raultov/browser-control-mcp/releases/download/v0.5.0-beta.8"
4
4
  ],
5
5
  "author": "raultov <raultov@protonmail.com>",
6
6
  "bin": {
@@ -9,7 +9,7 @@
9
9
  "dependencies": {
10
10
  "detect-libc": "^2.1.2"
11
11
  },
12
- "description": "MCP server to control and debug Chrome and Firefox at runtime: breakpoints, call frames and stepping over CDP and WebDriver BiDi/RDP, plus navigation, DOM, input, screenshots, console and network capture.",
12
+ "description": "MCP server to control and debug Chrome and Firefox, with JavaScript breakpoints",
13
13
  "devDependencies": {
14
14
  "prettier": "^3.8.3"
15
15
  },
@@ -92,7 +92,7 @@
92
92
  "zipExt": ".tar.xz"
93
93
  }
94
94
  },
95
- "version": "0.4.0-beta.7",
95
+ "version": "0.5.0-beta.8",
96
96
  "volta": {
97
97
  "node": "18.14.1",
98
98
  "npm": "9.5.0"