Dev Browser
FreeNot checkedBrowser automation through Chrome DevTools Protocol with AI-friendly DOM snapshots, element targeting, and multi-tab management for web testing and automation w
About
Browser automation through Chrome DevTools Protocol with AI-friendly DOM snapshots, element targeting, and multi-tab management for web testing and automation workflows.
README
An MCP (Model Context Protocol) server that lets OpenCode (and other MCP clients) drive a real Chrome/Chromium tab locally by sending Chrome DevTools Protocol (CDP) commands—without requiring Chrome to be launched with --remote-debugging-port.
It solves: “I want an agent to click/type/navigate/screenshot an existing local browser session” using a lightweight extension bridge + local relay.
Architecture overview
This project runs an MCP server over stdio. Under the hood it talks to a local relay that connects to a Chrome/Chromium extension.
Extension-mode relay + endpoints
The relay exposes:
ws://HOST:PORT/extension
The browser extension connects here (one connection at a time).ws://HOST:PORT/cdp
A CDP-like WebSocket endpoint. The MCP server connects here and sends CDP JSON messages.
Tools like dev_browser_goto, dev_browser_click, etc. ultimately send CDP commands (e.g. Page.navigate, Runtime.evaluate, Page.captureScreenshot) over /cdp. The relay forwards those commands to the extension, and forwards CDP events back to connected clients.
Prerequisites
- Node.js >= 18
- Chrome/Chromium with the dev-browser extension installed (the extension must be running and able to connect to
ws://HOST:PORT/extension) - OpenCode installed and configured to run MCP servers
Setup
npm install
npm run build
This produces dist/ and a runnable entrypoint.
OpenCode configuration
OpenCode supports both a global config and a project config. In both cases, add an MCP server entry named dev_browser.
Global config: ~/.config/opencode/opencode.json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dev_browser": {
"type": "local",
"command": ["node", "/Users/<you>/Code/devtools/dev-browser-mcp/dist/index.js"],
"enabled": true,
"environment": {
"HOST": "127.0.0.1",
"PORT": "9222",
"RELAY_MODE": "auto"
}
}
}
}
Project config: ./opencode.json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"dev_browser": {
"type": "local",
"command": ["node", "./dist/index.js"],
"enabled": true,
"environment": {
"HOST": "127.0.0.1",
"PORT": "9222",
"RELAY_MODE": "auto"
}
}
}
}
Notes:
- No secrets/tokens are required.
- The MCP server communicates over stdio; OpenCode will launch it via the
commandarray.
Environment variables
HOST(default:127.0.0.1)
Host for the relay HTTP/WS server.PORT(default:9222)
Port for the relay HTTP/WS server.RELAY_MODE(default:auto)
Controls whether the MCP server starts or attaches to the relay:auto: probehttp://HOST:PORT/first; if a relay is already running, attach. Otherwise start a relay.- If starting the relay fails with
EADDRINUSE, it probeshttp://HOST:PORT/again (longer timeout). If the relay is reachable, it attaches; otherwise it rethrows the original error.
- If starting the relay fails with
start: always start its own relay (will fail on port conflicts).connect: never start; require an existing relay athttp://HOST:PORT/(throws if unreachable).
Usage examples (tool calls)
Typical flow: ensure the extension is connected → open/select a tab → navigate → interact → snapshot/screenshot.
1) Wait for the extension to connect
{
"tool": "dev_browser_ensure_extension_connected",
"input": { "timeoutMs": 30000, "pollIntervalMs": 250 }
}
2) Open (or reuse) a named tab
{
"tool": "dev_browser_page_open",
"input": { "name": "my-tab" }
}
3) Navigate
{
"tool": "dev_browser_goto",
"input": {
"url": "https://example.com",
"waitUntil": "load",
"timeoutMs": 30000
}
}
4) Snapshot (AI-friendly DOM outline)
{
"tool": "dev_browser_snapshot",
"input": {}
}
The snapshot includes snapshotRef identifiers you can use for click/type.
5) Click / type
Click by CSS selector:
{
"tool": "dev_browser_click",
"input": { "selector": "button[type='submit']" }
}
Click by snapshotRef (from dev_browser_snapshot output):
{
"tool": "dev_browser_click",
"input": { "snapshotRef": "e123" }
}
Type by CSS selector:
{
"tool": "dev_browser_type",
"input": { "selector": "input[name='q']", "text": "hello", "clearFirst": true }
}
Type by snapshotRef:
{
"tool": "dev_browser_type",
"input": { "snapshotRef": "e456", "text": "hello", "clearFirst": true }
}
6) Screenshot
{
"tool": "dev_browser_screenshot",
"input": { "fullPage": false, "saveToFile": true }
}
If saveToFile=true (default), it writes a PNG under:
./.opencode/dev_browser/
…and returns the file path (plus the image content).
Tool list
dev_browser_relay_status— Get relay status (wsEndpoint,extensionConnected,mode); inautoit will start or attach.dev_browser_ensure_extension_connected— Wait untilextensionConnected=true(polls relay/).dev_browser_pages_list— List named pages registered in the relay.dev_browser_page_open— Get or create a named tab via the relay and select it for subsequent actions.dev_browser_page_delete_mapping— Delete a named page mapping in the relay.dev_browser_goto— Navigate the selected tab to a URL.dev_browser_click— Click an element by CSS selector orsnapshotRef(fromdev_browser_snapshot).dev_browser_type— Type into an input by CSS selector orsnapshotRef(fromdev_browser_snapshot).dev_browser_wait_for_selector— Wait for a selector on the selected tab.dev_browser_evaluate— Evaluate JavaScript in the selected tab context.dev_browser_screenshot— Take a PNG screenshot; writes to./.opencode/dev_browserand returns the file path.dev_browser_snapshot— Return an AI-friendly snapshot (YAML-ish) for the selected tab.
Relationship to dev-browser (SawyerHood/dev-browser)
This project was built to expose the same core idea as SawyerHood/dev-browser to MCP clients (OpenCode): drive a real browser with persistent state and provide LLM-friendly DOM snapshots.
What we reuse / align with
- Extension-mode CDP relay concept: dev-browser has an “extension mode” where a local relay bridges CDP messages between an extension (
chrome.debugger) and automation clients. - Named pages: both systems expose a
POST /pagesabstraction to create/activate a named tab and return atargetId. - Snapshot refs: dev-browser’s snapshot approach uses an injected script that returns a YAML-ish outline with stable
[ref=eN]markers.
What’s different here
- Protocol surface: dev-browser is distributed as a Claude Code plugin/skill; this repo is a standalone MCP server designed for OpenCode.
- Control path: instead of shipping a “skill client” API, this exposes discrete MCP tools (
dev_browser_goto,dev_browser_click, etc.) that send CDP commands. - Relay ownership for multi-OpenCode: this MCP supports
RELAY_MODE=autoso multiple OpenCode instances can attach to a single relay process without crashing onEADDRINUSE. - Deterministic tab targeting: actions are scoped to a specific Chrome tab via
targetId+Target.attachToTargetsessions so separate OpenCode instances can reliably control different named tabs.
Troubleshooting
extensionConnected=false
- Ensure Chrome/Chromium is running and the dev-browser extension is installed/enabled.
- The extension must be able to connect to
ws://HOST:PORT/extension. - Run
dev_browser_relay_statusto confirm the relay is reachable and to seeextensionConnected.
EADDRINUSE / port conflicts
PORT=9222is commonly used by other tooling (including Chrome remote debugging).- Fix by choosing a different port:
- set
PORT(and keep it consistent for both relay + extension) - or set
RELAY_MODE=connectif you intentionally run a relay elsewhere and want to attach.
- set
Multiple OpenCode instances / tab naming
- Prefer explicit, unique tab names via
dev_browser_page_open(e.g."myproject-admin","myproject-patient"). - If you don’t pass
pageNameto tools, they operate on the “last selected” page; avoid collisions by always opening/selecting a named page per workspace/agent.
Where screenshots are written
- By default, screenshots are saved to:
./.opencode/dev_browser/
- If you don’t see files, confirm your current working directory (OpenCode project root) and that
saveToFile=true.
Installing Dev Browser
This server has no published package — it is built from source. Open the repository and follow its README.
▸ github.com/benkraus/dev-browser-mcpFAQ
Is Dev Browser MCP free?
Yes, Dev Browser MCP is free — one-click install via Unyly at no cost.
Does Dev Browser need an API key?
No, Dev Browser runs without API keys or environment variables.
Is Dev Browser hosted or self-hosted?
Self-hosted: the server runs locally on your machine via the install command above.
How do I install Dev Browser in Claude Desktop, Claude Code or Cursor?
Open Dev Browser on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Related MCPs
Playwright
Browser automation, scraping, screenshots
by MicrosoftPuppeteer
Browser automation and web scraping.
by modelcontextprotocolopentabs-dev/opentabs
Plugin-based MCP server + Chrome extension that gives AI agents access to web applications through the user's authenticated browser session. 100+ plugins with a
by opentabs-devrobhunter/agentdeals
1,500+ developer infrastructure deals, free tiers, and startup programs across 54 categories. Search deals, compare vendors, plan stacks, and track pricing chan
by robhunterCompare Dev Browser with
Not sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All browse MCPs
