Chromewright

by bnomei

Not rated
GitHub

About

Browser automation via Chrome DevTools Protocol

Details

Author
bnomei
Categories
Developer Tools, Automation, Other

Setup

Install Chromewright in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/bnomei/chromewright

Follow the installation instructions in the repository README, then restart your MCP client.

Chromewright is a local-first browser automation MCP server built on Chrome DevTools Protocol (CDP). It exposes a real Chrome or Chromium browser to MCP clients over stdio or loopback streamable HTTP, with high-level tools for navigation, page reading, tab management, screenshots, viewport emulation, and bounded interaction. The default build also includes a semantic terminal browser and a co-hosted loopback MCP companion for its live document state.

Use Chromewright when an agent needs browser state from a real browser without embedding a Node.js automation stack or writing raw CDP calls. Chromewright is not an end-to-end test runner; it is a browser control layer for AI agents and MCP clients.

- Attach an MCP client to an existing Chrome or Chromium profile on a DevTools endpoint.
- Launch a dedicated local browser session for agent work.
- Read pages through snapshots, markdown extraction, targeted inspection, and link inventory.
- Browse a page's semantic DOM locally in the terminal, with a co-hosted MCP companion for its active document and selection state.
- Drive bounded interactions such as click, input, select, hover, key press, scroll, and wait.
- Capture managed PNG screenshots without letting callers choose arbitrary output paths.
- Reuse revision-scopedcursorhandles from snapshots instead of relying only on CSS selectors.

Chromewright requires Rust 1.88 or newer when you install or build it with Cargo.

brew install bnomei/chromewright/chromewright
git clone https://github.com/bnomei/chromewright.git cd chromewright cargo install --path .

You can also download prebuilt archives from GitHub Releases and place thechromewrightbinary on yourPATH.

This path starts a visible Chrome profile with DevTools enabled, then serves Chromewright over loopback HTTP athttp://127.0.0.1:3000/mcp.

- chromewrighton yourPATH
- Chrome, Chromium, or another CDP-compatible browser
- An MCP client that supports streamable HTTP or stdio servers

open -na "Google Chrome" --args \ --remote-debugging-port=9222 \ --user-data-dir="$HOME/.chromewright-agent-profile"

Use a dedicated profile when you do not want agent automation attached to your personal browser session. The default Chromewright attach mode expects DevTools athttp://127.0.0.1:9222.

Ready to accept MCP connections at http://127.0.0.1:3000/mcp

For JSON-configured clients that support streamable HTTP:

{ "mcpServers": { "chromewright": { "transport": "streamable_http", "url": "http://127.0.0.1:3000/mcp" } } }

For Codex over stdio, let the client start the server:

[mcp_servers.chromewright] command = "/absolute/path/to/chromewright" enabled = true

For Codex against the long-lived HTTP server from step 2:

[mcp_servers.chromewright] url = "http://127.0.0.1:3000/mcp" enabled = true

Use your MCP client to calltab_list. A connected session should return at least one tab with a stabletab_id. If no active tab is useful, callnew_tabbefore callingsnapshot.

# Default: attach to http://127.0.0.1:9222 and serve MCP over stdio. chromewright # Serve streamable HTTP on the default loopback endpoint. chromewright serve # Serve streamable HTTP on a custom port and path. chromewright serve --port 3333 --http-path /browser # Attach to a different DevTools endpoint. chromewright --ws-endpoint http://127.0.0.1:9333 # Launch a visible browser with a dedicated profile. chromewright --user-data-dir /tmp/chromewright-profile # Launch a headless browser and serve streamable HTTP. chromewright --headless --user-data-dir /tmp/chromewright-profile serve # Seed two managed tabs at startup. This works with attach, launch, serve, and tui modes. chromewright --url https://example.com --url https://example.org serve

--urlis repeatable and seeds one separate managed tab for every value, in the order supplied; the final seeded tab becomes active. It accepts absolutehttp:,https:, andabout:URLs. Relative, unsafe, and protocol-relative URLs are rejected before any startup tab is opened. In attach mode, existing tabs are untouched; only seeded tabs become managed by chromewright.

The default build includes a semantic terminal browser. It attaches to the same Chromewright browser session and renders semantic DOM content only (not pixels, CSS, or browser layout).

# Attach to an existing DevTools endpoint (default http://127.0.0.1:9222). chromewright tui # Managed private headless Chrome for the normal terminal-browser flow. chromewright --headless tui

