Skip to content

Releases: nguyenvanhuy0612/browserctl

0.9.4

Choose a tag to compare

@nguyenvanhuy0612 nguyenvanhuy0612 released this 10 Oct 15:36

A snapshot names what you ask for and nothing twice: only lists just the fields, buttons or
links, a viewport snapshot's text is the text on screen, and a page with iframes returns one
census.

  • BREAKING: browser_snapshot takes elements: true for the structured list; compact is
    refused with a pointer to it, and the output format no longer decides which is returned.
    format is json, pretty or smart; compact and raw are gone. CLI: --elements
    replaces -c/--compact, and snapshot --json answers the census.
  • BREAKING: a page with iframes answers one census with every frame in it; compactView is
    gone. Folded controls come back as one line each, @ref "text" -> href. hiddenContent kinds
    are load-more, collapsed and scrollable-region; tabs are tagged in the census instead, and
    collapsed menus no longer push a real "Show more" out of the list.
  • browser_snapshot only: ["fields", "buttons", "links"] lists just those kinds and leaves the
    page text out unless maxText is set (CLI --only). With scope "viewport", text is the
    visible text on screen. The smart format carries every field the JSON does.
  • browser_type: on an autocomplete field, effect.suggestions lists the options the text
    opened, each with a ref.
  • browser_click: plain text inside a box with a pointer cursor is clicked
    (resolved.clickableAncestor); a refusal names the controls nearest to the text, and the
    covered and did-not-change warnings name the next step.
  • A click whose navigation has not committed when it answers (a slow server, a cold DNS lookup)
    reports urlChanged: true with the pending address and a note, instead of "click NOT
    confirmed".
  • browser_fill_form: the description states it sets checkboxes, radios and selects.
    Load-more detection reads "Xem thêm", "Hiện thêm" and "Tải thêm".

0.9.3

Choose a tag to compare

@nguyenvanhuy0612 nguyenvanhuy0612 released this 01 Oct 02:05

A session's tab is its own: no other agent, and no CLI call, can act on it, and a click in another
window no longer decides where an agent's next command goes.

  • A session's target tab is held for it in the bridge. Another session (MCP or CLI) that acts on
    it or closes it gets TAB_OWNED, naming the holder, and nothing is sent; it may still read the
    tab by passing its tabId. The hold is renewed by every call and a 5 s
    heartbeat, released at once when the session's process exits or the tab closes, and lapses
    15 s after a session that hangs. browser_tabs list marks each held tab with heldBy.
  • A held tab can be taken on purpose: browser_tabs select on it is TAB_BUSY while its session
    is acting there or did under 30 s ago, otherwise TAKE_CONFIRM; repeating it with
    force: true (CLI --force) takes it, and the other session gets TARGET_TAKEN on its next
    command. browser_tabs gains release (give your tab up) and yield (let anyone take it
    without confirmation), and the CLI tab release and tab yield.
  • With several browsers or profiles connected, a session's first call no longer goes to the
    last-focused window: it is NEEDS_TARGET, listing every open tab and who holds it, and the agent
    selects one. A session moves freely between tabs in any browser; the tab it leaves is freed.
    The CLI follows the same rule and no longer reads BROWSERCTL_BROWSER; -b still names a
    browser.
  • A tab named by id alone reaches the browser that has it, for MCP and CLI alike: the bridge
    finds the owner, so browserctl -t <id> needs no -b. An id open in two browsers is
    AMBIGUOUS_TAB, one open nowhere TAB_NOT_FOUND.
  • The CLI keeps one session (cli, or BROWSERCTL_SESSION) whose target tab the bridge keeps
    between commands, instead of sharing the extension's pin with every agent. The pin is gone: the
    extension acts only on the tab id each command carries, and pinned is no longer in tab lists
    or current_tab. The ownership and routing errors (TAB_OWNED, TAB_BUSY, TAKE_CONFIRM,
    TARGET_TAKEN, NEEDS_TARGET, NEEDS_TAB, AMBIGUOUS_TAB, TAB_NOT_FOUND) exit the CLI with
    code 2.
  • The call log is on by default, at ~/.browserctl/calls.jsonl, and records each refusal with
    the session holding the tab. BROWSERCTL_CALL_LOG=0 turns it off.
  • A navigation stopped by a certificate warning is CERT_INTERSTITIAL, with a hint to ask the user
    instead of driving the browser through the OS.
  • The recorder serves only the tab it records: starting, stopping, reading or replaying it from
    another tab is RECORDING_ELSEWHERE; closing the recorded tab frees it. reload_extension
    waits (BROWSER_BUSY) while another session is acting in that browser.
  • A browser that reconnects keeps the holds and CLI targets on tabs it still has, so a restarted
    service worker loses nothing; a restarted browser's stale tab ids are dropped. browserctl tab list marks tabs held by another session.
  • switch_tab and close_tab accept the tab as tabId too, so browserctl tab close -t <id>
    closes that tab.
  • Errors the extension raises with a code now keep that code on the way to the agent.

v0.9.2

Choose a tag to compare

@nguyenvanhuy0612 nguyenvanhuy0612 released this 29 Sep 04:38

