Cat Burglar
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., "@Cat Burglar Open news.ycombinator.com and take a snapshot of the front page"
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.
Cat Burglar
A stealth browser MCP for agents. It gets in, reads the room, and leaves the DOM tidy.
Cat Burglar is a local Model Context Protocol server for browser work. One agent session gets three browsers: patched stealth Chromium, stock Chromium for devtools, and Obscura's 43 MB Rust engine. Pages come back as compact snapshots and diffs. Sites are remembered between runs. High-impact clicks pass through a policy gate.
Quick start
git clone https://github.com/DrMkdaddy/cat-burglar.git
cd cat-burglar
npm install
npm run build
npm run install:obscura # optional, 43 MB fallback engine
npm run smokeAdd the server to your MCP client. OpenCode V2 uses mcp.servers:
{
"mcp": {
"servers": {
"catburglar": {
"type": "local",
"command": ["node", "/absolute/path/to/cat-burglar/dist/index.js"],
"environment": {
"BROWSER_MCP_ALLOW_PRIVATE_NETWORK": "1",
"BROWSER_MCP_OBSCURA_PATH": "/absolute/path/to/obscura"
},
"timeout": { "startup": 45000, "execution": 600000 }
}
}
}
}The server name is catburglar on purpose. OpenCode already has a built-in browser toolset, and the two names collide in Code Mode. Rename the key if you prefer, but keep it distinct from browser.
Then ask your agent:
Open the pricing page, take a snapshot, and tell me what changed after I switch to annual billing.
Related MCP server: OpenBrowser
The 30 second tour
Step | What happens |
| Opens a URL and waits for the page to settle |
| Returns URL, title, controls with stable refs, and visible text |
| Acts on a ref, selector, text, or ARIA role |
change observation | The action returns only the added, changed, removed, or text delta |
| Saves the recent tool sequence as a workflow for that origin |
Refs stay stable while the element remains in the DOM. A new snapshot does not renumber them, so an agent can act on a ref it learned earlier. If the element is gone, the action fails with a stale-ref error instead of clicking a clone.
Three browsers, one session
Engine | Use it for | Cost |
| Protected sites, logins, anti-bot work | Full Chromium memory |
| Devtools, console, traces, PDF, local app testing | Full Chromium memory |
| Low-memory scraping, high-volume reads, tracker blocking | About 43 MB |
Switch per session:
{ "engine": "chromium", "restart": true }A running browser cannot change engines in place. Stop it and open again.
Observation that sends only what changed
Full DOM dumps are expensive and noisy. Cat Burglar returns a compact control list, then a diff after each action. Navigation collapses to one URL line. Filling a field is silent unless you ask for an observation. Clicking, selecting, uploading, and pressing keys return a bounded change summary.
Model profiles set the budgets:
Profile | Snapshot | Controls | Markdown | Change summary | Diff by default |
| 1,800 chars | 50 | 4,000 | 300 chars | yes |
| 2,800 | 70 | 6,000 | 400 | yes |
| 8,000 | 160 | 14,000 | 900 | no |
| Flash-safe until per-model probing lands | yes |
Use open({ profile }) or set BROWSER_MCP_PROFILE.
The numbers
Mode | Success | Tool calls | Observation chars | Wall time |
Full snapshots | 12/12 | 80 | 30,029 | 15.37 s |
Diff + change observation | 12/12 | 68 | 21,057 | 13.86 s |
That is 29.9% less text and 15% fewer calls with the same success rate. Content-heavy tasks dropped 40% to 46%. The flaky-UI task dropped 66%. One run, profile flash, engine chromium, Node 26. Raw JSON: bench/results/2026-11-09-flash.json. Reproduce with npm run bench.
The first version of this feature made output larger. It returned a rich observation after every action, including fills. Measurement caught it. Silent fills, URL-only navigation lines, and bounded diffs fixed it.
Compared with the field
Measured on the same machine and the same page. Tool count and schema bytes matter when a client does not use Code Mode. RSS is the full process tree after the first snapshot. First navigation includes browser launch.
Server | Tools | Schema KB | Startup | Snapshot chars | RSS | First nav |
Cat Burglar | 30 | 24.3 | 169 ms | 553 | 999 MB | 953 ms |
Playwright MCP | 25 | 21.1 | 789 ms | 841 | 1174 MB | 438 ms |
Chrome DevTools MCP | 32 | 28.9 | 880 ms | 859 | 1028 MB | 490 ms |
Obscura MCP | 38 | 13.3 | 3 ms | 572 | 43 MB | 16 ms |
Snapshot size is not a quality score. The accessibility trees differ. All Chromium engines pay full-browser memory.
Capability | Cat Burglar | Playwright | Chrome DevTools | Obscura | BrowserMCP / BrowserTools | Browserbase / browser-use / Skyvern |
General interaction | Strong | Strong | Strong | Partial | Partial | Strong |
Devtools and perf | Partial | Partial | Strong | None | Partial / Strong | None |
Stealth | Strong | None | None | Strong | Strong, real Chrome | Strong, cloud |
Your logged-in Chrome | Partial | Partial | Partial | Partial | Strong | Partial |
Cloud, proxies, CAPTCHA | None | None | None | Waitlist | None | Strong |
Diff and change observation | Strong | None | None | None | None | None |
Site memory and workflows | Strong | None | None | None | None | Partial |
Origin, injection, and risk policy | Strong | Partial | None | Partial | Partial | Partial |
Reproducible eval harness | Strong | None | None | None | None | None |
OpenCode Code Mode fit | Strong | Partial | Partial | Partial | Partial | Strong |
Short version: Playwright has the ecosystem and cross-browser reach. Chrome DevTools has the deepest debugging. Obscura has the smallest footprint. BrowserMCP and BrowserTools use the Chrome you are already in. Browserbase, browser-use, Skyvern, and Hyperbrowser handle cloud scale and natural-language automation. Cat Burglar is the one that combines stealth engine choice, adaptive observation, site memory, safety guards, and a local benchmark in one server.
What it does
Lifecycle: open, close, navigate, back, forward, reload, status, tabs
Reading: snapshot, markdown, extract, evaluate, screenshot, pdf
Interaction: click, fill, type, press, select, hover, scroll, upload, wait
State: cookies, storage, stealth, memory
Diagnostics: network, console, perf
extract runs in five modes: links, tables, jsonld, meta, text, and a CSS map for custom fields. perf covers web vitals, CDP runtime metrics, slowest resources, and Chrome traces. trace_stop writes the full JSON trace and returns long tasks, top scripts, and layout totals.
Safety
SSRF guard on navigation and every request. DNS is resolved before loading, redirects re-check, and results are cached for 60 seconds.
Private, loopback, link-local, CGNAT, multicast, and reserved ranges are blocked unless
allow_privateis set.Cloud metadata endpoints stay blocked even with private-network access on.
Origin allow and block lists accept exact origins or
https://*.example.comwildcards.file://is off by default.Page-derived output carries an untrusted-content marker. The server instructions put page content below the user and system prompt in the trust hierarchy.
High-impact targets such as delete, pay, transfer, send, publish, and deactivate are flagged. With
BROWSER_MCP_RISKY_ACTION_POLICY=ask, the action needsconfirm:trueafter user approval.Site memory is agent-authored only. Page text is never ingested, refs are dropped, and typed values become
{{value}}placeholders.Tracker blocking uses Obscura's 3,520-domain PGL list plus common analytics hosts.
These are guardrails, not a sandbox. A model that ignores the trust boundary can still be influenced by a page.
Research
The design follows a review of web-agent work from 2023 to 2026: evaluation error, observation alignment, change observation, memory, planning, prompting, and prompt injection. The full review with 40 sources is in docs/research/2026-11-browser-agent-research.md.
The benchmark and the LLM runner are in bench/. Use npm run bench:compare for the server table above and npm run bench:llm for a model-level run. The LLM runner accepts --server ours|playwright|chrome-devtools|obscura, so the same 12 tasks can produce a head-to-head result with your model.
Develop
npm run build # tsc -> dist
npm test # 28 unit tests
npm run smoke # MCP stdio end-to-end
npm run bench # full vs adaptive
npm run bench:compare # tool surface, startup, RSS
npm run bench:llm # model-level run, OpenAI-compatible endpoint
BROWSER_MCP_DEBUG=1 node dist/index.jsConfig file: ~/.config/browser-mcp/config.json. Example: cat-burglar.config.example.json. Environment variables override it.
Layout:
src/
config.ts env and config file
profiles.ts local / flash / frontier budgets
security.ts SSRF, origins, tracker blocking, route guard
risk.ts high-impact action classification
memory.ts per-origin hints and workflows
diff.ts stable-ref control and text diffs
session.ts engines, tabs, capture, observation, traces
page-scripts.ts snapshot, markdown, stealth probe, vitals
markdown.ts Readability-lite HTML to Markdown
tools/ one module per tool group
data/ generated tracker blocklist
bench/
fixture-server.mjs hermetic app with state verification
tasks.mjs 12 deterministic tasks
run.mjs full vs adaptive report
compare-servers.mjs measured server comparison
llm-agent.mjs optional model policy adapter
docs/research/ evidence reviewCredits
Source | License | What we used |
Apache-2.0 | Ref-token snapshot ideas, markdown and extract semantics, SSRF posture, tracker list data | |
Apache-2.0 | Accessibility-first snapshots, persistent profiles, origin and file policy | |
Apache-2.0 | Performance metrics and traces, network and console inspection | |
Apache-2.0 | Stealth Playwright driver | |
MIT | Agent action vocabulary and humanized interaction ideas | |
MIT | Writing checks that removed the em dashes and stock phrasing from this README |
The tracker list is the only copied data asset. See NOTICE.
Status
Version 0.2.0. The local benchmark covers 12 tasks. Public WebArena, Online-Mind2Web, and prompt-injection runs are next. Issues and counterexamples are welcome, especially from models other than the one this was built against.
License
MIT. See LICENSE.
Available Tools
30 toolsbackbackC
Go back in history.
Inputs: no named parameters.
clickClickA
Click an element. Target one of: ref (preferred), selector, text, or role+name. Humanized mouse movement is used by default. Returns a compact change observation so you rarely need a second snapshot.
Inputs: ref, name, role, text, +7 more.
closeClose browserA
Close the browser, all tabs, and any Obscura child process.
Inputs: no named parameters.
consoleConsole logB
Read console messages and page errors captured since launch. Note: Patchright stealth mode disables the console API by design; use engine=chromium when console output matters.
Inputs: level, limit, action, filter.
cookiesCookiesC
Get, set, or clear cookies for the current browser context. get can be limited to URLs.
Inputs: action (required), urls, cookies.
evaluateEvaluate JavaScriptA
Evaluate a JavaScript expression in the page and return its value as JSON. Promises are awaited. Use for data extraction or page state, not for navigation (prefer navigate).
Inputs: expression (required), max_chars.
extractExtract structured dataARead-only
Deterministic extraction from the current page. Modes: links, tables, jsonld, meta, selector (CSS map), text. No LLM involved; pair with snapshot/markdown when you need to locate a selector first.
Inputs: mode (required), limit, selector, max_chars.
fillFill inputA
Set an input/textarea/contenteditable value in one call (fires input + change). Target one of: ref (preferred), selector, text, or role+name.
Inputs: value (required), ref, name, role, +5 more.
forwardforwardC
Go forward in history.
Inputs: no named parameters.
hoverHoverA
Move the mouse over an element (menus, tooltips). Target one of: ref (preferred), selector, text, or role+name.
Inputs: ref, name, role, text, +4 more.
markdownRead as MarkdownARead-only
Extract the main readable content of the current page as Markdown (article/main detection, boilerplate removal, absolute links). Best for articles, docs, and research. Use snapshot instead when you need to interact.
Inputs: max_chars.
memorySite memoryA
Per-origin memory for selector hints, notes, and reusable workflows. Entries are agent-authored only (never page text). navigate injects the top hints automatically. Use learn after a successful run to save the recent action sequence as a workflow; verify selectors before replaying them.
Inputs: action (required), id, kind, name, +4 more.
networkNetwork logB
Inspect requests made by pages in this browser session: status, type, size, duration, and failures. URLs are redacted according to BROWSER_MCP_REDACT_PARAMS.
Inputs: type, limit, action, filter, +2 more.
openOpen browserA
Launch the agent browser. Default engine is patchright (stealth Chromium). Use engine=chromium for full-fidelity devtools/perf/local testing, or engine=obscura for a lightweight Rust engine (lower memory, strongest tracker blocking). Reusing an open browser keeps cookies and tabs; pass restart=true to relaunch with new options.
Inputs: url, proxy, engine, locale, +10 more.
pdfExport PDFCRead-only
Render the current page to PDF and save it under the artifact directory.
Inputs: path, format, landscape, print_background.
perfPerformanceB
Performance tools: web vitals (LCP/CLS/FCP/TTFB/long tasks), CDP runtime metrics, slowest resources, a combined overview, or a Chrome trace. trace_start → do work → trace_stop returns a summary and writes the full trace JSON to the artifact directory. Use engine=chromium for full devtools fidelity.
Inputs: action (required), limit.
pressPress keyB
Press a keyboard key (Enter, Escape, Tab, ArrowDown, Control+A…). Optionally focus a target first.
Inputs: key (required), ref, confirm, observe, +1 more.
reloadreloadA
Reload the active tab.
Inputs: no named parameters.
screenshotScreenshotARead-only
Capture the viewport, full page, or a single element as PNG. The image is returned inline; an optional path saves a copy under the artifact directory.
Inputs: path, selector, full_page.
scrollScrollB
Scroll the page by direction/amount, to the top/bottom, or bring an element into view. Humanized wheel events by default.
Inputs: ref, amount, selector, direction.
selectSelect optionA
Choose one or more values in a select element. Target one of: ref (preferred), selector, text, or role+name.
Inputs: values (required), ref, name, role, +5 more.
snapshotSnapshot pageARead-only
Compact view of the current page: URL, title, actionable elements with refs (e1, e2…), control states, and visible text. Refs stay stable while the element remains in the DOM; a new snapshot does not renumber them. Use diff=true (or since=sN) to see only changes since the last observation. Prefer refs over CSS selectors.
Inputs: diff, since, max_chars, include_text, +1 more.
statusBrowser statusARead-only
Report the active engine, URL, tabs, capture buffers, resolved config, and which engines are available on this machine.
Inputs: no named parameters.
stealthStealth checkARead-only
Fingerprint self-check on the current page: navigator.webdriver, UA-CH, plugins, chrome runtime, native function masking, canvas/WebGL, timezone/locale, screen, and permissions. Returns a verdict plus concrete warnings. Run after opening a protected site.
Inputs: no named parameters.
storageStorage stateA
Export or import cookies + localStorage as a Playwright storage-state file. Use this to persist logins across browser restarts. Import applies cookies immediately and writes localStorage through CDP.
Inputs: action (required), path, state, include_state.
tabsTabsB
List, create, switch, or close tabs. Switching preserves page state and JS globals.
Inputs: action (required), url, index.
typeType textA
Type into a field with humanized per-character delays. Target one of: ref (preferred), selector, text, or role+name. Use fill for long values or speed; use type for keystroke-driven UIs.
Inputs: text (required), ref, name, role, +7 more.
uploadUpload filesA
Attach local files to a file input. Paths are resolved from the current directory; ~ is expanded.
Inputs: paths (required), ref, name, role, +5 more.
waitWaitARead-only
Wait for a selector or text to become visible, or wait a fixed number of milliseconds. Prefer this over sleep loops after triggering async UI.
Inputs: text, state, selector, timeout_ms.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 30 tools
Most tools have clearly distinct purposes, and the descriptions actively disambiguate the risky pairs (fill vs type, snapshot vs markdown vs extract vs evaluate, click target modes). The main residual overlap is among the several read/extract tools, where an agent must reason about which output format fits, but the guidance is explicit enough to make a correct choice.
All names are single lowercase words with no camelCase/snake_case mixing, which is readable and predictable in style. However, the set mixes action verbs (navigate, click, fill, evaluate) with bare nouns that bundle multiple operations (tabs, cookies, storage, memory, network, perf), so there is no single verb_noun convention to extrapolate from.
At 30 tools this is on the heavy side, and some consolidation is plausible (back/forward/reload could be one history tool; cookies/storage partially overlap, as do screenshot/pdf/snapshot). Still, the surface is a full browser automation stack with stealth, perf, network, and memory subsystems, so nearly every tool maps to a real capability rather than padding.
Coverage is broad: navigation, interaction, extraction, media capture, session persistence, diagnostics, stealth checks, and workflow memory are all present, so there are few dead ends. Gaps are minor but real — no dialog/alert handling, no iframe/frame-scoped operations, and no drag-and-drop or multi-select gesture support.
Maintenance
Related MCP Connectors
Official Browserless MCP server: browser automation, scraping, screenshots and PDFs for AI agents.
Stealth web browser for agents: search, fetch, click, download and type in persistent MCP sessions.
Hosted Web Crawler MCP server for Claude, ChatGPT and Cursor, with each action switched per account.
Browz hosted MCP (free public beta): let an AI app drive your own Browz browser profiles from anywhere. Connect https://mcp.gobrowz.com/mcp and sign in with your Browz account (OAuth) or an agent token. Each call is relayed to the Browz app on your computer, which must be online with Remote control on and have a hardware security chip (Mac Secure Enclave or TPM 2.0). 17 tools: profiles, tabs, navigate, snapshot, act, wait, screenshot. No cookies, script, downloads or stored sign-ins remotely.
Related MCP Servers
- AlicenseAqualityDmaintenanceA high-performance browser automation MCP server that provides AI agents with a fast, persistent Chromium instance via Playwright. It features reference-based element interaction, snapshot diffing, and manual handoff capabilities to handle complex tasks like CAPTCHAs.6122 npm32MIT
- AlicenseNot gradedqualityBmaintenanceA 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.374 npmMIT
- AlicenseNot gradedqualityCmaintenancePolicy-gated MCP server for local-first browser automation, enabling agents to drive isolated Chromium sessions via snapshots, revision-bound refs, typed actuation, scripts, and telemetry receipts.Apache 2.0
- AlicenseNot gradedqualityAmaintenanceAn MCP server that exposes browser-drive tools over a local endpoint, letting AI agents launch and control isolated browser profiles with their own cookies, fingerprints, and proxies, then navigate, click, type, extract, screenshot, evaluate JS, and manage tabs and cookies. Session state persists across launches so authenticated workflows carry over between AI sessions.MIT