To connect an MCP client to the co-hosted companion, choose a fixed loopback port; the default0selects an ephemeral port that the TUI does not print.

chromewright --headless tui --companion-port 3334
[mcp_servers.chromewright_tui] url = "http://127.0.0.1:3334/mcp" enabled = true

The companion exposes eighttui_*coordination tools and bounded semantic resources.semantic_refvalues are tied to one document revision; the active capture plus the previous eight revisions are retained, while stale or evicted references fail closed. Attention messages are limited to 512 characters. Semantic Markdown resources paginate at 32,000 characters by default and cap at 200,000; JSON resources fail instead of returning a truncated document.

The header is a single browser-like bar: tab ordinal (2/5) left of the history arrows, then location/title, with a lifecycle glyph on the right. Keyboard bindings are not shown in the terminal chrome. Defaults are Vimari-compatible. Multi-key sequences such asggandgiwait for the full chord; an unbound prefix is rejected rather than re-firing the last key.

Browser-first (Vimari) defaults, withmd-tui-style aliases where they do not collide. Overlaying an action replacesallof its sequences (primary + aliases).

Hints use deterministic two-key labels from the alphabetasdfgqwertzxcvb(for exampleaa,as), assigned to viewport-visible links and form controls (one label per target; painted on the first line only when a target wraps).

After navigation or a link follow settles, a URL fragment such as#sectionmoves the TUI selection to the matching component (id, then named anchor), expands collapsed ancestors, and scrolls it into view. Unmatched fragments keep the prior selection.

The content pane uses a terminal-native ANSI-16 role palette (clearer heading ladder H1–H6, blue links, light-cyan forms, yellow hints) with reverse-video selection applied last. Colors inherit the terminal light/dark theme; override individual roles under[theme]intui.toml. By default the markdown/content area has 1 column of left/right padding and is capped at 100 columns (centered; header and footer stay full width); presswfor full width. A one-column Amp-style block scrollbar sits on the far right of the content band. Override layout under[layout]intui.toml.

Default reading mode isprose(markdown-like): no▾ [main]/ol/ group chrome, fully flat lines. Presszsforstructure(DOM-like outline). Wrap (zw) and structure (zs) are not shown in the header bar; toggle feedback appears in the status line.

Search follows Vim semantics: a new/patternstarts after the current selection and wraps at the end;nrepeats forward,Nrepeats backward, and submitting an empty/prompt repeats the previous pattern. The footer shows the cmdline while typing (/…) and keeps/{pattern} n/mwhile a search is active — pressEscin Normal mode to clear it (Esc while typing/…only cancels the prompt and keeps the prior pattern forn/N). Link hints (f/F) also use the footer (f as) rather than the header. Bracketed paste is accepted only in URL, search, and form input modes and is bounded to 4096 characters.

Bindings are replaceable by action name.--config PATHtakes precedence; if omitted, Chromewright reads$XDG_CONFIG_HOME/chromewright/tui.toml, falling back to~/.config/chromewright/tui.toml. A missing default file keeps the built-ins; an explicitly requested file must parse successfully.

# Only list keys you want to change. Unknown names or conflicting # bindings abort startup rather than partially applying the overlay. [keymap] reload = "ctrl-r" quit = "ctrl-q" tab_prev = "shift-tab" # Optional content-pane padding + column width (header/footer stay full width). # Defaults: 1 col L/R, 0 row T/B, content_max_width = 100 (0 = always full). # Press w to toggle full width vs the capped column. [layout] # content_padding_x = 1 # content_padding_y = 0 # content_max_width = 100 [theme] # Optional ANSI names, reset, or #rrggbb — defaults already use a clear ladder. # link = "blue" # h1 = "lightblue" # h2 = "green" # h3 = "magenta" # h4 = "cyan" # h5 = "yellow" # h6 = "lightred" # form_control = "lightcyan" # hint_label = "yellow"

Binding specs accept single keys (r,space,esc,enter,tab), multi-key letter sequences (gg,gi), and chords with-,+, or space separators (ctrl-c,C-c,shift-tab). Supported named keys includeesc,enter,tab,backtab/shift-tab,backspace, arrow keys,home,end,pageup/pgup,pagedown/pgdn,space, and function keys such asf1.

Theme roles:link,h1h6,landmark,group,list,image,form_control,hint_label,muted,chrome_ready,chrome_loading,chrome_error,chrome_mode,attention_fg,attention_bg.

Layout keys:content_padding_x,content_padding_y(symmetric inset around the markdown/content pane only),content_max_width(default 100;0disables the cap;wtoggles full vs capped).

The source of truth for defaults issrc/tui/keymap.rsandsrc/tui/action.rs.
- Calltab_listornew_tabto establish an active tab.
- Callsnapshotto read the current page and collect actionable nodes.
- Prefer a freshcursorfromsnapshotorinspect_nodewhen targeting follow-up actions.
- Useinspect_node,get_markdown,extract, orread_linksfor more focused reads.
- Useclick,input,select,hover,press_key,scroll,wait, or tab tools for bounded interaction.
- Callsnapshotagain after navigation, DOM-changing actions, viewport changes, or ambiguous target recovery.

DOM-targeted tools accept a publictargetobject:

{ "target": { "kind": "selector", "selector": "h1" } }
{ "target": { "kind": "cursor", "cursor": "<cursor from snapshot or inspect_node>" } }

Selector strings are still accepted for compatibility by tools that use the public target type, but the object form is the canonical contract.

Production MCP sessions register the default high-level tools plus the guarded operator toolevaluate.

evaluateexecutes JavaScript in the active page and requiresconfirm_unsafe = trueon each call. It is available for diagnostics and escape-hatch inspection when bounded tools cannot answer a page-specific question.

Source:src/tools/core/mod.rsandsrc/browser/session.rs.

Usescreenshotwhen a caller needs a managed PNG artifact. The tool accepts:

- mode:viewport,full_page,element, orregion
- scale:deviceorcss
- optionaltab_id
- optionaltargetforelementcaptures
- optionalregionforregioncaptures

Successful calls return managed artifact metadata, includingartifact_uri,artifact_path,mime_type,byte_count, image dimensions, CSS dimensions, device pixel ratio, pixel scale,revealed_from_offscreen, and optional clip data. Callers do not provide output paths.

Useset_viewportto emulate responsive breakpoints through CDP. Successful calls returnviewport_metrics_after; latersnapshotcalls expose the live metrics underscope.viewport.

Finished tool results includeoperation_metricsmetadata when a tool records non-zero metrics.operation_metrics.output_bytesis optional; it appears only when a tool path measures the exact serialized output size.

- browser evaluation count
- poll iterations
- DOM extraction count and extraction time
- last DOM node count
- snapshot render time
- handoff rebuild count and time
- exact serialized output size when measured

Run the focused operation metrics tests:

cargo test --locked --all-features operation_metrics

Run the browser smoke suite from the repository root:

cargo test --test browser_smoke -- --nocapture

Browser smoke checks launch a local browser and are intended for maintainer workstations. CI covers formatting, clippy, MSRV, cargo check, tests, and packaging without requiring a live browser attach target.

- Package metadata and Rust version:Cargo.toml
- CLI flags and transports:
src/bin/mcp_server.rs
- Tool registry:
src/tools/core/mod.rs
- MCP handler:
src/mcp/handler.rs
- Public target contract:
src/contract/target.rs
- Screenshot contract:
src/tools/screenshot.rs
- TUI default keymap and actions:
src/tui/keymap.rs,src/tui/action.rs
- Browser smoke script:
scripts/browser-smoke.sh

This is a web browser that enables your coding agent, such as Claude Code, to visit websites on your behalf and assist you in identifying bugs or creating UI test cases.

An AI agent for the Playwright MCP server, enabling automated web testing and interaction.

Generate Playwright BDD tests, GitHub Actions and Azure Pipelines with business-rule traceability, focused CodeGraph context and persistent Engram memory.

Autonomous QA MCP that tests web and macOS apps like a real engineer and verifies every bug.

A Playwright-based MCP server that exposes a live browser as a traceable, inspectable, debuggable and controllable execution environment for AI agents.

Drive, inspect, and assert on real Electron desktop apps from an AI agent — agent-native, Playwright-style automation with accessibility refs, stable error codes, and retrying assertions

Playwright MCP for Godot, screenshots, SceneTree manipulation, and arbitrary GDScript execution at runtime through a local UDP bridge.

A lightweight, AI-powered end-to-end testing framework for CI workflows. Requires an OpenAI API key.

Automate web testing and tasks by connecting Claude Desktop with Playwright.

Create and manage end-to-end tests using the Octomind platform.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.