Your real browser, your real session
Runs in the Chrome you already use — logged in, configured, extensions installed. No separate headless instance to keep signed in.
OpenBrowser is a Chrome extension plus a zero-dependency MCP server that lets any AI agent — Claude Code, opencode, Cursor — drive your real browser. Your logins, your cookies, real trusted input events. No headless instance, no install step.
Every design decision here came from a real failure on a real site — payment forms that ignore synthetic clicks, iframes three levels deep, pages that cost 4,000 tokens to read.
Runs in the Chrome you already use — logged in, configured, extensions installed. No separate headless instance to keep signed in.
Clicks and keystrokes go through the Chrome debugger, so they carry isTrusted: true. Sites that reject synthetic events — Stripe, Google, drag-and-drop — simply work.
Pages become a compact accessibility tree with actionable refs — ~350 characters instead of ~4,000 tokens of raw DOM or a screenshot.
Every tool takes a tabId. Fan one call across twenty tabs, and watch them collect into labelled, colour-coded Chrome tab groups.
Hand-written WebSocket and MCP implementations. No npm install to break, nothing to build. Node 18+ and Chrome 116+ is the whole requirement.
Console and network activity are recorded continuously into ring buffers, so browser_inspect answers questions about bugs that already happened — no reproduction needed.
The design assumes tokens are the scarce resource. A 6,000-element page becomes ~350 characters of tree — with every element directly actionable.
app.example.com/login · "Sign in · Example" · tab 481 · 1280x800
banner
link "Example" [e1] /
main
heading "Sign in" h1
form
textbox "Email" [e2] required
password "Password" [e3] required
checkbox "Remember me" [e4] unchecked
button "Sign in" [e5]
link "Forgot your password?" [e6] /reset
After the first snapshot, ask only for what changed — perfect for watching a status flip or a list populate.
After a click you usually already know what changed, so no follow-up snapshot is needed. The single largest token saving in the design.
browser_batch collapses a whole login into one call. browser_macro replays a flow forever for the cost of one call.
The first MCP server to start binds the hub port; later ones join it as peers. Several agents can work in the same session without fighting over the browser.
Everything is local. Nothing leaves your machine except the pages you ask it to visit.
Tools are grouped by action enums rather than split into dozens of single-purpose ones — models pick an enum value far more reliably.
Fourteen tools is a small surface. The interesting things come from how they combine — and all of this is real behaviour in the current build, not a roadmap.
browser_batch with a parallel array fans a sequence of steps across N tabs concurrently, results labelled per tab. Each workstream gets a coloured Chrome tab group, so a human watching the tab strip sees three labelled jobs instead of a wall.
browser_macro saves a step sequence with {{placeholders}} and replays it for the cost of a single call. Re-deriving a login or a search-and-extract flow means five calls and reasoning; replaying it is one call and none.
Ring buffers record from the moment a tab is touched, so browser_inspect answers questions about something that already went wrong — including CSP violations page JS never logs — without reproducing it.
All pointer and keyboard events carry isTrusted: true via CDP. Drag-and-drop, canvas and map apps, and file uploads that never expose an <input type=file> in the DOM — including Meta Business Suite and Google Drive — all work.
Content scripts run in every frame; refs from nested frames carry an fN prefix and route back automatically. A checkout page whose card fields are a Stripe iframe three levels deep reads as one tree, and clicks land on the right pixel.
Device presets, arbitrary viewports, forced light/dark, user-agent override, and network throttling down to offline. Automation keeps running while the window is minimized, so long jobs get out of your way.
text, no_text, selector, no_selector, ref_gone, url, network_idle, load, time. ref_gone — wait until the spinner disappears — is not expressible as a selector on most SPAs.
Obstruction by a cookie banner is reported, naming the covering element. CAPTCHAs are surfaced and never bypassed — that needs a human, and the tool says so instead of looping. Truncation is always reported, because “no matches” and “no matches in the part I read” mean different things.
Binds to 127.0.0.1. Nothing is exposed to your network.
No analytics, no outbound calls of any kind. Everything is local.
Identity providers are never automated — a mistake against an SSO flow is expensive and hard to undo.
A blocking challenge must be solved by a human, and the tool says so instead of trying to bypass it.
Treat an agent with browser access as having your logged-in privileges. Use the site allowlist when running unattended — and turn off the debugger permission in options if you would rather not grant it.
Load the extension, point your MCP client at the server, check it. No npm install, no build step.
Open chrome://extensions, enable Developer mode, click Load unpacked and select the extension/ folder.
Pick your client below and copy the snippet. The server is a plain node process — nothing to install.
Run --health. The toolbar badge clears when Chrome is connected, and you are driving a real browser.
claude mcp add openbrowser -- node /absolute/path/to/openbrowser/mcp-server/src/index.js
{
"mcp": {
"openbrowser": {
"type": "local",
"enabled": true,
"command": ["node", "/absolute/path/to/openbrowser/mcp-server/src/index.js"]
}
}
}
{
"mcpServers": {
"openbrowser": {
"command": "node",
"args": ["/absolute/path/to/openbrowser/mcp-server/src/index.js"]
}
}
}
node mcp-server/src/index.js --health
Node 18+ · Chrome 116+
Star it, fork it, read the architecture notes, or just load it and watch an agent sign into your own inbox.