Skip to main content
Glama
README.md
# Browser-bridge-MCP

[![License: MIT](https://img.shields.io/badge/License-MIT-FFB020.svg)](LICENSE)
[![Node.js](https://img.shields.io/badge/Node.js-%E2%89%A520-2FD08A.svg)](https://nodejs.org)
[![MCP](https://img.shields.io/badge/Model_Context_Protocol-compatible-4FA8FF.svg)](https://modelcontextprotocol.io)
[![Platform](https://img.shields.io/badge/Browser-Chrome%20%7C%20Edge-07080A.svg)](#)
[![H0RNET](https://img.shields.io/badge/H0RNET-cybersecurity-E0334B.svg)](https://h0rnet.eu)

> **Part of the [H0RNET](https://h0rnet.eu) system** — H0RNET cybersecurity · OSINT · Penetration Testing · Digital Forensics.
> Built and maintained by **Mario Đukić (`h0rnet` / `blackkat`)**.

A local, user-controlled browser bridge for [MCP](https://modelcontextprotocol.io)-compatible AI agents. It lets an agent such as Claude Code drive a **real browser you own** — your tabs, your sessions, your logins — but only within limits you set explicitly: a saved domain allowlist, per-session tab isolation, loopback-only networking, and separate tokens for the extension and for each agent.

The MVP targets Chromium-based **Chrome and Edge**. Firefox is not supported because the extension relies on Chromium-specific APIs such as `chrome.debugger` and `tabGroups`. The extension exposes tab inspection, visible-page text, screenshots, navigation, CSS-selector clicks, text entry, scrolling, common key presses, and bounded DevTools-style diagnostics.

## Why it exists

H0RNET is an independent European cybersecurity practice focused on authorized offensive security, OSINT investigations, and digital forensics. A large part of that work happens **in a browser**: reconnaissance, reproducing a reported bug, inspecting a target's DOM and network traffic, or walking through a multi-step authenticated flow.

Browser-bridge-MCP turns those browser actions into tools an AI agent can call, without handing control to a cloud service or a throwaway browser profile. Everything runs on `127.0.0.1`, the agent is confined to hosts you are authorized to test, and the human stays in charge of connecting, approving domains, and recording. It is a precision instrument for authorized testing — **not** a mass-automation or detection-evasion tool.

## What's in the box

| Part | Path | Role |
| --- | --- | --- |
| **Browser extension** (MV3) | `extension/` | Runs in Chrome/Edge, speaks to the relay over a local WebSocket, and performs the actual browser actions. |
| **MCP + relay server** | `server/` | `global.js` is the launcher/config CLI and HTTP+relay host; `index.js` defines the MCP tools and the WebSocket relay. |
| **Launcher** | `run.sh` | Finds Node 20+, starts the server, and configures agents, credentials, and upload directories. |
| **Tests** | `test/` | Node test-runner coverage for the MCP contract and the global server. |

## How it works

```
  MCP agent (Claude Code, VS Code, …)
        │  HTTP (Streamable) + Bearer token, 127.0.0.1 only
        ▼
  server/global.js  ── per-agent MCP endpoints ──┐
        │                                         │
        │  WebSocket relay (ws://127.0.0.1), relay token
        ▼                                         │
  extension/background.js  ◀────────── one tab group per MCP session
        │  chrome.debugger / tabs / scripting
        ▼
  Your real Chrome / Edge tabs (allowlisted hosts only)
```

1. **You** start `./run.sh`. On first run it creates a config under `~/.config/browser-bridge-mcp/` holding a random **relay token** and port. No agents and no browser access exist yet.
2. You register one or more agents (`./run.sh add <name>`). Each gets its **own** loopback MCP port and bearer token.
3. You load the unpacked extension, paste the relay token into its popup, set the **domain allowlist**, save, and **Connect session**. The extension registers a stable Browser ID with the relay.
4. An MCP agent lists connected browsers, selects one explicitly, and calls browser tools. Each MCP session gets an isolated tab group; it can only see and control tabs it opened, on allowlisted hosts.
5. When you are done, disconnect the session from the popup. Nothing runs when the session is off.

## Permission and privacy model

- The extension is disconnected by default. The user enters the local server token and explicitly connects from the extension popup.
- Each MCP client session gets its own browser tab group. Agents can only list, read, and control tabs opened in their own session, even when they share one extension relay.
- Every installed extension profile registers a stable browser ID. An MCP session must list connected browsers and explicitly select one; a disconnected browser is never silently replaced.
- While connected, the MCP agent can read and control only HTTP/HTTPS tabs whose host is in the saved allowlist. The allowlist applies to tab listing, reading, screenshots, navigation, clicks, text entry, DevTools, and JavaScript. An allowed host also includes its subdomains.
- The initial allowlist is `localhost`, `127.0.0.1`, `h0rnet.lab`, and `h0rnet.eu`. Add only domains you own or are explicitly authorized to test, then choose **Save settings**. The saved token and domain list persist across popup closes and browser restarts.
- On allowlisted hosts, `browser_devtools_evaluate` runs JavaScript in the page's DevTools execution context. It can read or change page data available to JavaScript and perform side effects, including network requests. It is not safe to run untrusted code.
- `browser_devtools_network_bodies` can return text request and response bodies observed during a short capture window. Bodies can contain credentials, tokens, personal information, or other secrets. Headers and cookies are not returned directly. Captures are limited to 5 seconds, up to 100 requests, 20,000 characters per body, and 100,000 body characters total.
- JavaScript evaluation is limited to 10,000 input characters, a 5-second CDP execution timeout, and a 50,000-character result. These limits do not make untrusted scripts safe.
- DOM/source, accessibility, console, and network data can contain sensitive page content; only allow hosts you own or are explicitly authorized to test. Disable the browser session when not using it.
- The MCP relay and each agent-specific MCP HTTP endpoint bind only to `127.0.0.1`. The relay requires its own random token and accepts WebSocket origins from browser extensions only. Each agent endpoint has a different bearer token.
- Page text is returned on request and limited to 40,000 characters. Password field values are not included in page snapshots. No page content is written to disk or logged by the bridge.
- The `debugger` permission enables browser-like input events and may display a browser debugging notice. It can interfere with other DevTools/debugger sessions.
- `browser_recording` is off by default. While explicitly recording, successful page actions save screenshots and an action log under `extension/recordings/`. Screenshots contain whatever is visible in the page; the log omits typed values, JavaScript expressions, DOM contents, and audio. Stop and delete recordings with `browser_recording`, or remove their folders yourself. Recording data is ignored by Git.
- Local file upload is disabled until the user explicitly approves a directory with `./run.sh allow-file-dir <absolute-directory>`. Uploads are restricted to regular files beneath those approved directories; symbolic links are resolved before checking.
- The optional `cdp` server launches a separate, temporary Chrome profile. It does not attach to the user's normal browser profile. CDP performance, Lighthouse, network-body, extension/PWA, and heap tools are exposed only through that separately configured MCP server. The Chrome DevTools MCP backend uses Apache-2.0 licensed `chrome-devtools-mcp` 1.8.0; usage statistics and CrUX URL reporting are disabled. Screencast uses the project-local `ffmpeg-static` 5.3.0 binary, licensed GPL-3.0-or-later; its install script downloads the platform binary.
- Browser-internal pages, extension stores, and other restricted URLs cannot be controlled.
- Treat the connected MCP client as trusted: it can view private tabs and perform actions as the user for the duration of the session.

## Run the global MCP server

Requires Node.js 20 or newer. From the project folder run:

```sh
./run.sh
```

On first start, the launcher creates a fresh configuration with no MCP agents and saves only the relay token and port under `~/.config/browser-bridge-mcp/agents.json` (or `$XDG_CONFIG_HOME/browser-bridge-mcp/agents.json`). The directory and file are restricted to the current user. Existing settings under the previous `browser-mcp-bridge` directory are moved automatically on first start, preserving agent tokens and ports. The relay token is required to authenticate the browser extension; no agent token or test agent is created automatically. After restarting the computer, run `./run.sh` again; saved agent ports and tokens remain unchanged.

In another terminal, add your own separately authenticated agent, then restart `./run.sh` so it listens on that agent's MCP port:

```sh
./run.sh add claude
./run.sh add vscode 8768
./run.sh credentials
```

Each agent gets a distinct MCP port and bearer token. The relay has its own token and port. Register an agent with any MCP client that supports Streamable HTTP and custom request headers; for example, Claude Code:

```sh
claude mcp add --transport http \
  --header "Authorization: Bearer <AGENT_TOKEN>" \
  claude http://127.0.0.1:<AGENT_PORT>/mcp
```

Replace the placeholders with the values from `./run.sh credentials`. Configure the agent before or after starting `./run.sh`; when adding an agent to a running service, restart `./run.sh` so it listens on the new port. The service waits for MCP clients and the extension. Keep all tokens private and do not expose these loopback services on a network interface.

## Load the extension

1. Open `chrome://extensions` in Chrome or `edge://extensions` in Edge.
2. Enable Developer mode and choose **Load unpacked**.
3. Select this project's `extension` directory.
4. Run `./run.sh credentials` and copy the **Relay token** and **Relay port** into the extension popup. Save the settings and choose **Connect session**.
5. Configure each MCP client with its own URL and **Bearer token** as described above.
6. Call `browser_list_tabs` from an MCP client to verify the connection.

Each connected browser profile registers with the shared relay. Each agent has its own HTTP port and token, while browser extensions use the separate relay token. Agent and extension settings persist across browser restarts.

After updating the extension files, open the extensions page and click **Reload** on Browser-bridge-MCP before testing the changes.

## MCP tools

- `browser_list_browsers`, `browser_select_browser`, `browser_selected_browser` (explicit, sticky browser selection per MCP session)
- `browser_session_context`, `browser_list_tabs`, `browser_open_tab`, `browser_close_tab` (isolated per MCP session)
- `browser_select_tab` (focus one of this session's tabs)
- `browser_get_page` (semantic interactive snapshot, field state/options, stable element identities and fresh `ref`s; optional `tabId`)
- `browser_click_ref`, `browser_type_ref` (use a fresh ref from `browser_get_page`)
- `browser_fill_form` (batch up to 50 fields using fresh refs)
- `browser_drag_ref` (drag between fresh element refs)
- `browser_dialog` (accept/dismiss JavaScript dialogs)
- `browser_history` (back, forward, reload)
- `browser_viewport` (bounded responsive viewport emulation and reset)
- `browser_upload_file` (only after approving a local directory with `./run.sh allow-file-dir`)
- `browser_screenshot` (captures a session-owned tab; optional `[x, y, width, height]` region in viewport CSS pixels)
- `browser_mouse` (coordinate click/right-click/double-click/hover/drag)
- `browser_navigate` (HTTP/HTTPS URLs only; optional `tabId`)
- `browser_click` (CSS `selector`; optional `tabId`)
- `browser_type` (CSS `selector`, `text`; optional `tabId`)
- `browser_scroll` (`direction`, optional `pixels` and `tabId`)
- `browser_press_key` (`Enter`, `Tab`, `Shift+Tab`, `Escape`, `Backspace`, `Delete`, `Space`, or an arrow key; optional `tabId`)
- `browser_devtools_dom` (bounded DOM outline; allowlisted host)
- `browser_devtools_source` (selected element `outerHTML`, input values removed; allowlisted host)
- `browser_devtools_accessibility` (bounded accessibility tree; allowlisted host)
- `browser_devtools_styles` (computed styles and layout geometry for a CSS `selector`; allowlisted host)
- `browser_devtools_performance` (CDP counters and navigation timing; allowlisted host)
- `browser_devtools_capture` (console and network metadata observed during 250–5000 ms; allowlisted host)
- `browser_devtools_evaluate` (JavaScript in the page context; allowlisted host; 10,000-character input and 5-second timeout)
- `browser_devtools_network_bodies` (text request/response bodies during 250–5000 ms; allowlisted host; bounded output)
- `browser_read_console`, `browser_read_network` (short, bounded capture; headers/cookies excluded)
- `browser_batch` (up to 10 sequential actions, stops at the first error)
- `browser_recording` (`start`, `stop`, `status`, `delete`; local screenshots and metadata, explicit opt-in)
- `browser_wait_for_selector` (wait for a visible CSS `selector` for up to 10 seconds; allowlisted host)
- `browser_wait_for_text` (wait for visible page text; allowlisted host)
- `browser_assert_page` (checks optional expected title, URL, and visible text; allowlisted host)

### Select a browser

Connect the extension in each browser profile using the same relay token and port. The popup shows a persistent **Browser ID**. In each MCP session:

1. Call `browser_list_browsers`.
2. Call `browser_select_browser` with the exact ID to use.
3. Use browser tools; the selection remains bound to that browser for the MCP session.

If that browser disconnects, calls fail rather than being routed to a different browser. Select another browser explicitly to continue.

### Optional full Chrome DevTools MCP toolset

For Lighthouse, performance traces, heap snapshots, deep network inspection, screencast, PWA, WebMCP, third-party developer tools, and Chrome extension management, add a separate MCP server. It starts an isolated temporary Chrome profile and does not share cookies with the extension-backed browser:

```json
{
  "mcpServers": {
    "chrome-devtools": {
      "command": "/absolute/path/to/this/project/run.sh",
      "args": ["cdp"]
    }
  }
}
```

The CDP server exposes the full Chrome DevTools MCP 1.8.0 toolset (including its optional categories), with Chrome selected explicitly and page-ID routing enabled. It turns off usage statistics and CrUX URL reporting. Per MCP roots, file-writing tools are confined to client-approved roots; without roots, the upstream server restricts output to the OS temporary directory. Add `--headless=true` to the `args` list if a visible browser window is not wanted. Screencast tools are enabled when `ffmpeg` is installed.

This CDP mode is Chrome-only; the upstream DevTools MCP does not guarantee Edge support. The extension-backed MCP tools have been tested with Chrome and Edge. Firefox is installed on this machine but is not compatible with this extension's Chromium `debugger` and `tabGroups` APIs; the project does not claim Firefox support.

## Development checks

```sh
npm run check
npm test
```

`npm run check` runs `node --check` over the server and extension scripts plus `bash -n run.sh`; `npm test` runs the Node test runner over `test/*.test.js`.

## Authorized use only

This tool exists for **authorized** security work. Use it only against systems you own or have explicit, written permission to test. The domain allowlist, loopback-only binding, and explicit human connect step are guardrails, not a license to test third-party systems. You are responsible for staying within the scope of your engagement and applicable law.

## Author

Built and maintained by **Mario Đukić** — founder of **H0RNET**, an independent European cybersecurity specialist working in authorized penetration testing, OSINT investigations, and digital forensics.

- Web: [h0rnet.eu](https://h0rnet.eu)
- GitHub: [@h0rnet-1101](https://github.com/h0rnet-1101)
- LinkedIn: [mario-dukic-h0rnet](https://www.linkedin.com/in/mario-dukic-h0rnet/)
- Handle: `h0rnet` / `blackkat`

Browser-bridge-MCP is part of the broader **H0RNET system** of security tooling. Design language (the "Black & Amber" theme), naming, and branding follow h0rnet.eu.

## License

Released under the **MIT License** — see [`LICENSE`](LICENSE). © 2026 Mario Đukić (H0RNET).

The project's own source is MIT-licensed. It installs third-party backends with their own terms, which are **not** relicensed by this project:

- [`chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp) 1.8.0 — Apache-2.0 (used only by the optional `cdp` server).
- [`ffmpeg-static`](https://github.com/eugeneware/ffmpeg-static) 5.3.0 — the downloaded FFmpeg binary is GPL-3.0-or-later (used only for optional screencast).
- [`@modelcontextprotocol/sdk`](https://github.com/modelcontextprotocol/typescript-sdk), [`ws`](https://github.com/websockets/ws), [`zod`](https://github.com/colinhacks/zod) — see each package for its license.