Atlas / MCP servers / wxtsky / Byob

ByobBLOCK

mcp/wxtsky/byob

Bring Your Own Browser — let your AI agent use the Chrome you already have open

Verdict
BLOCK
Grade
D
Trust score
69 /100
Exposed tools
25 15r · 6w · 4d
Transport
stdio
License
MIT
Stars
132
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

Bring Your Own Browser — let your AI assistant use the Chrome you already have open.

[](LICENSE) [](https://modelcontextprotocol.io) [](https://developer.chrome.com/docs/extensions/mv3/intro/) [](CHANGELOG.md)

English · 中文

byob is a local MCP server that lets AI coding tools (Claude Code, Cursor, Cline, Windsurf, etc.) directly control your real Chrome — the one where you're already logged into everything.

"read my Twitter timeline and summarize the top 5 posts"
"google 'mcp protocol spec', click the first result, read the page"
"take a screenshot of example.com"
"grab my GitHub session cookie so I can curl with it"
"open my Gmail tab and tell me how many unread"
"fill in this form with my details and submit it"

Compared with tools that attach over Chrome's remote-debugging port (DevTools MCP, agent-browser, Playwright --cdp): byob is an extension, so there's no debugging port to open, no "Allow remote debugging?" prompt on every connection, and nothing else on your machine can hijack your logged-in browser through it.

Install

Quick install (recommended)

curl -fsSL https://raw.githubusercontent.com/wxtsky/byob/main/install.sh | bash

On Windows, run the same command from Git Bash or MSYS2. The script checks prerequisites (Node.js ≥ 20, bun, Chrome/Edge/Brave), clones the repo, builds eve

Read from source at commit a291a871b308OBSERVED · 2026-10-07
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control.

claude-code
claude mcp add shared -- npx -y @byob/[email protected]
claude-desktop
{
  "mcpServers": {
    "shared": {
      "command": "npx",
      "args": [
        "-y",
        "@byob/[email protected]"
      ]
    }
  }
}
03

Exposed tools (25)

15 read · 6 write · 4 destructive. Blast radius: 4 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
browser_batchwriteSeveral steps in one call, e.g. fill + submit: [{tool:
browser_clickreadClick by ref (from snapshot/find), CSS selector, or viewport x+y. Real mouse events. ${ACT}
browser_clipboardwriteRead or write plain text on the system clipboard (explicit calls only).
browser_consolereadConsole output, uncaught errors and browser warnings of a tab, buffered since byob first touched it.
browser_dialogreadGet or answer (accept/dismiss + promptText) a JS dialog. Never auto-accepted; actions report when one opens.
browser_download_imageswriteSave the images of a page (or url) to disk, skipping icons smaller than minWidth×minHeight.
browser_dragdestructiveDrag from one ref/selector/x+y to another. Supports HTML5 drag-and-drop as well as mouse-driven sliders and sortable lists.
browser_emulatereadDevice/viewport, color scheme, reduced motion, geolocation, timezone, locale, offline, extra headers; reset:true clears all.
browser_evaluatereadEvaluate an expression (or a function body with return) in the page. With ref/selector the element is available as
browser_findreadLocate elements semantically and get refs: role(+name), text, label, placeholder, alt, title or testId (substring, case-insensitive unless exact). With action (click/fill/check/...) acts on match #nth right away — no snapshot needed.
browser_hoverwriteMove the mouse over a ref / selector / x+y (menus, tooltips). snapshot:true shows what appeared.
browser_inspectreadelement: box, visibility, state, value, attributes, match count, computed styles. performance: Web Vitals + timing.
browser_navigatereadOpen a URL (a new background tab, then reused — never the user
browser_networkwriterecord → act → stop (summary, or json/har file). intercept: block / mock / modify requests; unintercept to stop.
browser_press_keyreadPress a key or combo on the focused element (or on a ref/selector, focused first): Enter, Escape, Tab, ArrowDown, Backspace,
browser_readreadPage content: text (all visible), markdown (main article, else whole page), html, links or tables. outline:true = headings only; filter = sections mentioning a phrase; scope with ref/selector. For finding things to click use snapshot.
browser_screenshotreadViewport (default), fullPage, element (ref/selector) or clip; returns the image and saves it. annotate:true labels the snapshot refs on it. format:
browser_scrollreaddirection up/down/left/right (optional amount px) or to top/bottom — for the page, or inside the scroll container given by ref/selector. A target without direction scrolls it into view. Reports the scroll position so you know when the end is reached.
browser_selectdestructiveSelect option(s) of a native <select> by value or visible label. For custom dropdowns click the control, then the option.
browser_snapshotreadThe page as an outline of roles and names (iframes included) — the main way to see a page. Interactive elements get refs like [ref=e12] for click/type/etc., valid until the page navigates. interactive:true = controls only; diff:true = only changes since the last snapshot; scope with ref/selector.
browser_storagedestructiveget / set / clear cookies (default: the tab URL) or local/sessionStorage — e.g. export a login cookie for curl.
browser_tabsreadTabs of the user
browser_typedestructiveFill an input / textarea / contenteditable (replaces content; clear:false appends). No target = the focused element. slowly:true for autocompletes, submit:true presses Enter. ${ACT}
browser_upload_filewriteSet absolute local file paths on an <input type=file> (hidden inputs work: target them with selector
browser_waitreadWait (AND of all given): element state, text appears/gone, URL match, load/networkidle, JS predicate fn (BYOB_ALLOW_EVAL=1), ms delay. Actions already auto-wait — use this for things that happen later.
04

Trust audit

BLOCKgrade D · trust 69/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (3 observation(s))
Network
declared (7 observation(s))
Shell
declared (4 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (25)

CRITICALObfuscation / stealth · obf.decode_then_exec · CWE-506, CWE-94
plugins/byob/servers/byob-mcp.mjs:136
atob( ... new Function(
Why it matters. decodes a payload and executes it
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/bridge/src/upload-server.ts:193
endpoint: `http://127.0.0.1:${port}/upload`,
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
browser_drag, browser_select, browser_storage, browser_type
Why it matters. 4 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/extension/lib/__tests__/page-scripts.test.ts:21
expect(() => new Function(`return (${src});`)).not.toThrow();
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/extension/lib/__tests__/page-scripts.test.ts:31
expect(() => new Function(`return ${READABILITY_INSTALL};`)).not.toThrow();
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/extension/lib/__tests__/sensitive.test.ts:7
const hasSensitiveValue = new Function(
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/bridge/bin/byob.ts:17
const repoRoot = path.resolve(here, '../../..');
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/superpowers/plans/2026-04-25-read-tools-trio-implementation.md:629
endpoint: `http://127.0.0.1:${port}/upload`,
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/superpowers/plans/2026-04-25-read-tools-trio-implementation.md:630
readabilityEndpoint: `http://127.0.0.1:${port}/readability`,
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
docs/superpowers/specs/2026-04-25-read-tools-trio-design.md:166
2. extension 把 outerHTML POST 到 bridge 的 `http://127.0.0.1:<port>/readability`(沿用 `download_images` 走过的 loopback HTTP)
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
e2e/harness.ts:143
primary: `http://127.0.0.1:${a.port}`,
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
packages/extension/lib/handlers/intercept-start.ts:376
const bin = atob(b64);
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
packages/extension/lib/handlers/screenshot.ts:34
const buf = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
LOWObfuscation / stealth · obf.decode_call · CWE-506, CWE-94
packages/extension/lib/handlers/screenshot.ts:127
const bytes = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
e2e/package.json
@modelcontextprotocol/sdk
Why it matters. 1 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/bridge/package.json
commander, @types/node, tsx, typescript
Why it matters. 4 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/extension/package.json
zod, @types/chrome, typescript, wxt
Why it matters. 4 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/mcp-server/package.json
@modelcontextprotocol/sdk, undici, zod, @types/node, tsx, typescript
Why it matters. 6 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
shared/package.json
zod, typescript
Why it matters. 2 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/superpowers/plans/2026-04-25-read-tools-trio-implementation.md:694
`/get-console-logs` and `/extract-table` are simple `routeFor(...)` passthroughs. `/read-markdown` has to spin up the upload-server (for `/readability`) and pass `readabilityEndpoint + secret` into th
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/superpowers/plans/2026-04-25-read-tools-trio-implementation.md:1098
3. POST `{ html, sourceUrl, options }` to `readabilityEndpoint?secret=...` (bridge passes the endpoint + secret in params).
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
LOWPrompt injection · prompt.transfer_instruction · CWE-94, CWE-1427
docs/superpowers/specs/2026-04-25-byob-design.md:382
`browser_screenshot` 这种动辄 MB 级的 PNG 不走 Native Messaging。bridge 临时开 `127.0.0.1:<random>` HTTP server,把 endpoint + secret 通过 Native Messaging 告诉扩展,扩展直接 `fetch(endpoint, { method:'POST', body: pngBytes }
Why it matters. an instruction to move sensitive data to an outside destination
Fix. remove; a skill never needs the user's secrets off the machine
INFOPrompt injection · prompt.credential_read · CWE-94, CWE-1427
docs/superpowers/plans/2026-04-25-byob-implementation.md:3850
// We can't read process.env in extension; gate via chrome.storage.local for parity.
Why it matters. asks the agent to read credentials
INFOSupply chain · prompt.pipe_to_shell · CWE-829, CWE-1357
README.md:44
curl -fsSL https://raw.githubusercontent.com/wxtsky/byob/main/install.sh | bash
INFOSupply chain · prompt.pipe_to_shell · CWE-829, CWE-1357
README.zh-CN.md:44
curl -fsSL https://raw.githubusercontent.com/wxtsky/byob/main/install.sh | bash

Gates applied: critical_finding, no_behavioural_pass.

Audited 2026-10-07 · audit v0.4.1 · source sha a291a871b308full audit observations/trust-audit/mcp-server/wxtsky__byob.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-07a291a871b308BLOCKD69first audit
06

Questions

What is the Byob MCP server?

Bring Your Own Browser — let your AI agent use the Chrome you already have open

What tools does Byob expose?

25 in total: 15 read-only, 6 that write, and 4 that can delete or overwrite (browser_drag, browser_select, browser_storage, browser_type). Every one is listed on this page with its risk.

Is Byob safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (69/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on. Separately from the audit: 4 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does Byob need?

No credential environment variables were found in its source, so it appears to need none.

How does Byob run?

It speaks stdio, so it runs as a local process your client starts. It is published on npm as @byob/shared at 0.5.0.

How current is this page?

The grade is for one exact copy of the source (a291a871b308), read on 2026-10-07. The repository is watched and re-audited when it changes.

Advertisement