Several agents can now work on the same browser at the same time, and long-open background tabs
no longer stall.

  • Two sessions taking screenshots on one browser no longer refuse each other. Chrome allows two
    visible-tab captures a second per extension; captures are queued. A tab that another session
    moves out of view while a capture waits is captured as a background tab, never as the other
    tab's pixels.
  • Commands on one tab from several sessions share a single debugger attach, so none fails with
    "another debugger is already attached".
  • Edge now captures background tabs without bringing them to the front, as Chrome and Brave do.
    Focus emulation is on only for the moment of the capture.
  • A tab the browser froze in the background (Edge sleeping tabs, Chrome and Brave memory and
    energy savers) is woken before a command, instead of every command waiting 30 s. A discarded tab
    is reported with a reload hint, and browser_tabs list marks frozen and discarded tabs.
  • browser_get_property reads checked on a checkbox or radio. A click that checks one, or its
    label, is confirmed instead of warned about as "the page did not change".
  • New release gate: one session per connected browser (up to three) runs every core action at the
    same time, and each session's commands must stay on its own browser and tab.

v0.9.1

Choose a tag to compare

@nguyenvanhuy0612 nguyenvanhuy0612 released this 29 Sep 02:29

One bridge serves every browser and profile on the machine. Install the extension in each profile
and leave its port at 8765: there is no port to assign and nothing to add to the MCP config. Each
agent session keeps its own target tab, chosen on first use (the visible tab of the browser you
focused last) and kept afterwards, so two sessions can work in Chrome and Edge at the same time.
browser_tabs gained browser, query and activate; tabId routes to whichever browser owns
it. The CLI gained --browser / -b and BROWSERCTL_BROWSER, and browserctl status lists
every connected browser.

BREAKING:

  • Point every extension at port 8765 (Options > port, Save & reconnect) and stop any extra bridge
    you ran for a second browser.
  • browser_tabs select no longer brings the tab to the front; pass activate: true for that. The
    CLI's tab switch still does.
  • A closed target tab is TARGET_CLOSED (listing the open tabs) instead of falling back to the
    active tab, until browser_tabs select or new. A disconnected browser is
    BROWSER_DISCONNECTED until it reconnects.
  • A session's first call answers with a target block instead of the "re-issue" guard error.
  • browser_tabs list returns {tabs, browsers, target}, each tab tagged with its browser.
  • /status and browser_status list browsers instead of a top-level instanceId /
    browserType. No browser connected is 409 NO_BROWSER (was 503). CLI routing errors exit 2.

v0.9.0 — a compact snapshot is the census

Choose a tag to compare

@nguyenvanhuy0612 nguyenvanhuy0612 released this 24 Sep 05:09

Every tool was run against real pages and automation practice sites; this release is what that
turned up.

BREAKING: a compact browser_snapshot no longer carries elements. Folded controls come back
in folded as {ref, text, href}; compact: false still returns elements. Snapshots are about a
third of their old size (Google search 152 KB → 23 KB).

  • The census shows state: native checkbox/radio [checked]/[unchecked], closed menus
    [collapsed], disabled controls listed as [disabled]; each control appears once.
  • Controls are named the way the page names them (icon link by aria-label, <label> over
    placeholder, wrapped <select> by its label), and the census, browser_find and target
    resolution agree on names.
  • browser_navigate waits up to 20 s for the navigation to commit and fails with Chrome's network
    error instead of reporting the old page.
  • browser_find ranks exact names first; browser_press_key sends code/keyCode/which.
  • Scrolling a background tab dispatches the scroll event pages listen for; browser_hover sends
    pointer events as well as mouse events.
  • Capturing one element no longer needs browser_cdp_attach; an iframe element's frame is origin
    and path only; browser_a11y_snapshot coverage counts the whole census; browser_extract renders
    refs with one @.

Install: npm install -g browserctl-mcp@0.9.0 · npm: https://www.npmjs.com/package/browserctl-mcp/v/0.9.0

v0.5.1 — Stable Release

Choose a tag to compare

@nguyenvanhuy0612 nguyenvanhuy0612 released this 18 Aug 03:18

Key Highlights

1. Dynamic Tool Discovery & Lazy Loading (MCP)

  • Token Efficiency: Default core profile exposes ~24 essential tools, saving ~10,000 prompt tokens.
  • On-Demand Loading: Load tool groups (network, cdp, cookies, storage, console, record, tabs, advanced, all) at runtime with browser_load_tools.
  • On-Demand Unloading: Reset back to core with browser_unload_tools to reclaim context tokens.
  • Catalog Tool: Inspect active/inactive tool groups with browser_list_available_tools.

2. Zero-Terminal Background Daemon & State Machine

  • Automatic background daemon spawn on first MCP connection or CLI call (detached: true, child.unref()).
  • Instant CLI exit (browserctl start exits in ~150ms with code 0).
  • Lifecycle state machine managed via ~/.browserctl/daemon.json.

3. Extension Auto-Connect on Install

  • Auto-connects immediately upon extension load and browser launch (autoConnect: true).
  • Zero manual 'Connect' clicks required on fresh installs.

4. Form & Rich-Text Editor Compatibility

  • fill, type, and paste utilize native descriptor setters (100% Vue/React v-model safe).
  • Rich-text insertion via clipboard events (ProseMirror/Tiptap/Quill safe without AST corruption).
  • Added DOM primitives: fill, paste, clear, check, uncheck, focus, get_property, scrollintoview.

5. CLI & Smart Output Formatting

  • Ergonomic subcommands: open, get, fill, paste, clear, check, uncheck, select, wait, pdf, screenshot, tabs, eval.
  • Output flags: smart (default compact tree/table), -r / --raw, --json, --pretty.

6. Safety & Isolation Disclaimer

  • Prominent guidance advising users to run automation on dedicated test profiles or open-source Chromium builds.

Quickstart

{
  "mcpServers": {
    "browserctl": {
      "command": "npx",
      "args": ["-y", "browserctl-mcp"]
    }
  }
}