kilogent-browser

kilogent-browser

MCP server that lets agents drive your real Chrome browser with existing logins and sessions via an outbound-only WebSocket extension. It exposes Playwright-compatible browser tools for navigation, clicking, typing, and snapshots.

Category
访问服务器

README

Kilogent Browser

Lend your own Chrome to a Kilogent workspace, so agents can use the sites you are already signed in to. They never see a password, and they never see a tab you opened.

The only thing you install is a Chrome extension. It dials out, so there is nothing to open on your machine — no inbound port, no tunnel, no --remote-debugging flag.

<p align="center"> <img src="docs/infographic.svg" alt="An agent drives your real local Chrome through an outbound-only MV3 extension" width="100%"> </p>

This is a fork, and that is on purpose

Upstream is navidshad/remote-browser-mcp — the open project: the extension core, the relay, and the MCP server. This repository is the Kilogent-branded build of it.

Everything Kilogent-specific lives in one directory, packages/extension/src/providers/kilogent/:

File What it does
index.js the transport itself — what upstream's registry calls
popup.js the panel — sign-in, workspaces, blocklist
auth.js signing in, and keeping the session alive
connection.js the socket to Kilogent's relay
api.js the browser's own row, written under rules
blocklist.js the second of the two blocklist levels
config.js the one URL compiled in, and the storage keys

The rule that keeps this fork alive: never edit the core. executor.js, page-scripts.js and connection.js come from upstream untouched — as do sw.js, providers/registry.js and providers/bridge/ — so git merge upstream/main stays clean. A fix that belongs to everybody goes upstream as a pull request and comes back down; only branding and the Kilogent transport are ours.

git remote add upstream https://github.com/navidshad/remote-browser-mcp.git
git fetch upstream && git merge upstream/main

Neither sw.js nor popup.js conflicts any more. Both used to, on every merge, because the transport and the sign-in UI were written into them — 390 lines where upstream had 69, and 391 where upstream had 177. Upstream grew a seam on both sides, ours moved into the directory above, and the worker and the popup shell are now byte-identical on both sides.

Our whole divergence in code is that one directory, plus one import and one entry in each of providers/index.js and providers/panels.js.

⚠️ popup.html is the small remainder. Its body is upstream's structure — same ids, same mount point — so a structural change merges; what is ours is the heading and the stylesheet, which is what a brand IS. And manifest.json, for the same reason.

📖 MAINTAINING.md is the guide for both jobs: the full update loop (including which files conflict and how to resolve them), and the complete inventory of what a rebrand touches — written from the real Lumi → Kilogent rename, so the three traps in it are ones that actually happened rather than ones that might.

Running it against your own server instead

The self-hosted path is untouched and needs no Kilogent account: point the extension at a bridge you run yourself, with a URL and a shared token. See packages/bridge-server below, and the Advanced section of the popup.

Features

  • 🔐 Browse as yourself — the agent works inside your genuine Chrome profile: existing logins, cookies, sessions, extensions, and your home IP. No credential sharing, no re-authentication, no datacenter/bot fingerprint.
  • 📡 Outbound-only, token-authenticated — the extension dials out over wss:// and authenticates with a shared token. Zero inbound ports, zero local tunnels, zero debug flags on your machine.
  • 🔌 Standard MCP, Playwright-compatible tools — one Streamable-HTTP MCP endpoint with tool names mirroring the official Playwright MCP (browser_navigate, browser_snapshot, browser_click, …). Works out of the box with Claude Code or any MCP client; agents written against Playwright MCP port over almost unchanged.
  • 👀 Live activity overlay — a colored ring + status badge appears on the page whenever the agent acts, so you always know what it's doing. It self-clears the moment the agent goes idle.
  • ✋ Take over anytime — it's your real browser window; just grab the mouse. An optional per-profile input-lock prevents you from accidentally fighting the agent mid-task, and always self-releases.
  • 🤖 Multi-agent, multi-profile — run several Chrome profiles, each dialed into its own bridge. Every MCP session gets its own Chrome tab group, so parallel agents keep their work visually separate and never touch each other's tabs.
  • 🧱 Profile-level isolation — a Chrome extension can only act within its own profile. Install it in one dedicated profile and the agent physically cannot reach your personal browsing.
  • 🧪 Snapshot-driven control — the agent reads pages as accessibility trees with stable [ref=eNN] element ids, then clicks/types by ref. Faster and more reliable than pixel-hunting screenshots (screenshots are there too when needed).
  • 🩺 Self-healing & observable — WebSocket heartbeat + chrome.alarms keepalive survive MV3 service-worker eviction, reconnect with backoff, and re-attach the debugger lazily. /health, bridge_ping, and check_local_status tell the agent whether a human/browser is actually there. Idle sessions are reaped automatically.
  • 🪶 Tiny footprint — no Playwright install, no Node process, no daemon on your machine. One unpacked MV3 extension; everything else lives on the VM.

How it works

There are two halves that meet over an authenticated WebSocket:

  • On the VM — packages/bridge-server exposes browser control to the agent as MCP and relays each command to the browser. It has two faces:
    • an MCP face on localhost:3000/mcp — the VM's Claude Code (or packages/agent) connects here and calls browser_* tools. Requires Authorization: Bearer $BRIDGE_MCP_TOKEN;
    • a WebSocket face on localhost:3002 — the extension dials in and authenticates with a shared token. cloudflared running on the VM publishes this face at a wss:// URL.
  • On your machine — the packages/extension MV3 extension runs in a dedicated Chrome profile, dials out to that wss:// URL, and drives a real tab with chrome.debugger (CDP).
   ┌──────────────────────── CLOUD VM ────────────────────────┐        ┌───────────── YOUR MACHINE ─────────────┐
   │  AI Agent  ──MCP──▶  bridge-server                        │        │  MV3 extension  (Aso Dara profile)     │
   │  (Claude Code /       ├─ MCP face  localhost:3000/mcp     │        │    │                                    │
   │   packages/agent)     └─ WS  face  localhost:3002 ◀───────┼── wss ─┼────┘  dials OUT, token-authenticated   │
   │                          published by cloudflared         │        │    chrome.debugger / CDP  ──▶  a tab   │
   └───────────────────────────────────────────────────────────┘        └────────────────────────────────────────┘
                                        ▲                                          nothing inbound on your machine
                                        └──────── agent never touches localhost; always over the network ─────────

Browser tool names mirror the official Playwright MCP, so an agent (or contract) written against Playwright MCP works with almost no changes.

Why not just…

Alternative What goes wrong
A headless browser on the VM Fresh profile with no logins, a datacenter IP, and a bot fingerprint — captchas, blocks, and 2FA prompts everywhere.
Chrome with --remote-debugging-port Chrome 136+ blocks it on your default profile, so you lose your real logins anyway — and you're running your browser with an open debug port.
Tunneling into your machine Inbound access to your laptop (tunnel daemons, port forwarding, access policies) just to reach a browser. Here the browser dials out instead — there is nothing to reach.
Sharing credentials with the agent Passwords and 2FA secrets in an agent's context. Here the agent gets a browser that is already signed in and never sees a credential.

Packages

Path What it is
packages/bridge-server VM-side bridge. MCP browser tools ⇄ WebSocket to the extension, with token auth, /health, and per-session tab tracking. Exposes browser_*, check_local_status, and bridge_ping. This is the self-host path, and the only server in this repo — if you are running this for yourself, this is the one you want. (Kilogent's own hosted relay, which the same extension talks to in Kilogent mode, is a different program and lives in Kilogent's private repo; nothing here depends on it.)
packages/extension The MV3 Chrome extension. Popup for Agent URL + token, a service worker holding one outbound WS per profile (heartbeat + chrome.alarms keepalive + reconnect backoff), and a chrome.debugger executor.
packages/agent A standalone terminal agent — a stand-in for the VM's real client. Connects to the bridge and runs a tool-use loop. LLM is pluggable (src/llm) — Gemini by default, Anthropic optional — with a no-API-key smoke test.
packages/daemon Legacy local MCP sidecar (presence + session notifications) from the pre-bridge architecture. Kept for reference; superseded by the bridge.

Browser tools

All exposed on the one bridge MCP endpoint, mirroring Playwright MCP names:

browser_navigate · browser_snapshot · browser_click · browser_type · browser_press_key · browser_take_screenshot · browser_wait_for · browser_tab_list · browser_tab_new · browser_tab_select · browser_tab_close · check_local_status · bridge_ping

browser_snapshot returns an accessibility tree whose interactable elements are tagged with [ref=eNN] ids; you pass those refs to browser_click / browser_type. Refs are only valid for that tab's latest snapshot, so re-snapshot after navigation or DOM changes.

Prerequisites

  • Node.js 22+
  • Google Chrome
  • cloudflared on the VM (brew install cloudflared / apt) — publishes the WebSocket face
  • A shared token: openssl rand -hex 32 — the same value goes on the VM and in the extension popup
  • (only for the standalone packages/agent) a Gemini API key (GEMINI_API_KEY), or set LLM_PROVIDER=anthropic + ANTHROPIC_API_KEY

Quick start

Three steps: run the bridge on the VM, load the extension in Chrome, verify. About ten minutes end to end.

npm install
npm run build

1 · VM — run the bridge

BRIDGE_ACCESS_TOKEN=<token> BRIDGE_MCP_TOKEN=<mcp-token> MCP_PORT=3000 WS_PORT=3002 \
  node packages/bridge-server/dist/index.js
# or under pm2:
BRIDGE_ACCESS_TOKEN=<token> BRIDGE_MCP_TOKEN=<mcp-token> pm2 start packages/bridge-server/dist/index.js --name rbm-bridge

Publish the WS face with cloudflared and point the VM's agent at the MCP face (http://localhost:3000/mcp). Full ingress config and DNS notes are in BRIDGE-SETUP.md.

2 · Machine — load the extension (one dedicated profile)

  1. Create a dedicated Chrome profile for the agent (e.g. "Aso Dara"), ideally an account-less local profile so Chrome sync can't copy the extension into or out of it.
  2. chrome://extensions → Developer mode → Load unpacked → select packages/extension/. Install it in only this profile, and turn off Extensions sync — that isolation is what keeps the agent off your other profiles.
  3. Open the popup and set Agent URL (wss://…/rbm-ws) + Access Token (the token from step 1) → Save & Connect. Status should read Connected to agent.
  4. Keep a window of that profile open whenever the agent may browse — background is fine, focus is not required. The first command attaches chrome.debugger and shows Chrome's "…started debugging this browser" bar; leave it in place.

3 · Verify end-to-end

# on the VM
curl -s localhost:3000/health          # → {"status":"ok",…} — liveness, no credential needed
curl -s localhost:3000/status -H "Authorization: Bearer $BRIDGE_MCP_TOKEN"   # → "extensionConnected":true
BRIDGE_MCP_TOKEN=$BRIDGE_MCP_TOKEN node packages/bridge-server/dist/test-client.js   # bridge_ping → "pong"

/health is deliberately thin. It used to report whether a browser was attached, how many tabs it held and which sessions were live — a description of a specific person's Chrome, served to anyone who could reach the port. That moved to /status, behind the token; /health stays anonymous because a tunnel health check has no credential.

Or drive the whole path with the standalone agent's no-API-key check:

npm run smoke --workspace=packages/agent

Development

npm run test:mock       # bridge round-trip against a fake-extension WS client
npm run test:profiles   # multi-profile / multi-session harness
npm run build --workspaces

Each package also has dev (tsx watch), start, and typecheck scripts.

Security notes

  • Two tokens, and they must differ. BRIDGE_ACCESS_TOKEN authenticates the extension dialling in; BRIDGE_MCP_TOKEN authenticates the agent asking for work. The bridge refuses to start if you set them to the same value — one is typed into a popup on a laptop, the other pasted into an agent config, so they leak through different accidents, and sharing one would mean a leaked agent token also lets the holder impersonate the extension and take over the browser.
  • The WS face authenticates in-band, as the first frame — a browser WebSocket cannot send CF-Access-* headers, so the WS hostname must have no Cloudflare Access policy in front of it. Every frame after that handshake is schema-validated and size-bounded (protocol.ts); the socket itself caps one frame at 12 MB.
  • The MCP face requires a bearer token and binds to loopback by default. It used to have no authentication at all, on the reasoning that loopback was the boundary — which holds until one tunnel ingress rule exists, and was never a boundary between users on a shared box. Set BRIDGE_BIND_HOST if you genuinely mean to expose it; the token is then the only thing in front of a fully logged-in Chrome.
  • Sessions are mandatory. Every call is routed to the tab group its MCP session owns, so a request that names no session is refused rather than being run against a shared "default".
  • The extension is the trust boundary. It can drive any tab in its profile via chrome.debugger; keep it in a dedicated profile with only the accounts the agent needs.
  • Keepalive is the known risk. MV3 evicts idle service workers; the WS heartbeat keeps it resident and a 1-minute chrome.alarms revives it, re-attaching chrome.debugger lazily on the next command.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选