OpenBrowser

OpenBrowser

A zero-dependency MCP server that drives a real Chrome browser through a companion extension, enabling AI agents to automate real user sessions with trusted input events, compact accessibility-tree snapshots, and 14 tools for navigation, interaction, scripting, and inspection.

Category
Visit Server

README

<div align="center">

<img src="extension/icons/icon128.png" width="96" height="96" alt="OpenBrowser">

OpenBrowser

Browser automation for AI agents โ€” in your real Chrome, with your real logins.

A Chrome extension with a side-panel UI, plus a zero-dependency MCP server, so any MCP client can drive an actual browser instead of a headless copy of one.

Website License: MIT Version Node Chrome Dependencies

๐ŸŒ openbrowser.pulse-core.com

Install ยท Tools ยท Token cost ยท Difficult sites ยท Security ยท Docs

</div>


Why this exists

Most browser automation hands your agent a fresh headless browser: signed out of everything, fingerprinted as a bot, and reading pages as either raw DOM or screenshots. OpenBrowser takes the opposite position on all three.

What it means
๐Ÿ”“ Real browser, real session Runs in your actual Chrome, with your logins, cookies, and extensions. Nothing to keep signed in.
โŒจ๏ธ Trusted input events Clicks and keystrokes go through the Chrome debugger, so they are indistinguishable from a real user's. Payment forms, login pages, and drag-and-drop all work.
๐Ÿชถ Built for token cost Pages are read as a compact accessibility tree, not screenshots or raw DOM. A full login page costs ~350 characters.
โšก Parallel by default Every tool takes a tabId. Read twenty tabs at once.
๐Ÿ“ฆ Zero dependencies No npm install. Node 18+ and Chrome 116+ is the whole requirement.
๐Ÿ  Entirely local Loopback only. No telemetry, no analytics, no outbound calls.

<a id="zero-dependencies"></a>

Zero dependencies is a feature, not a boast. npm install failing is the most common reason a local MCP server doesn't work, and it fails silently from the user's point of view. The WebSocket and MCP protocol implementations are hand-written for exactly this reason.


Install

1. Load the extension

Open chrome://extensions, turn on Developer mode, click Load unpacked, and select the extension/ folder.

2. Point your MCP client at the server

<details open> <summary><b>Claude Code</b></summary>

claude mcp add openbrowser -- node /absolute/path/to/openbrowser/mcp-server/src/index.js

</details>

<details> <summary><b>opencode</b> โ€” <code>~/.config/opencode/opencode.json</code></summary>

{
  "mcp": {
    "openbrowser": {
      "type": "local",
      "enabled": true,
      "command": ["node", "/absolute/path/to/openbrowser/mcp-server/src/index.js"]
    }
  }
}

</details>

<details> <summary><b>Anything else</b> (Cursor, Windsurf, Zed, custom clients)</summary>

Standard MCP stdio server:

{
  "mcpServers": {
    "openbrowser": {
      "command": "node",
      "args": ["/absolute/path/to/openbrowser/mcp-server/src/index.js"]
    }
  }
}

</details>

3. Check it

node mcp-server/src/index.js --health

The toolbar badge clears when Chrome is connected. If it doesn't, see Troubleshooting.


How it fits together

  Claude Code โ”€โ”
               โ”œโ”€ stdio โ”€> mcp-server โ”€ ws://127.0.0.1:8848 โ”€> Chrome extension โ”€> your tabs
  opencode โ”€โ”€โ”€โ”€โ”˜

The first server to start binds the hub port; later ones join it. So several agents can share one browser โ€” an editor agent and a CLI agent can work in the same session without fighting over it.

Everything is local. Nothing leaves your machine except the pages you ask it to visit.


The tools

Fourteen tools, grouped by action enums rather than split into forty single-purpose ones โ€” models pick an enum value far more reliably.

