# io.github.frsorrentino/chrome-bridge (npm · chrome-bridge-mcp)

Your real, logged-in Chrome as an MCP server: 63 token-efficient web-dev tools. ChromeOS included.

- Trust score: 64/100 (medium)
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-05

> **Malware flagged**: A supply-chain scanner flagged a high-severity malware risk in this package. Treat it as unsafe to install until the finding is cleared.

## Components

- npm · `chrome-bridge-mcp`: 64/100 (this document), [markdown](https://verifymcp.io/servers/frsorrentino-chrome-bridge/chrome-bridge-mcp.md), [page](https://verifymcp.io/servers/frsorrentino-chrome-bridge/chrome-bridge-mcp)

## Channel facts

- Registry: `npm`
- Package: `chrome-bridge-mcp`
- Version: `1.15.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-05.

- **Supply Chain Security**: 42/100
  - Malware check failed: a supply-chain vendor flagged a high-severity malware risk.
  - Only part of the dependency tree could be resolved (106 of 110), so this covers what we could see, not the whole tree.
  - No install/post-install scripts declared.
  - Only part of the dependency tree could be resolved (106 of 110), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 97/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to frsorrentino/chrome-bridge).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 4 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 71/100
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 5371 tokens (~157/item across 34 items; 34 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 20/100
  - Stability observed for 6 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add frsorrentino-chrome-bridge -- npx -y chrome-bridge-mcp
```

### Codex

```bash
codex mcp add frsorrentino-chrome-bridge -- npx -y chrome-bridge-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "frsorrentino-chrome-bridge": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "chrome-bridge-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add frsorrentino-chrome-bridge --command npx --arg -y --arg chrome-bridge-mcp
```

### Hermes

```yaml
mcp_servers:
  frsorrentino-chrome-bridge:
    command: "npx"
    args: ["-y", "chrome-bridge-mcp"]
```

### Other

```json
{
  "mcpServers": {
    "frsorrentino-chrome-bridge": {
      "command": "npx",
      "args": [
        "-y",
        "chrome-bridge-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-05 (score 64, +1)

- [security improvement] CVE-2026-69207 no longer affects this package
- [security improvement] Known CVEs: fail → partial

### 2026-08-04 (score 63, 0)

- [security regression] CVE-2026-69207 affects this package: medium
- [security regression] Known CVEs: partial → fail

### 2026-08-02 (score 63, +44)

- [security regression] Malware scan: unverified → fail
- [security regression] Malware indicator gptMalware:QwocqzvG6ZjlG5ApZuMoP-XO8DeakRB_ZBJ-P6SWamhs: high
- [security improvement] Known CVEs: unverified → partial
- [security improvement] Install scripts: unverified → pass
- [security improvement] Provenance: unverified → pass
- [security] The attested source repository moved: frsorrentino/chrome-bridge
- [functional improvement] Schema quality: unverified → excellent
- [functional improvement] License: unverified → pass
- [functional improvement] Stability: unverified → 0.10
- [functional improvement] Dependency health: unverified → partial
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] MCP protocol: unverified → pass
- [functional] Licence: MIT

### 2026-08-01 (score 19, +14)

- [functional regression] Schema quality: 137 → 157
- [functional improvement] Tool coverage: unverified → 100

### 2026-07-31 (score 5, −21)

- [functional] Package version: 1.10.1 → 1.11.0
- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-30 (score 26)

First indexed and scored.

## MCP tools (34)

### `get_status` (~26 tokens)

Check bridge status: extension connection, server mode (primary/relay), port, version

### `get_tabs` (~114 tokens)

List every open tab with id, url, title and active flag. Read-only. Use it to find a tab_id when the implicit target (last navigated tab, else the active one) is not the tab you mean. include_windows adds the windows themselves with their position, size, state and type — what you need before moving or tiling anything, and the only way to tell which monitor a window is on.

Input parameters:

- `include_windows` (boolean): Also return the windows with bounds, state, type and tab count

### `navigate` (~74 tokens)

Navigate a Chrome tab to a URL. Returns a preview of interactive elements with refs usable in click/type_text/hover.

Input parameters:

- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `url` (string, required): Absolute URL, or a path resolved against the current page

### `screenshot` (~106 tokens)

Screenshot of the visible viewport only (PNG), at the current scroll position. Read-only. Activates the tab in the background without stealing window focus, then restores the previous tab. Downscaled to ≤1568px, so fine print may not survive.

Input parameters:

- `save_to` (string): Absolute path: write the PNG there and return the path instead of the content
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `execute_js` (~111 tokens)

Run JavaScript in the page (MAIN world). Requires the extension's "Allow user scripts" toggle; errors explain setup if disabled.

Input parameters:

- `code` (string, required): JS evaluated in the page; the value of the last expression is returned
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `max_length` (number): Max output chars
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `click` (~252 tokens)

Click an element, by CSS selector or by a ref (n1, n2…) from get_interactives or navigate. Fires a real pointer sequence, so it can submit, open a dialog or navigate away — use wait_after to let that settle. Not idempotent, and a click that triggers a native confirm() blocks the bridge: install handle_dialogs first.

Input parameters:

- `button` (string): right opens the page context menu instead of activating the element
- `count` (number): 2 emits dblclick after the two clicks, which is what selects a word or opens an editor
- `force` (boolean): Click even if occluded
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `ref` (string): From get_interactives, e.g. "n3"
- `selector` (string): CSS selector; ">>>" pierces shadow DOM. Ignored when ref is given
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `wait_after` (string): Settle before returning: navigation waits for a page load, networkidle for quiet traffic

### `type_text` (~255 tokens)

Put text into an input, textarea or contenteditable, by CSS selector or by a ref from get_interactives. Replaces the whole value rather than appending, and assigns through the native setter so React and Vue controlled inputs register the change, then fires input and change. mode=keys instead emits keydown/input/keyup per character, which is what autocomplete and masked fields need — slower, so reach for it only when mode=set leaves the field empty or the dropdown never opens.

Input parameters:

- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `mode` (string): set = assign value; keys = per-char events (autocomplete/masked)
- `ref` (string): From get_interactives, e.g. "n3"
- `selector` (string): CSS selector; ">>>" pierces shadow DOM. Ignored when ref is given
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `text` (string, required): Value to type; empty string clears the field
- `wait_after` (string): Settle before returning: navigation waits for a page load, networkidle for quiet traffic

### `read_page` (~205 tokens)

Read the page as text (default), markdown, raw HTML, or accessibility tree. Read-only. markdown keeps headings, links and tables at a fraction of the HTML cost, and is usually the right middle ground. Expensive on large pages: HTML on a big table costs tens of thousands of tokens for data you then filter anyway — prefer extract_table or extract for tabular and repeated content, and get_interactives to find click targets.

Input parameters:

- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `max_length` (number): Max output chars
- `mode` (string): text strips markup, markdown keeps headings/links/tables far cheaper than html, accessibility returns the a11y tree
- `save_to` (string): Absolute path: write the page there and return the path instead of the content
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `get_page_info` (~70 tokens)

Get page metadata: meta tags, scripts, stylesheets, links, and forms

Input parameters:

- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `query_dom` (~132 tokens)

Query DOM elements by CSS selector, returning structure, attributes, bounding rect, and computed styles.

Input parameters:

- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `limit` (number): Max elements returned, from the top of the match list
- `properties` (array): Computed styles to include, e.g. ["color"]
- `selector` (string, required): CSS selector; ">>>" pierces shadow DOM. Matches all, not just the first
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `read_console` (~109 tokens)

Read console messages captured since page load, incl. uncaught errors and unhandled rejections.

Input parameters:

- `clear` (boolean): Clear buffer after read
- `format` (string): lines is compact; json keeps timestamps and stack traces
- `level` (string): all merges every level in one chronological list
- `limit` (number): Most recent; buffer 1000
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `monitor_network` (~135 tokens)

Monitor network requests. source=page: XHR/fetch hook (installed on first call); source=browser: all requests incl. static assets. format=har exports HAR 1.2.

Input parameters:

- `clear` (boolean): Clear buffer after read
- `format` (string): har exports HAR 1.2 for external tooling
- `limit` (number): Most recent; buffer 1000
- `source` (string): page sees XHR/fetch only; browser also sees static assets
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `create_tab` (~172 tokens)

Open a new tab, optionally at a URL, and make it the implicit target of later commands in this session. Each call creates another tab: reuse a tab_id or navigate() to move an existing one instead of piling up tabs.

Input parameters:

- `active` (boolean): false opens the tab in the background, leaving the current one focused
- `height` (number): Window height px (new_window)
- `left` (number): Window x on the virtual desktop (new_window)
- `new_window` (boolean): Open in a fresh window instead of a tab; with left/top it lands on the chosen monitor
- `top` (number): Window y (new_window)
- `url` (string): URL to open (default: new tab page)
- `width` (number): Window width px (new_window)

### `wait_for` (~308 tokens)

Block until a condition holds: element (selector in the DOM), function (JS expression turns truthy; needs the "Allow user scripts" toggle), navigation (mode=spa for client-side route changes), network_idle. Polls until timeout — 10s for element and function, 15s for navigation and network_idle — then **returns `found: false` with a reason instead of raising**, so a caller that ignores the result silently proceeds as if the wait had succeeded. Read-only: waiting changes nothing on the page.

Input parameters:

- `condition` (string, required): element and text need selector or text; function needs expression
- `expression` (string): JS expression (condition=function)
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `idle_ms` (number): Quiet period ms (network_idle)
- `interval` (number): Poll ms, min 50
- `mode` (string): spa = pushState/popstate/hashchange
- `selector` (string): condition=element; with condition=text it narrows the search to that subtree
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `text` (string): Literal text to wait for (condition=text), matched case-insensitively
- `timeout` (number): Max ms (default 10000; 15000 navigation/network_idle)
- `visible` (boolean): Element must also be visible

### `scroll` (~256 tokens)

Scroll. action=to: once to element/coordinates; action=until: repeatedly until element visible, network idle, or no new content (infinite scroll).

Input parameters:

- `action` (string): to jumps to a position or element; until scrolls repeatedly to load more
- `behavior` (string): instant avoids waiting for smooth-scroll animations
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `max_scrolls` (number): Cap on scroll steps, so an infinite feed terminates
- `offset_y` (number): px offset for fixed headers (to)
- `selector` (string): Target (to) or stop element (until=element)
- `settle_ms` (number): Pause ms after each step
- `step_px` (number): px per step, default viewport height
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `until` (string): no_new_content stops when the page height stops growing
- `x` (number): Absolute horizontal position in px (action=to, without selector)
- `y` (number): Absolute vertical position in px (action=to, without selector)

### `fill_form` (~125 tokens)

Batch fill form fields with React-compatible events. Handles input, select, checkbox, radio, and textarea.

Input parameters:

- `fields` (array, required): {selector, value} pairs
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `submit_selector` (string): Submit button to click after filling
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `wait_after` (string): Settle before returning: navigation waits for a page load, networkidle for quiet traffic

### `element_screenshot` (~104 tokens)

Screenshot cropped to one element (PNG), scrolled into view first. Read-only. The cheapest image in the set, because it carries only the box you asked for: a component, a chart, a table cell.

Input parameters:

- `selector` (string, required): CSS selector; ">>>" pierces shadow DOM. The element is scrolled into view first
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `full_page_screenshot` (~233 tokens)

Full-page capture by scrolling: stitched segments of ~2 viewports (≤1568px, top→bottom), or one image per viewport with stitch=false. Read-only, but expensive: each segment costs ~2.7k image tokens, so only the first max_segments are returned and the rest need segment_offset. On a long page, reading the text you actually need is cheaper by an order of magnitude — prefer read_page, extract or find_text unless the layout itself is the question.

Input parameters:

- `delay` (number): ms between captures (min 500, Chrome quota)
- `max_scrolls` (number): Cap on scroll steps: a taller page is captured only up to here
- `max_segments` (number): Images returned, from the top (each ≈2.7k image tokens); raise or use segment_offset for the rest
- `segment_offset` (number): Skip the first N segments
- `stitch` (boolean): false = one image per viewport
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `hover` (~104 tokens)

Hover over an element (mouseenter/mouseover), by CSS selector or ref.

Input parameters:

- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `ref` (string): From get_interactives
- `selector` (string): CSS selector; ">>>" pierces shadow DOM. Triggers CSS and JS hover handlers
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `press_key` (~192 tokens)

Send a key to the focused element (or to selector, focusing it first) as a real keydown/keypress/keyup sequence, so framework handlers fire. For typing a value use type_text; this is for Enter, Tab, Escape, arrows and shortcuts. Not idempotent: two calls send the key twice.

Input parameters:

- `alt` (boolean): Hold Alt
- `ctrl` (boolean): Hold Control
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `key` (string, required): e.g. "Enter", "Escape", "Tab", "ArrowDown"
- `meta` (boolean): Hold Meta (Command/Windows)
- `selector` (string): Target (default: activeElement)
- `shift` (boolean): Hold Shift
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `get_frames` (~59 tokens)

List frames (main + iframes) with frameId, parent, URL — for the frame_id parameter of DOM tools.

Input parameters:

- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `tab_action` (~199 tokens)

Tab lifecycle: close, activate (focus), reload (optional cache bypass), back, forward. close discards the tab and anything unsaved in it, and cannot be undone — it may be a tab the user is working in. reload and navigation drop injected CSS, emulations and page hooks. duplicate works where create_tab is forbidden (chrome-untrusted://, verified on a ChromeOS Terminal tab) and lands in the source tab's own window, app windows included — the only way to open a new Terminal session inside the Terminal window. discard replaces the tab id: the result carries the new one, saved ids go stale.

Input parameters:

- `action` (string, required): close cannot be undone; discard frees memory, the tab reloads on focus; reload drops injected CSS and hooks
- `bypass_cache` (boolean): reload only
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `upload_file` (~100 tokens)

Set a file on input[type=file] from the server filesystem via DataTransfer (max 10MB).

Input parameters:

- `mime_type` (string): Default: inferred from extension
- `path` (string, required): Absolute path on the server machine
- `selector` (string, required): The file input to fill; ">>>" pierces shadow DOM
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `dismiss_overlays` (~59 tokens)

Dismiss cookie banners/modal overlays: OneTrust, Cookiebot, Usercentrics, then generic heuristic. Idempotent.

Input parameters:

- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `handle_dialogs` (~94 tokens)

Auto-accept/dismiss future JS dialogs (alert/confirm/prompt), logging them. reset restores native dialogs and returns the log.

Input parameters:

- `action` (string): accept/dismiss auto-answer future dialogs; reset restores native behaviour
- `prompt_text` (string): Returned by window.prompt on accept
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `find_text` (~113 tokens)

Find text on the page: parent selector, context, visibility, position per match. Attaches nearby interactive elements (with refs for click/type_text/hover) for the first visible match.

Input parameters:

- `case_sensitive` (boolean): Match case exactly
- `max_results` (number): Cap on matches returned, in document order
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `text` (string, required): Literal text to find, not a regex

### `clipboard` (~73 tokens)

Read or write the system clipboard (text). Activates the tab first.

Input parameters:

- `action` (string, required): write takes text; read returns the current clipboard contents
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `text` (string): For write

### `http_request` (~202 tokens)

HTTP request sent from the browser, so it carries the session cookies of the logged-in user: fetches URLs a plain server-side request would get a login page for (invoices, authenticated JSON, CSV exports). Text bodies are returned inline (capped by max_length); with save_to the bytes are written to that path instead, which is how you read a PDF — Chrome renders PDFs in a viewer no content script can reach, so read_page returns nothing on a PDF tab.

Input parameters:

- `body` (string): Request body (POST/PUT/PATCH)
- `headers` (object): Extra request headers
- `max_length` (number): Max chars of body returned inline
- `method` (string): HEAD fetches headers only, without the body
- `save_to` (string): Absolute path: write the response bytes here instead of returning them (PDF, images, archives)
- `url` (string, required): Absolute URL. Cookies are sent for its origin

### `move_tab` (~342 tokens)

Move an existing tab into another window (chrome.tabs.move). Nothing is created or closed: the tab keeps its id, history and page state, and this works even on chrome-untrusted:// tabs where creating one is forbidden — verified on a ChromeOS Terminal tab. The **destination** must be a normal window: moving out of an app or popup window is fine, moving into one is refused with "Tabs can only be moved to and from normal windows". So a ChromeOS Terminal session can be pulled out to its own window (new_window, then position it with viewport_resize) but cannot be merged back into the Terminal window — the closest look is window_type popup: no tab strip, no omnibox, visually a terminal window. An extension cannot create app windows: normal and popup are all Chrome offers.

Input parameters:

- `height` (number): New window height px (new_window)
- `index` (number): Position in the destination window; -1 appends at the end
- `left` (number): New window x (new_window)
- `new_window` (boolean): Extract the tab into a fresh window instead — tabs.move needs an existing window, this does not
- `tab_id` (number, required): Tab to move; get it from get_tabs
- `top` (number): New window y (new_window)
- `width` (number): New window width px (new_window)
- `window_id` (number): Destination window; get_tabs reports windowId for every tab
- `window_type` (string): new_window only: popup has no tab strip and no omnibox — the terminal-window look for detached chrome-untrusted://terminal tabs

### `tile_windows` (~230 tokens)

Tile Chrome windows over one monitor, splitting its usable area into equal parts that leave no gap. Only Chrome windows: an extension cannot touch other applications. The monitor is chosen by pointing at a window already on it, since the work area is read from a page there — so at least one target window needs a scriptable tab (a chrome:// or chrome-untrusted:// tab cannot provide it). Maximized windows are restored first, because a maximized window accepts bounds and ignores them.

Input parameters:

- `area` (object): Monitor area to fill, when no target window has a scriptable tab to read it from
- `include_types` (array): Window types to include; omitted = normal only
- `layout` (string): columns splits left to right, rows top to bottom, grid keeps tiles as square as it can
- `padding` (number): Px of empty margin kept inside the work area
- `reference_window_id` (number): Window whose monitor is used; omitted = the focused one
- `window_ids` (array): Windows to tile; omitted = every normal window on the reference monitor

### `window_layout` (~125 tokens)

Save the current window arrangement under a name, restore one, list or delete saved ones. save overwrites a same-named layout without asking. Window ids do not survive a browser restart, so restore recognises windows by the overlap of their tab URLs (same type required) and repositions the best match — windows it cannot recognise are reported, not guessed. Needs extension >= 1.14.0 for window geometry.

Input parameters:

- `action` (string, required): save snapshots every window; restore repositions the recognised ones
- `name` (string): Layout name, required except for list

### `get_interactives` (~157 tokens)

List actionable elements (buttons, links, inputs, [role], [onclick]) with ready-to-use CSS selector, label, position, flags. Prefer this over dumping HTML to discover selectors.

Input parameters:

- `format` (string): lines is compact; json adds full attributes per element
- `frame_id` (number): Target iframe id from get_frames; omitted = main frame
- `limit` (number): Max elements returned; raise it on a dense page
- `scope` (string): Limit search (CSS selector)
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `visible_only` (boolean): false also lists elements hidden or scrolled out of view

### `extract` (~181 tokens)

Read repeated non-tabular structures — product cards, list items, search results — as one record per item: item_selector matches the repeating block, fields map output names to selectors relative to it. Read-only, deterministic, parsed server-side from the main-document HTML.

Input parameters:

- `fields` (object, required): field name → {selector, attr}
- `format` (string): lines is compact; json keeps one object per record
- `item_selector` (string, required): CSS selector matching each item
- `max_items` (number): Cap on records returned, in document order
- `max_length` (number): Max output chars
- `save_to` (string): Absolute path: write the records as JSON there and return the path instead of the content
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one

### `assert` (~188 tokens)

Assert a page condition, polling until timeout: element exists/visible (optionally with count or containing text), text on page, tab url/title. Patterns: substring, or "/…/" for regex. Recorded flows replay it as a test.

Input parameters:

- `count` (number): Exact match count for selector
- `selector` (string): Element the assertion is about; ">>>" pierces shadow DOM
- `state` (string): attached means present in the DOM, visible also requires a rendered box
- `tab_id` (number): Target tab; omitted = last tab navigated in this session, else the active one
- `text` (string): In the element (with selector) or anywhere on the page
- `timeout` (number): Max ms to wait for the condition before failing
- `title` (string): Tab title pattern
- `url` (string): Tab url pattern

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/frsorrentino-chrome-bridge/chrome-bridge-mcp#diagnostics

## Score history

- 2026-08-05: 64
- 2026-08-04: 63
- 2026-08-03: 63
- 2026-08-02: 63
- 2026-08-01: 19
- 2026-07-31: 5
- 2026-07-30: 26

## Links

- npm package: https://www.npmjs.com/package/chrome-bridge-mcp
- Socket report: https://socket.dev/npm/package/chrome-bridge-mcp
- Repository: https://github.com/frsorrentino/chrome-bridge
- Changelog RSS feed: https://verifymcp.io/servers/frsorrentino-chrome-bridge/chrome-bridge-mcp/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/frsorrentino-chrome-bridge/chrome-bridge-mcp/changelog.json
- HTML version of this page: https://verifymcp.io/servers/frsorrentino-chrome-bridge/chrome-bridge-mcp
