Skip to main content
Glama

Cat Burglar

A stealth browser MCP for agents. It gets in, reads the room, and leaves the DOM tidy.

License: MIT Node MCP Benchmark

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.

Architecture

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 smoke

Add 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

navigate

Opens a URL and waits for the page to settle

snapshot

Returns URL, title, controls with stable refs, and visible text

click / fill / select

Acts on a ref, selector, text, or ARIA role

change observation

The action returns only the added, changed, removed, or text delta

memory learn

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

patchright (default)

Protected sites, logins, anti-bot work

Full Chromium memory

chromium

Devtools, console, traces, PDF, local app testing

Full Chromium memory

obscura

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

local

1,800 chars

50

4,000

300 chars

yes

flash

2,800

70

6,000

400

yes

frontier

8,000

160

14,000

900

no

auto

Flash-safe until per-model probing lands

yes

Use open({ profile }) or set BROWSER_MCP_PROFILE.

The numbers

Benchmark

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_private is set.

  • Cloud metadata endpoints stay blocked even with private-network access on.

  • Origin allow and block lists accept exact origins or https://*.example.com wildcards.

  • 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 needs confirm:true after 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.js

Config 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 review

Credits

Source

License

What we used

Obscura

Apache-2.0

Ref-token snapshot ideas, markdown and extract semantics, SSRF posture, tracker list data

Playwright MCP

Apache-2.0

Accessibility-first snapshots, persistent profiles, origin and file policy

Chrome DevTools MCP

Apache-2.0

Performance metrics and traces, network and console inspection

Patchright

Apache-2.0

Stealth Playwright driver

browser-use

MIT

Agent action vocabulary and humanized interaction ideas

unslop

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 tools
backbackC

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 dataA
Read-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 MarkdownA
Read-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 PDFC
Read-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.

screenshotScreenshotA
Read-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 pageA
Read-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 statusA
Read-only

Report the active engine, URL, tabs, capture buffers, resolved config, and which engines are available on this machine.

Inputs: no named parameters.

stealthStealth checkA
Read-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.

waitWaitA
Read-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

    B3.3/5.0

    Scored across 30 tools

    Disambiguation4/5

    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.

    Naming Consistency3/5

    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.

    Tool Count3/5

    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.

    Completeness4/5

    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

    ActivityMaintained
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      A
      quality
      D
      maintenance
      A 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.
      61
      22 npm
      32
      MIT
    • A
      license
      Not graded
      quality
      B
      maintenance
      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.
      374 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Policy-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
    • A
      license
      Not graded
      quality
      A
      maintenance
      An 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