Tool What it does
browser_tabs list / new / close / select / reload / duplicate
browser_navigate go to a URL, back, forward, reload
browser_snapshot read the page as an accessibility tree with [ref=eN] handles
browser_find find elements by description, ranked
browser_act click, hover, drag, select, check, answer native dialogs โ€” trusted input events
browser_input type text, fill many fields at once, press keys
browser_screenshot viewport / full page / element / region, or record a GIF
browser_wait block on text, selector, URL, network idle, load
browser_eval run JavaScript in the page
browser_inspect console, network, cookies, storage, downloads, frames
browser_batch run many calls as one request, optionally across many tabs
browser_upload attach local files to a file input
browser_window resize, emulate a device, force dark mode, throttle network
browser_macro save and replay step sequences

Full parameter reference: docs/TOOLS.md.

What a page looks like

browser_snapshot renders this:

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

356 characters โ€” roughly 90 tokens. The same page is ~4,000 tokens as raw accessibility JSON and ~1,500 as a screenshot.

A whole login in one call

{
  "tool": "browser_batch",
  "args": {
    "steps": [
      { "tool": "browser_navigate", "args": { "url": "app.example.com/login" } },
      { "tool": "browser_input", "args": {
          "fields": [
            { "ref": "e2", "value": "ada@example.com" },
            { "ref": "e3", "value": "correct horse battery staple" }
          ]}},
      { "tool": "browser_act", "args": { "action": "click", "ref": "e5" } },
      { "tool": "browser_wait", "args": { "for": "text", "value": "Dashboard" } }
    ]
  }
}

One round-trip instead of eight.


Keeping token cost down

The design assumes tokens are the scarce resource:

  1. Snapshots, not screenshots. ~20x cheaper, and refs are directly actionable. Screenshot only to verify something visual.
  2. mode: "diff" in loops. After the first snapshot, ask only what changed.
  3. Actions return their own delta. After a click you usually already know what changed, so no follow-up snapshot is needed.
  4. selector to scope. On a dense page, read the one region you care about.
  5. browser_batch for known flows. Collapses N round-trips into one.
  6. browser_macro for repeated flows. Derive the flow once, replay for the cost of a single call.

Difficult sites

The cases that usually break browser automation, and what handles them here:

Problem How it is handled
Site ignores synthetic clicks Trusted events via the Chrome debugger
Content inside iframes All frames are read; refs carry their frame (f2e5)
Cross-origin iframe coordinates Offsets cascade via postMessage so clicks land correctly
Element under a cookie banner Detected before clicking, and reported with what is covering it
Shadow DOM / web components Open shadow roots are pierced when reading and hit-testing
React ignores a typed value Native setter + the event pair frameworks actually listen for
Hidden file inputs behind "Browse" The real input[type=file] is located from the visible control
Drag-and-drop libraries Interpolated, eased movement above the drag threshold
SPA re-render invalidates a ref Refs re-resolve through a stored selector before failing
Element is off screen Auto-scrolled into view, then waited until it stops moving
CAPTCHA Detected and reported. Not bypassed โ€” that needs a human
Click opens a new tab or popup Reported with the new tab's id, rather than looking like nothing happened
Tab is in the background Foregrounded before input; Chrome silently discards clicks aimed at hidden tabs
Click seems to do nothing Distinguishes "the app has not reacted yet" from "the click missed"
Native JS dialog (alert/confirm/beforeunload) Reported with the dialog's text; answered with browser_act action:"dialog" accept:true/false

Every row above is a bug that was found by driving the extension against a real site, not a hypothetical. The write-ups are in docs/SESSION-2026-08-02.md and docs/SESSION-2026-08-03.md.


Side panel

Click the toolbar icon or press <kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>U</kbd>.

  • Control โ€” tabs, quick actions, element search
  • Tools โ€” run any tool by hand and see exactly what an agent would get
  • Macros โ€” inspect, run, and delete saved sequences
  • Activity โ€” every call with timing and errors

The panel calls the same dispatcher the MCP server does, so it is the fastest way to debug a flow: try it by hand, then hand it to the model.


