bro
Health Uyari
- License — License: Apache-2.0
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Uyari
- process.env — Environment variable access in benchmarks/pi-agent/compare-extension.ts
- process.env — Environment variable access in benchmarks/pi-agent/refs-extension.ts
Permissions Gecti
- Permissions — No dangerous permissions requested
Bu listing icin henuz AI raporu yok.
Rust-native MCP server for controlling a local browser through a minimal WebExtension bridge
bro
Rust-native MCP server for controlling a real local browser through a minimal
WebExtension bridge.
bro is built for agents that need a shorter browser interaction loop:
- open many URLs in background tabs and extract useful text/links in parallel
- keep a single tab leased for sequential click/fill/read flows
- use a logged-in Chromium-family browser without sending browsing data through
a cloud relay - keep the MCP server, API policy, concurrency, and tests in Rust
The browser runtime itself is still a WebExtension because Chromium exposeschrome.tabs, chrome.debugger, content scripts, and service workers only to
the extension environment. bro keeps that layer intentionally thin.
Acknowledgement
bro is inspired by and initially prototyped against
OpenBrowserMCP. OpenBrowserMCP
proved the local WebSocket bridge + browser extension shape; bro takes that
idea into a Rust-native MCP server with a smaller agent-facing API, tighter
regression tests, and a minimal extension adapter. OpenBrowserMCP is
Apache-2.0, and this repository keeps the Apache-2.0 license and attribution in
NOTICE.
Architecture
Codex MCP / bro Pi adapter
-> bro Rust server (:3500 /mcp, /ws, /health, /status)
-> bro WebExtension adapter
-> Chromium-family browser tab
The Rust server owns:
- MCP Streamable HTTP
- WebSocket bridge registry
- tool schema and routing
- default-first browser facade tools
- batch scheduling and cleanup policy
- regression tests and release artifacts
The extension owns:
- connecting to
ws://127.0.0.1:3500/ws - authenticating with the local token
- executing browser primitives via WebExtension APIs and CDP
Quick Start
Install with Homebrew:
brew install xiaotianxt/tap/bro
brew services start bro
bro setup codex
bro setup browser
For native bro tools in Pi, install the bro-owned adapter and reload Pi:
pi install git:github.com/xiaotianxt/[email protected]
Install the optional Codex/agent skill for bro-specific browser workflows:
npx -y github:xiaotianxt/skills bro-browser
After the npm package is published, the equivalent command is:
npx -y @xiaotianxt/skills bro-browser
The service runs bro serve locally and exposes MCP athttp://127.0.0.1:3500/mcp. bro setup codex updates~/.codex/config.toml to connect Codex to that local MCP endpoint with the
bearer token from ~/.bro/settings.json. Restart Codex after running it.
bro setup browser copies the token to your clipboard, opens the browser
extension page, and reveals the unpacked extension directory. In the browser,
enable Developer mode, choose Load unpacked, select the shown directory, then
open bro Options and paste the token.
Use brew services restart bro after upgrading.
For source development:
git clone https://github.com/xiaotianxt/bro.git
cd bro
cargo run -- serve
The first run creates ~/.bro/settings.json:
{
"token": "..."
}
Existing settings are read without modification. If the file is malformed or
contains an empty token, bro reports the error and leaves the file unchanged.
Build the extension:
pnpm install
pnpm --filter @bro/shared build
pnpm --filter @bro/extension typecheck
pnpm --filter @bro/extension test
pnpm --filter @bro/extension build
For source checkouts, pass the local extension directory explicitly:
cargo run -- setup browser --extension-dir extension/dist
MCP Configuration
Run bro as a local service, then point your MCP client at the HTTP endpoint with
the local bearer token from ~/.bro/settings.json.
For Codex, prefer the setup command:
bro setup codex
It writes a bro MCP server entry like this:
[mcp_servers.bro]
url = "http://127.0.0.1:3500/mcp"
[mcp_servers.bro.http_headers]
Authorization = "Bearer <token from ~/.bro/settings.json>"
The setup command does not print the token. If you configure another MCP client
manually, send the same token as an Authorization: Bearer ... header.
Codex also supports bearer_token_env_var, but bro setup codex uses a static
local header so the configuration does not depend on a particular shell startup
file.
The MCP client should connect to this endpoint. It should not spawn the server
per request; keep bro serve running through Homebrew services or another
local process supervisor. Do not commit browser output, cookies, signed URLs, or
tokens.
Pi
The Pi package in pi-extension/ uses Pi's extension API and the official MCP
TypeScript SDK. It reads the bearer token directly from ~/.bro/settings.json,
keeps one MCP connection per Pi session, and registers bro's live tool schemas
under a bro_ namespace. Nine tools start active: search, open/observe/act/close,
and extract/current.extract/batch.extract/batch.flow, selected by server metadata. bro_search_tools enables server-owned capability
packs for tabs, frames, accessibility, console, visual input, uploads,
shortcuts, and user scripts. Internal tools are not registered. Legacy flow
compatibility tools remain discoverable but inactive by default. Older servers
retain the old default catalog.
The adapter maps Pi session identity into bro's tab lifecycle, preserves browser
state across /reload, and finalizes owned tabs and unfinished targets when the
session ends. Owner labels are automatic and separate from pinned target IDs. It remains a protocol adapter: browser policy, tool schemas,
timeouts, and cleanup behavior stay in the Rust server.
For development from this checkout:
pi install /absolute/path/to/bro
Scoped 1Password Login
With a configured local op CLI, use login_form_inspect,onepassword_find_logins, and onepassword_fill_login (Pi search: 1Password login).
Login metadata is matched locally by registrable domain, like 1Password's default; a selected password is passed
privately to empty, document-bound main-frame inputs, not model-visible tool
arguments or results. Inspect/fill does not require CDP or pausing the password
manager. Filling and submitting are separate. See workflow, security boundaries,
and reproducible tests, including real CLI setup and
passkey/iframe limitations.
Browser Extension
Homebrew installs the unpacked bro extension under share/bro/extension.
bro setup browser
The command:
- finds the installed extension directory
- copies the local bro token to the clipboard when the OS clipboard tool is
available - opens
chrome://extensions/when possible - reveals the extension directory in the file manager when possible
Chromium-family browsers still require a user gesture to load unpacked
extensions. In the browser:
- Enable Developer mode.
- Choose Load unpacked.
- Select the extension directory printed by
bro setup browser. - Open bro Options.
- Paste the copied token and save.
The extension accepts only loopback ws:// server URLs. Its token is stored
locally in the extension profile and is not synced between browsers. A token
saved by an older version is moved out of sync storage on first use. Connected
status is shown only after the server authenticates the extension.
Connection settings stay collapsed after setup so the Options page can focus on
persistent inline user scripts. It can list, create, edit, and delete scripts
registered through either the UI or bro's userscripts_* tools. Enable Allow
User Scripts for the extension in chrome://extensions before using this
feature. File-backed scripts can be listed and deleted but cannot be edited in
the UI. Each script can include a short description so its purpose is visible
without opening the source. bro keeps its own local registry and restores
registered scripts if a browser extension update clears Chrome's runtime copy.
Verify the connection:
curl -fsS http://127.0.0.1:3500/status
bro call browsers_context
extensionCount should be at least 1.
browsers_context also includes best-effort native metadata undernativeInfo when the local server can identify the browser process. On macOS
and Unix-like systems this includes fields such as appName, processId,executablePath, userDataDir, profilePath, cookieStorePath, andsafeStorageService. Use nativeInfo for cookie/storage export workflows;browserInfo is only the browser identity visible to the WebExtension.
Main Tools
browser.extract: open one URL, extract visible text, close by defaultbrowser.current.extract: extract the current/default active tab in one callbrowser.batch.extract: extract many URLs in parallelbrowser.batch.run: open many URLs, read plain text, close by defaultbrowser.batch.flow: run the same ordered interaction on many URLs in
parallel, close by defaultbrowser.console.capture: open a page, trigger console output, collect logs
or exceptions, and clean up in one callbrowser.network.capture: open a page, trigger requests, and collect matching
request metadata and bounded response bodies in one callbrowser.open: create an owned background tab and return a browser/tab-pinnedtargetIdwith the first observation (observe: falsereturns at dispatch)browser.observe: scoped, bounded a11y observations with short stable refs
(kqx12) and cursor continuation; text mode for reading main-frame contentbrowser.act: compose orderednavigate,evaluate,wait, refclick/fill/select/check/scroll, andobservesteps; validate before
effects, stop on runtime failure, and report one line per stepbrowser.close: close the owned target;close: trueon a target's last
observe/act/click/fill/press does it in the same call
Legacy browser.flow.start/observe/act/finish keep their sessionId signatures
and CSS/wait/read_text steps on the same executor. See the facade
guide and interaction
internals. A dispatched action is not proof of
the application outcome; observe to verify it.
Use browser.batch.flow when each page needs the same interaction before
reading data, for example opening a reviews modal on every product page and
then returning a structured evaluate result. It keeps the repeated workflow inside
one MCP call with bounded per-URL timeouts and cleanup, instead of requiring the
agent to start, act on, and finish many separate flow sessions.
Raw browser primitives such as tabs_create, tabs_close, read_page,frames_list, javascript_tool, click_element, fill_element, andcomputer remain available for lower-level work. Ref click/scroll and realcomputer input temporarily emulate page focus without selecting a tab or
focusing its window; emulation is cleared before returning. Use tabs_activate
only when a task genuinely needs physical foreground interaction. See
Input focus for lifecycle and visibility semantics.
Use frames_list frame IDs with frame-aware flow steps for iframe interaction.
Extraction defaults are intentionally compact for agent workflows:
- text is capped at 20,000 characters for one page (
browser.extract,browser.current.extract) and 8,000 per page inbrowser.batch.extract - links are omitted unless
includeLinks:true - accessibility-tree fallback is omitted unless
includeA11y:true - screenshots default to lower JPEG quality; pass
qualityonly when visual
detail matters
Development
pnpm install --frozen-lockfile
make check
Run live dynamic-site regression tests when a local bro server and extension are
connected:
make live-test
The live tests open Reddit, LinkedIn, X, and Threads search pages in background
tabs, verify dynamic extraction, and exercise one-call request/body capture
against httpbin.
Run isolated multi-model Pi browser benchmarks frombenchmarks/pi-agent/. Keep raw sessions outside the repository because they
can contain sensitive browser content. The current tool-design findings are indocs/pi-tool-design.md.
Releases
Tagged releases build GitHub-hosted binaries for:
x86_64-unknown-linux-gnuaarch64-unknown-linux-gnux86_64-apple-darwinaarch64-apple-darwinx86_64-pc-windows-msvcaarch64-pc-windows-msvc
The Homebrew formula in xiaotianxt/tap installs the GitHub release binary for
the current macOS or Linux architecture, installs the matching browser
extension asset, and exposes brew services start bro. Releases also include an
npm-compatible tarball for the Pi adapter; the tagged Git repository is directly
installable as a Pi package.
Maintainers release from a clean main checkout withscripts/release.sh --version <version>. The script runs the checks, creates and
pushes the tag, waits for the GitHub release artifacts, updates the Homebrew tap,
and verifies the installed package.
Security Notes
bro controls a logged-in browser. Keep it local.
- The server binds to
127.0.0.1by default. - The WebSocket bridge requires the token from
~/.bro/settings.json. - Do not expose port
3500to untrusted networks. - Do not commit browser output, cookies, signed URLs, or tokens.
License
Yorumlar (0)
Yorum birakmak icin giris yap.
Yorum birakSonuc bulunamadi