@raultov/browser-control-mcp 0.5.0-beta.8 → 0.6.0-beta.10

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,111 @@ from a copy of its code: entries describe the differences from that release.
10
10
 
11
11
  ## [Unreleased]
12
12
 
13
+ ## [0.6.0-beta.10] - 2026-10-31
14
+
15
+ Public **BETA**. Fixes four input and snapshot bugs found while driving a
16
+ real web app (Discord): `fill_input` now types into rich text editors
17
+ (Slate, Lexical, ProseMirror) so the editor records the edit, styled
18
+ checkboxes covered by their own label are clicked, controls shown only on
19
+ hover are revealed and clicked, and `snapshot` lists the links and buttons
20
+ inside a clickable container. Behaviour change: a covered element now gets
21
+ a mouse move before the click is refused.
22
+
23
+ ### Fixed
24
+
25
+ - `click_element`, `hover` and `fill_form` reach controls shown only while
26
+ the mouse is over something (a message's actions, a row's toolbar): a
27
+ covered element now gets the mouse first and is checked again 100 ms
28
+ later. Discord's message "More" button failed with "covered by
29
+ 'div.message…'". An element that stays covered still fails, naming what
30
+ covers it, without a click. (#26)
31
+ - `snapshot` and `find_in_snapshot` list what a clickable container holds:
32
+ an element without a role that has a click handler or a pointer cursor
33
+ was a leaf named from its whole text, so a container that sets
34
+ `cursor: pointer` hid every link and button inside it (Discord's whole
35
+ channel list was one line). A clickable that holds interactive elements
36
+ now lists them; one with text only is still one named line. (#25)
37
+ - `click_element`, `hover` and `fill_form` click a control covered by its
38
+ own label (or the element its `aria-labelledby` names), as styled
39
+ checkboxes and switches are: they failed with "covered by 'span…'". An
40
+ element under anything else still fails, naming it. (#24)
41
+ - `fill_input` and `fill_form` work in rich text editors (Slate, Lexical,
42
+ ProseMirror, Draft.js): a contenteditable element was emptied with
43
+ `textContent = ''`, which removed the nodes the editor renders from its
44
+ own model, so the typed text showed in the page but the editor did not
45
+ record it (Discord's channel topic was never saved), and the tool
46
+ reported success. The content is now selected and the first typed key
47
+ replaces it, as when a user selects all and types; an empty text deletes
48
+ it through the editing commands. (#23)
49
+
50
+ ## [0.6.0-beta.9] - 2026-10-31
51
+
52
+ Public **BETA**. Spends fewer tokens and answers what the agent needs, after
53
+ a side-by-side study with Playwright MCP and chrome-devtools-mcp (now in the
54
+ README): `get_network_logs` and `get_console_logs` answer one line per entry
55
+ (details on demand), `snapshot` no longer repeats table text, input actions
56
+ wait for the page to settle, and `profile_page_performance` explains its
57
+ numbers with `insights`. Behaviour changes: the two log tools answer text
58
+ instead of JSON unless `include_details: true`, layout tables leave only
59
+ their content in `snapshot`, and input actions take ~50 ms more when the
60
+ page does not react.
61
+
62
+ ### Added
63
+
64
+ - `profile_page_performance` takes `insights: true`: what explains the
65
+ numbers, read in the page with the Web Performance APIs on both browsers:
66
+ the document's TTFB, server time and compression, the LCP element with
67
+ its breakdown (TTFB, load delay, load, render delay), layout-shift
68
+ culprits, render-blocking requests, the slowest requests and the scripts
69
+ of long animation frames (at most 5 each), and `findings` from the web.dev
70
+ thresholds (LCP over 2.5 s, CLS over 0.1, a slow server, an uncompressed
71
+ document, render-blocking requests). Firefox reports no layout shifts,
72
+ render-blocking status or long frames: those are `null`, with notes. The
73
+ reply grows from ~60 to ~600-700 tokens on Wikipedia. (#22)
74
+
75
+ ### Changed
76
+
77
+ - `click_element`, `hover`, `fill_input`, `fill_form` and `press_key` wait
78
+ for the page to settle before answering: until the DOM stays unchanged for
79
+ 50 ms (style changes aside) and the requests the action started finished,
80
+ at most 1 s, on both browsers. They answered in 1-2 ms, before the page
81
+ reacted, so a read right after a click that fetches data saw the old page.
82
+ An action nothing reacts to now takes ~50 ms and keeps its reply; one the
83
+ page reacts to adds how (`The page reacted (the DOM changed, 1 request(s))
84
+ and settled after 134 ms.`), or that it was still changing after 1 s. Not
85
+ done when the action left a dialog open or the page paused. (#21)
86
+ - `snapshot` and `find_in_snapshot` no longer print a table's text two or
87
+ three times. A table without headers (`th`, `thead`, `caption`,
88
+ `summary`) and without a role is layout: its `table`, `row` and `cell`
89
+ lines are left out and only their content stays, as in Chrome's
90
+ accessibility tree. A cell is named by its content only when that content
91
+ is plain text (folded into the name, up to 100 characters); a cell with
92
+ links or controls keeps them as children, unnamed. Hacker News went from
93
+ ~8 500 to ~4 500 tokens. (#20)
94
+ - `get_console_logs` answers one line per message by default: `[level]
95
+ text @ url:line` (lines from 1), repeats in a row folded (`[x3]`),
96
+ uncaught errors marked (`Uncaught ...`) with up to 5 stack lines
97
+ indented; `include_details: true` keeps the previous JSON. A page with
98
+ six messages went from ~550 to ~150 tokens. (#19)
99
+ - `get_network_logs` answers one line per request by default (`id METHOD
100
+ url => status [type]`, oldest first), then one per WebSocket frame with a
101
+ payload preview: ~100 tokens for a page of four requests instead of ~2 250.
102
+ The new `request_id` shows one request's headers and body;
103
+ `include_details: true` (now off by default) keeps the previous JSON with
104
+ every request's details. (#18)
105
+
106
+ ### Fixed
107
+
108
+ - `get_console_logs` previews objects and arrays as the console shows
109
+ them (`hello {n: 1, s: 'x'} [1, 2, 3]`): Chrome printed `Object`, Firefox
110
+ `Object(3) Array(3)`. On Chrome a `console.*` call keeps its location
111
+ (`url`, `line_number`), which was always empty, and `undefined`
112
+ arguments are printed. (#19)
113
+ - `get_network_logs` no longer lists the browser's own requests: a freshly
114
+ launched Chrome logged its new-tab page (`chrome://resources/...`, `data:`
115
+ images) before the first navigation. `chrome://`, `devtools://`, `data:`,
116
+ `about:` and extension URLs are not logged. (#18)
117
+
13
118
  ## [0.5.0-beta.8] - 2026-10-31
14
119
 
15
120
  Public **BETA**. Closes the rest of the Playwright MCP comparison: the new
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # browser-control-mcp
2
2
 
3
+ [![Discord](https://img.shields.io/discord/1566088811354656778?label=Discord&logo=discord)](https://discord.gg/JDfcmD73A)
4
+
3
5
  **Browser Control MCP** lets an AI agent control **and debug** real browsers
4
6
  at runtime: breakpoints, pause on load, call frames, evaluation in a paused
5
7
  frame, stepping and script search on **Chrome (CDP)** and **Firefox
@@ -11,12 +13,62 @@ It is the successor of
11
13
  from a copy of its code) and complements Playwright MCP or
12
14
  chrome-devtools-mcp with runtime JavaScript debugging on both browsers.
13
15
 
14
- > **Status: BETA (0.5.0-beta.8).** This version contains known bugs and differences
16
+ > **Status: BETA (0.6.0-beta.10).** This version contains known bugs and differences
15
17
  > between Chrome and Firefox (see [Limitations and TODO](#limitations-and-todo))
16
18
  > and parts that have not been verified (see [Untested](#untested)). Tool
17
19
  > replies may change in incompatible ways before 1.0. Please report problems
18
20
  > in the [issues](https://github.com/raultov/browser-control-mcp/issues).
19
21
 
22
+ 💬 Questions, ideas or feedback: join us on [Discord](https://discord.gg/JDfcmD73A).
23
+
24
+ ## Comparison with Playwright MCP and chrome-devtools-mcp
25
+
26
+ Measured on 2026-10-31 with browser-control-mcp built from the current
27
+ sources, `@playwright/mcp` 0.0.83 and `chrome-devtools-mcp` 1.12.0, driven by
28
+ the same stdio client through the same tasks on Chrome 156 (headless,
29
+ Linux). Every outcome was checked in the page, not taken from the reply.
30
+ Tokens are estimated as characters / 4 for every server.
31
+
32
+ **What each one can do**
33
+
34
+ | | browser-control-mcp | Playwright MCP | chrome-devtools-mcp |
35
+ | --- | --- | --- | --- |
36
+ | JavaScript debugger (breakpoints, call frames, stepping, script search) | **✓ Chrome and Firefox** (pause on load: Chrome) | ✗ | ✗ |
37
+ | Firefox | **✓ next to Chrome, same tools** | ✓ one browser per server | ✗ |
38
+ | Several browsers and instances at once | **✓** | ✗ | ✗ |
39
+ | Selectors | CSS, snapshot refs, `host >>> inner` into shadow roots and iframes | CSS, snapshot refs | snapshot refs only |
40
+ | Snapshot of a long page | **bounded at 50 000 characters**, `find_in_snapshot` searches the rest | unbounded | unbounded |
41
+ | Waits for the page to react after an action | ✓ ~50 ms when nothing reacts | ✓ ~500 ms | ✓ ~200 ms |
42
+ | Clicking a covered or hidden element | **fails at once, naming the overlay** | fails after a 5 s timeout | reports success (the overlay gets the click) |
43
+ | Mock requests, offline mode | ✓ | ✓ | offline only |
44
+ | PDF | ✓ file or inline | ✓ file | ✗ |
45
+ | Cookies and web storage | ✓ values hidden unless asked | ✓ values shown | ✗ |
46
+ | Secrets masked in output (`--secrets`) | ✓ | ✓ | ✗ |
47
+ | Performance | vitals + insights (LCP breakdown, layout shifts, render-blocking, long scripts) | trace file | trace + insights, Lighthouse |
48
+ | Heap snapshots, CSS styles, screencast | ✗ | video, tracing | ✓ |
49
+ | Generates Playwright test code | ✗ | ✓ | ✗ |
50
+ | Telemetry | **none** | none found | usage statistics on by default; traced URLs sent to CrUX |
51
+ | Single native binary (no Node.js) | **✓** | ✗ | ✗ |
52
+
53
+ **Measured**
54
+
55
+ | Task | browser-control-mcp | Playwright MCP | chrome-devtools-mcp |
56
+ | --- | --- | --- | --- |
57
+ | Tool list in context, default tools | 6 040 tokens | 5 330 tokens | 7 770 tokens |
58
+ | Tool list in context, every opt-in tool on | 9 500 tokens | 12 040 tokens | not measured (optional categories) |
59
+ | Snapshot of Hacker News | **4 588 tokens** | 12 356 tokens | 6 869 tokens |
60
+ | Snapshot of Wikipedia "Web browser" | **12 643 tokens** (cut, searchable) | 34 349 tokens | 27 656 tokens |
61
+ | Snapshot of MDN `<input>` | **12 625 tokens** (cut, searchable) | 158 077 tokens | 76 654 tokens |
62
+ | Log in step by step (8 calls) | **298 tokens, 1.8 s** | 521 tokens, 2.4 s | 364 tokens, 2.6 s |
63
+ | Log in with `fill_form` (5 calls) | **321 tokens, 1.6 s** | 428 tokens, 1.9 s | 352 tokens, 2.0 s |
64
+ | Click, median | 52 ms | 531 ms | 234 ms |
65
+ | Evaluate JavaScript, median | **0 ms** | 504 ms | 204 ms |
66
+ | Navigate (local page), median | **13 ms** | 31 ms | 119 ms |
67
+ | Full-page screenshot of a 31 700 px page | cut at 16 384 px, with a note | 3.3 MB image in the reply | saved to a file |
68
+ | Navigation to an unknown host | error | error | success with the error in the text |
69
+ | Navigate, then read the console (log, warning, errors) | 249 tokens | 191 tokens | 117 tokens |
70
+ | Navigate, then read the network log (3 requests) | 168 tokens | 48 tokens | 54 tokens |
71
+
20
72
  ## Supported browsers
21
73
 
22
74
  | Browser | Protocol | Validated with |
@@ -72,12 +124,12 @@ see the note.
72
124
  | `emulate` | ✓ | partial | `emulation` group; `width`/`height`, `device_scale_factor`, `mobile` (touch), `color_scheme`, `reduced_motion`, `forced_colors`, `media` (`print`), `reset`; answers what the page now sees; Firefox: viewport and device pixel ratio only (BiDi has no media or touch emulation yet; those options fail naming them) |
73
125
  | `wait_for` | ✓ | ✓ | waits (checking every 100 ms, at most 30 s) until a visible text appears or is gone, a selector is `visible` / `hidden` / `attached` / `detached`, or the URL contains a text; a dialog or debugger pause ends the wait at once |
74
126
  | `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) |
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 |
127
+ | `snapshot` | ✓ | ✓ | outline of the page: role, name, states, value and a ref (`e12`) per element, through open shadow roots and same-origin iframes; tables without headers (`th`, `thead`, `caption`) are layout and leave only their content, and a cell is named by its text only when it holds nothing else; an element that is only clickable (a handler or a pointer cursor) is one named line, unless it holds links, buttons or fields, which are listed under it; at most 50 000 characters (`selector` and `depth` narrow it); the same JavaScript on both browsers |
76
128
  | `find_in_snapshot` | ✓ | ✓ | `text` (case-insensitive) or `regex` over the whole outline; matching lines under their ancestors, at most 20 |
77
129
  | `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` |
78
130
  | `capture_screenshot` | ✓ | ✓ | `format` `png`, `jpeg` (or `jpg`) or `webp`; `full_page` at most 16 384 px per side (a text note says when cut) |
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}`) |
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 |
131
+ | `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 (its own label on top does not count: styled checkboxes and switches are clicked through it; a covered element first gets the mouse, so controls shown only on hover are revealed and clicked); `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}`) |
132
+ | `fill_input` | ✓ | ✓ | picks `<select>` options; fails without typing on elements that cannot take the text; in a contenteditable element (including rich text editors such as Slate, Lexical or ProseMirror) it selects the content and types over it, so the editor records the edit; 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 |
81
133
  | `press_key` | ✓ | ✓ | one key (a character, Enter, Tab, Escape, arrows, F1–F12...) with Control / Shift / Alt / Meta held, in `selector` (focused first) or the focused element; a shortcut types nothing |
82
134
  | `hover` | ✓ | ✓ | moves the mouse over the element (scrolled into view; fails when hidden or covered) |
83
135
  | `fill_form` | ✓ | ✓ | several fields in one call: text and `<select>` as `fill_input`, a checkbox or radio takes `true`/`false` and is clicked only when its state differs; stops at the first failing field naming what was done; never echoes values |
@@ -86,15 +138,15 @@ see the note.
86
138
  | `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`) |
87
139
  | `cookies` | ✓ | ✓ | `storage` group; `get` / `set` / `delete`: the cookies sent to the page (or `url`) or of a `domain`; values hidden unless `show_values: true` (Chrome `Network.*Cookie*`, Firefox BiDi `storage.*` in the tab's partition) |
88
140
  | `web_storage` | ✓ | ✓ | `storage` group; `get` / `set` / `delete` / `clear` on the page's `localStorage` or `sessionStorage`; values hidden unless `show_values: true` |
89
- | `get_console_logs` | ✓ | ✓ | a message keeps at most 10 000 characters; Firefox: page errors, CSS warnings and platform messages need the debugger port |
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 |
141
+ | `get_console_logs` | ✓ | ✓ | one line per message, oldest first: `[level] text @ url:line` (lines from 1), objects and arrays previewed as the console shows them (`{n: 1}`, `[1, 2, 3]`), repeats in a row folded (`[x3]`), uncaught errors marked with up to 5 stack lines indented; `include_details: true` gives the JSON with every field; a message keeps at most 10 000 characters; Firefox: page errors, CSS warnings and platform messages need the debugger port |
142
+ | `get_network_logs` | ✓ | ✓ | one line per request, oldest first (`id METHOD url => status [type]`, or `failed: <reason>` / `pending`), then one per WebSocket frame (payload preview); `request_id` shows one request's headers and body, `include_details: true` every request's as JSON (a binary body has `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); the browser's own requests (`chrome://`, `devtools://`, `data:`, `about:`, extensions) are not logged; Firefox: WebSocket frames need the debugger port |
91
143
  | `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
144
  | `list_routes` | ✓ | ✓ | `network` group; the tab's routes with the `hits` each answered |
93
145
  | `remove_route` | ✓ | ✓ | `network` group; one route by id, or all |
94
146
  | `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 |
95
147
  | `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` |
96
148
  | `get_performance_metrics` | ✓ | partial | `perf` group; Firefox: `Nodes`, `Frames`, `Resources`, `TransferSize` from the Web Performance APIs (no Performance domain), plus a note |
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` |
149
+ | `profile_page_performance` | ✓ | partial | `perf` group; `insights: true` adds what explains the numbers, read with the Web Performance APIs (same JavaScript on both): the document's TTFB, server time and compression, the LCP element and its breakdown (TTFB, load delay, load, render delay), layout-shift culprits, render-blocking requests, the slowest requests and the scripts of long animation frames (at most 5 each), plus `findings` from the web.dev thresholds; Firefox: FCP, LCP, DCL and Load; no trace, so `total_blocking_time_ms` and `top_long_tasks` are `null`, and its insights have no layout shifts, render-blocking requests or long frames (`null`, with notes) |
98
150
  | `set_breakpoint` | ✓ | partial | Firefox: by URL only (no `script_id` / `script_hash`) |
99
151
  | `remove_breakpoint` | ✓ | ✓ | |
100
152
  | `resume` | ✓ | ✓ | |
@@ -111,6 +163,16 @@ see the note.
111
163
  | `webmcp_get_invocation` | ✓ | ✗ | needs `--enable-webmcp` |
112
164
  | `webmcp_list_invocations` | ✓ | ✗ | needs `--enable-webmcp` |
113
165
 
166
+ After `click_element`, `hover`, `fill_input`, `fill_form` and `press_key`
167
+ the server waits for the page to settle before answering: until its DOM
168
+ stays unchanged for 50 ms (style changes, often animations, aside) and the
169
+ requests the action started finished, at most 1 s, on both browsers. An
170
+ action nothing reacts to costs those 50 ms and keeps its reply; otherwise
171
+ the reply adds `The page reacted (the DOM changed, 1 request(s)) and settled
172
+ after 134 ms.`, or says the page was still changing after 1 s. A click that
173
+ navigates waits for the new page's requests. Use `wait_for` for anything
174
+ slower (a timer, a long request).
175
+
114
176
  The JavaScript debugger tools on Firefox need its debugger (RDP) port: on by
115
177
  default for a launched Firefox, `--firefox-rdp-port` for an attached one. The
116
178
  same port gives Firefox's WebSocket frames and the console messages BiDi does
@@ -547,7 +609,7 @@ incompatible:
547
609
  - Firefox debugger: tabs are mapped to the debugger through Firefox's Remote
548
610
  Agent (verified on Firefox 157 only); a Firefox without it answers the
549
611
  debugger tools with an error instead of guessing a tab.
550
- - `get_network_logs` with response bodies has no total size limit (each
612
+ - `get_network_logs` with `include_details: true` has no total size limit (each
551
613
  Firefox body is capped at 2 MB): use `url_filter` on busy pages.
552
614
  - The Docker image is amd64 only.
553
615
 
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT",
21
21
  "name": "@raultov/browser-control-mcp",
22
- "version": "0.5.0-beta.8"
22
+ "version": "0.6.0-beta.10"
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.5.0-beta.8"
51
+ "version": "0.6.0-beta.10"
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.5.0-beta.8"
3
+ "https://github.com/raultov/browser-control-mcp/releases/download/v0.6.0-beta.10"
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.5.0-beta.8",
95
+ "version": "0.6.0-beta.10",
96
96
  "volta": {
97
97
  "node": "18.14.1",
98
98
  "npm": "9.5.0"