Configuration

Extension options (chrome://extensions โ†’ Details โ†’ Extension options):

Setting Default Notes
Hub port 8848 Must match the server's --port
Connect automatically on Reconnects on browser start
Trusted input events on Turning this off makes many sites ignore the agent
Highlight elements on Outlines elements as they are used
Capture bodies off Request/response bodies; large, often sensitive
Snapshot budget 20,000 chars Truncation limit
Blocklist identity providers Never automated
Allowlist empty If non-empty, only these sites are automated

Security

  • Binds loopback only (127.0.0.1). Nothing is exposed to your network.
  • No telemetry, no analytics, no outbound calls of any kind.
  • The blocklist ships with identity providers on it, because an automation mistake against an SSO flow is expensive and hard to undo.
  • CAPTCHAs are reported, never solved or bypassed.
  • The debugger permission is what makes trusted input possible. It is broad โ€” read docs/ARCHITECTURE.md for exactly what it is used for, and turn it off in options if you would rather not grant it.

โš ๏ธ Treat an agent with browser access as having your logged-in privileges. Use the allowlist when running unattended.


Troubleshooting

<details> <summary><b>Badge shows <code>โ—‹</code>, health says not connected</b></summary>

node mcp-server/src/index.js --health

The hub only exists while an MCP client has the server running. To test standalone: npm run hub. </details>

<details> <summary><b>"Cannot attach to this page"</b></summary>

Chrome blocks extensions on chrome:// pages, the Web Store, and other extensions' pages. Navigate somewhere else. </details>

<details> <summary><b>"DevTools is open on this tab"</b></summary>

DevTools and the extension cannot both own the debugger. Close DevTools, or use another tab. </details>

<details> <summary><b>Refs keep going stale</b></summary>

The page re-renders aggressively. Use browser_find immediately before acting, or browser_batch so the whole sequence runs before the page can change under you. </details>

<details> <summary><b>Service worker went idle</b></summary>

Expected under MV3. It respawns and reconnects on its own; the first call afterwards may take a moment. </details>

<details> <summary><b>A change to <code>extension/</code> did nothing</b></summary>

Chrome caches extension files. Anything under extension/ needs chrome://extensions โ†’ reload before it takes effect. Anything under mcp-server/ is picked up when the MCP client next starts the server. </details>


Development

npm test          # 75 tests: WebSocket framing, MCP protocol, round trip, formatting
npm run preview   # UI preview + 68 browser tests at :8850
npm run hub       # hub only, verbose
npm run icons     # regenerate icon PNGs

npm run preview serves two things that need a DOM: the side-panel UI at /, and the accessibility-tree assertions at /test/a11y-browser.html.

Layout:

extension/
  background/   service worker: bridge, router, CDP, recorder, frames, formatting
  content/      injected: accessibility tree, actions, frame offsets
  sidepanel/    the UI
  options/      settings
mcp-server/src/ ws.js (hand-rolled RFC 6455), hub.js, mcp.js, tools.js
docs/           capabilities, tools reference, architecture, test checklist
site/           the source of openbrowser.pulse-core.com (static, no build step)
Doc What it is for
docs/CAPABILITIES.md What the fourteen tools can do in combination โ€” parallel tabs, macros, retroactive network capture, trusted input, iframe reach
docs/TOOLS.md Full parameter reference
docs/ARCHITECTURE.md Why the pieces are split this way
docs/TESTING.md Manual checklist for the parts that need a real browser
docs/SESSION-2026-08-02.md First real-site hardening pass: what broke, what was fixed, what is still unproven
docs/SESSION-2026-08-03.md Second pass โ€” OAuth, popups, checkout forms, and the backgrounded-tab input bug

CLAUDE.md carries the hard rules and the platform behaviours that each cost a real bug to discover. TODO.md has the open work with reproduction details.


License

MIT โ€” see LICENSE.

<div align="center"> <br>

openbrowser.pulse-core.com

</div>

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured