browser-harness
Controls a real Brave browser instance over the Chrome DevTools Protocol (remote debugging on port 9222), providing tab management (new/open/switch/close), navigation, clicking, typing, key presses, scrolling, screenshots, JS evaluation, file uploads, and raw CDP calls.
Drives a complete Gmail send flow in the user's real browser: opens the Gmail login page, opens a prefilled compose URL with recipient/subject/body, attaches a PDF and verifies it stuck, previews a draft or sends with explicit confirmation, and verifies the recipient/subject in Sent Mail.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@browser-harnesssend my resume.pdf to someone@example.com via Gmail and verify in Sent"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
browser-harness MCP
One MCP server named browser-harness for your real browser — plus a Gmail send flow.
Core browser control over CDP (
new_tab,page_info,cdp,js, …) via thebrowser-harnessdaemon — no second CDP layer.Gmail flow: open login → compose → attach PDF → send → verify in Sent.
Single file: server.py. Stdio transport.
Layout
browser-harness-mcp/
server.py # the MCP server (37 tools)
SKILL.md # agent workflow (single-tab default, memory, plans)
pyproject.toml # package + deps (backend included)
README.md # this file
LICENSE # MITRelated MCP server: chrome-mcp
Install — ONE command
pip install git+https://github.com/vaibhxvvy/browser-harness-mcpThat's it. The browser backend (browser-harness, mcp, pillow) installs automatically in the same command — there is nothing else to install, no second MCP, no separate doctor CLI. Then check health from inside any MCP client with the browser_doctor tool.
From a local clone (contributors):
pip install -e .Needs Chrome/Brave/Edge with remote debugging (port 9222). The daemon auto-starts on first tool call.
MCP config — ONE entry
After the install command (no python path needed):
{
"mcpServers": {
"browser-harness": { "command": "browser-harness-mcp" }
}
}Local-dev alternative (run from source without installing):
{
"mcpServers": {
"browser-harness": {
"command": "python",
"args": ["<clone-path>/browser-harness-mcp/server.py"]
}
}
}Only ONE mcpServers entry — this server is the whole thing.
Tools
Core browser (32):
Tool | What it does |
| Open tab, returns targetId |
| Navigate current tab |
| url, title, viewport |
| Labeled interactives + coords, one call |
| Click at x, y |
| Click button/link by visible label (no coords) |
| Type into focused element |
| Fill input by CSS selector |
| Press key (+ modifiers) |
| Wheel scroll at x, y |
| PNG path + size AND the image itself (no key) |
| List tabs |
| Active tab info |
| Switch by id / URL substring |
| Close tab |
| EXPLICIT multi-tab entry (parallel tasks only) |
| Escape chrome:// pages |
| Sleep seconds |
| Wait for readyState complete |
| Wait for CSS selector |
| Wait for text in page body |
| Run JS, return value (arrows auto-invoked) |
| Raw CDP call |
| Set file input |
| Browser-less GET |
| Record actions to a directory |
| Stop recording, return directory |
| Health check (daemon + browser, replaces any doctor CLI) |
| Cross-session memory ( |
| Supervised multi-step plans (verify + retry, write gate) |
| Screenshot + question for the driving model (key only for text-only drivers) |
Gmail flow (5, all in the current tab):
Tool | What it does |
| Open Gmail login (user signs in once) |
| Open a prefilled compose URL |
| Attach a PDF, verify it stuck |
| Preview draft, or send with |
| Verify recipient/subject in Sent Mail |
Every tool returns JSON text. Failures return {"error": "..."} — never raises.
Parallel tabs (explicit only)
Default is ONE tab: single-tab tasks must never open extra tabs — navigate the current tab.
Only when the request is genuinely multi-task ("do these things at the same time"):
browser_task_tabs(urls=[...]) → [{index, targetId, url}]
browser_switch_tab(target_A) → act on A → browser_switch_tab(target_B) → act on BEvery tool call runs atomically under a server-side lock, so switched work can't interleave mid-flight. Execution across tabs is sequential, not simultaneous — the backend holds a single session, and true concurrency would land actions in wrong tabs.
Usage (Gmail end-to-end)
gmail_open_login → sign in once in the debug Chrome window
gmail_compose(compose_url="https://mail.google.com/mail/?view=cm&to=someone@example.com")
gmail_attach(pdf_path="/path/to/resume.pdf")
gmail_click_send() → {"sent": false, "needs_confirm": true, "preview": {...}}
gmail_click_send(confirm=True) → {"sent": true}
gmail_check_sent(recipient="someone@example.com", subject="Application for Prompt Engineer")Usage (low-level)
browser_new_tab("https://mail.google.com/")
browser_page_info()
browser_js("() => document.title")
browser_screenshot()Notes
Backend (
browser_harnessdaemon) is a declared dependency — the ONE install command pulls it, no separate install.Dead browser fails fast (~1s) instead of hanging 30s.
Vision is native: screenshot/see return image blocks the driving model sees directly (~1–2k tokens a shot, capped at 1280px).
BH_VISION_API_KEYis only a fallback for text-only drivers.Tool calls are lock-atomic: explicit multi-tab work can't interleave.
Read-only tools retry once on transient IPC blips; clicking/typing/sending never retry (no double side effects).
gmail_click_sendsends nothing withoutconfirm=True— first call returns a draft preview.This package owns the tab marker (🥸, applied on tab-attach tools, legacy horse stripped once). Backend marking is disabled via
BH_TAB_MARKER=0; reload an old daemon once to pick that up.If the backend is ever missing, tools return
{"error": "...run ONE command..."}instead of crashing.stdout is redirected to stderr inside tools so MCP stdio never corrupts.
NaN/Infinity/bytes/dates are normalized before JSON serialization.
Gmail Send clicks the AX
Sendbutton, falls back todiv[role=button]JS click.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted real Google Chrome MCP with per-user persistent state. Navigate, click, type, screenshot.
Browser MCP for logged-in tasks. Uses your Chrome — credentials stay local. Zero-token replay.
Automate cloud Chrome—navigate, click, type, screenshot, run code, record screen video
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables MCP clients to drive a real, logged-in Chrome browser for web automation tasks like navigation, clicking, typing, and screenshotting.41MIT
- FlicenseNot gradedqualityCmaintenanceDrive your real, signed-in Chrome browser from any MCP client, enabling browser automation such as navigation, clicking, typing, and screenshots through standard MCP tools.1-
- AlicenseBqualityAmaintenanceMCP server that drives your real Chrome/Edge/Opera browser through a Chrome extension and DevTools Protocol, preserving logins and session state, and can also perform OS-level mouse and keyboard input behind approval.552MIT
- AlicenseNot gradedqualityAmaintenanceEnables local opencode agents to control a live Chrome browser via MCP tools, including tab management, JavaScript execution, clicking, form filling, page reading, screenshots, and console log retrieval.MIT