Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
1566bac
Initial commit with task details
konard Jun 24, 2026
ec8968f
feat: add personal browser targets
konard Jun 24, 2026
0c56a86
Revert "Initial commit with task details"
konard Jun 24, 2026
25fac54
Add browser share relay and Edge extension artifact
skulidropek Jun 24, 2026
3b4f970
Add zip artifact for Edge share extension
skulidropek Jun 24, 2026
79fe825
Connect Edge from control panel
skulidropek Jun 25, 2026
08cc457
Keep shared Edge relay sessions alive
skulidropek Jun 25, 2026
6883148
Add shared browser activity audit panel
skulidropek Jun 25, 2026
4abd3b2
Separate shared browser tabs by window profile
skulidropek Jun 25, 2026
2251cc4
Render shared tabs as window groups
skulidropek Jun 25, 2026
f1828b3
Make shared window groups collapsible
skulidropek Jun 25, 2026
2ddfdf0
Add browserctl CLI automation
skulidropek Jun 25, 2026
3b4b0dd
Use rbc project-first CLI syntax
skulidropek Jun 25, 2026
9bee3f0
Allow direct JavaScript eval in rbc
skulidropek Jun 25, 2026
626d36f
Add Playwright runner to rbc
skulidropek Jun 25, 2026
c4bcf13
Support Playwright subset for shared browsers
skulidropek Jun 25, 2026
79dde14
Resolve rbc targets from browser pool
skulidropek Jun 25, 2026
f8db525
chore: add edge share extension zip
skulidropek Jun 25, 2026
f65f60e
chore: update edge share extension zip
skulidropek Jun 25, 2026
0f75e00
feat: add shared browser action recorder overlay
skulidropek Jun 25, 2026
0d1be1b
feat: add recorder inspect and replay modes
skulidropek Jun 26, 2026
a096eb4
feat: add playwright crx edge share extension
skulidropek Jun 26, 2026
82e4f4a
feat: run shared playwright through extension
skulidropek Jun 27, 2026
67a02f2
fix: register extension relay on service worker startup
skulidropek Jun 27, 2026
2464b01
fix: timeout shared browser commands
skulidropek Jun 27, 2026
e7209cc
fix: adapt shared playwright crx application
skulidropek Jun 27, 2026
3c5d0ad
fix shared edge reconnect and relay routing
skulidropek Jun 27, 2026
bd4ddfd
fix shared crx playwright runner
skulidropek Jun 27, 2026
7f91ac4
fix shared crx recorder playback target
skulidropek Jun 27, 2026
de2733b
feat: add generic browser pool listing
skulidropek Jun 29, 2026
70ab370
refactor: separate browser extension and panel assets
skulidropek Jul 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ tungstenite = "0.24"
name = "browser-connection"
path = "src/bin/browser-connection.rs"

[[bin]]
name = "browser-connection-relay"
path = "src/bin/browser-connection-relay.rs"

[dev-dependencies]
tempfile = "=3.10.1"
proptest = "=1.4.0"
119 changes: 119 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Installs two binaries:
```text
docker-git-browser-connection # start/status browser container
browser-connection # MCP stdio server for Codex/Hermes
browser-connection-relay # WebSocket relay for browser share links
```

## Start browser manually
Expand Down Expand Up @@ -46,6 +47,116 @@ args = ["--project", "dg-my-project"]
```

Use `browser-connection`, not `npx @playwright/mcp`. The MCP server starts/reuses the same Rust-managed browser container automatically.
It also starts a local browser/noVNC control panel by default; `browser_list` reports its
`controlPanelUrl`.

Optional panel controls:

```toml
[mcp_servers.playwright]
command = "browser-connection"
args = ["--project", "dg-my-project", "--control-port", "6888"]
```

Use `--no-control-panel` for headless tests or when another process owns the chosen port.

## Share a remote Edge by link

For a remote Microsoft Edge where you do not want SSH, VPN, or an exposed CDP port, use the Edge
share extension plus the relay:

```bash
browser-connection-relay --bind 127.0.0.1:8765
```

In Edge, load `extension/edge-share` as an unpacked extension, open the extension popup, keep the
relay URL as `http://127.0.0.1:8765` for local testing or set your hosted relay URL, then click
`Share` and copy the link.

Open the `browser-connection` control panel (`controlPanelUrl` from `browser_list`), paste the link
into `Shared Link`, and add it as `edge`. The target appears as `kind=shared-extension`; selecting
it makes MCP tools route through the extension session instead of a CDP port:

```toml
[mcp_servers.playwright]
command = "browser-connection"
args = [
"--project", "dg-my-project",
"--browser-share", "edge=https://relay.example/share/session#agent=token",
"--active-browser", "managed",
]
```

The share link is a bearer credential. Anyone with the link can control that shared session until
the user clicks `Stop` in the extension or the relay session is removed. Extension sharing supports
common browser tools such as navigate, snapshot, evaluate, click, type, key press, and screenshot,
but it is not full CDP/VNC parity and protected Edge pages may reject actions.

## Personal browser

You can attach an already running desktop Chrome/Chromium browser if it exposes a CDP port.
When `browser-connection` runs inside Docker, use a host-reachable address such as
`host.docker.internal`, not `127.0.0.1`.

```bash
google-chrome \
--remote-debugging-address=0.0.0.0 \
--remote-debugging-port=9222 \
--user-data-dir="$HOME/.browser-connection-personal" \
--no-first-run
```

To also view that desktop browser through noVNC, expose the host desktop/browser through VNC:

```bash
x11vnc -display :0 -rfbport 5900 -listen 0.0.0.0 -nopw -forever -shared
```

Then register both the CDP endpoint and the VNC display endpoint:

```toml
[mcp_servers.playwright]
command = "browser-connection"
args = [
"--project", "dg-my-project",
"--personal-browser", "http://host.docker.internal:9222",
"--personal-vnc", "host.docker.internal:5900",
]
```

Multiple browser targets can be configured and switched at runtime. This example starts on the
Docker-managed noVNC browser and keeps the personal browser ready in the noVNC control panel:

```toml
[mcp_servers.playwright]
command = "browser-connection"
args = [
"--project", "dg-my-project",
"--browser", "personal=http://host.docker.internal:9222",
"--browser-vnc", "personal=host.docker.internal:5900",
"--browser", "work=http://127.0.0.1:9333",
"--active-browser", "managed",
]
```

Environment alternatives:

```bash
export BROWSER_CONNECTION_PERSONAL_CDP_ENDPOINT=http://host.docker.internal:9222
export BROWSER_CONNECTION_PERSONAL_VNC_ENDPOINT=host.docker.internal:5900
export BROWSER_CONNECTION_BROWSERS=work=http://127.0.0.1:9333
export BROWSER_CONNECTION_BROWSER_VNCS=work=host.docker.internal:5901
export BROWSER_CONNECTION_BROWSER_SHARES=edge=https://relay.example/share/session#agent=token
export BROWSER_CONNECTION_ACTIVE_BROWSER=managed
```

`browser_list` reports each target's `cdpEndpoint`, `vncEndpoint`, `novncUrl`, and `shareUrl`. If a
target has a VNC endpoint but no explicit noVNC URL, `browser_select` starts a lightweight noVNC
proxy for that target unless `--no-start-browser` is set.

Open the reported `controlPanelUrl` to choose `managed`, `personal`, or any configured browser from
the noVNC UI. The same `browser-connection` process keeps running, and MCP browser tools use the new
active target on the next tool call.

## Hermes MCP config

Expand All @@ -70,8 +181,16 @@ browser_click(selector)
browser_type(selector, text)
browser_press_key(key)
browser_take_screenshot(full_page?)
browser_list()
browser_select(name, cdp_endpoint?, vnc_endpoint?, novnc_url?, share_url?)
```

The noVNC control panel is the interactive switcher. Use `browser_select` with `name=managed` to
return to the Rust-managed noVNC/CDP browser, or with
`name=personal`, `cdp_endpoint=http://host.docker.internal:9222`, and
`vnc_endpoint=host.docker.internal:5900` to connect a personal browser without restarting the MCP
server.

## Smoke test

```bash
Expand Down
15 changes: 15 additions & 0 deletions artifacts/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Downloadable Artifacts

## Edge share extension

Download `edge-share-extension.tar.gz`, extract it, then open Edge:

```text
edge://extensions
```

Enable `Developer mode`, choose `Load unpacked`, and select the extracted
`edge-share` folder.

The extension connects to `browser-connection-relay` and produces share links
that can be pasted into the `browser-connection` control panel.
Binary file added artifacts/edge-share-extension.tar.gz
Binary file not shown.
9 changes: 9 additions & 0 deletions changelog.d/20260624_071400_personal_browser_targets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
bump: minor
---

### Added
- Add named MCP browser targets so agents can connect to a personal CDP browser and switch between personal, external, and Rust-managed browser sessions at runtime.
- Add optional VNC/noVNC display metadata for browser targets, including a Docker-managed noVNC proxy for host personal browsers.
- Add a local noVNC control panel for choosing the active browser target while one `browser-connection` MCP process keeps running.
- Add link-based shared browser targets through an Edge extension, `browser-connection-relay`, and `--browser-share NAME=URL`.
102 changes: 102 additions & 0 deletions extension/edge-share/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Browser Connection Edge Share

Static Microsoft Edge extension skeleton for sharing a running Edge browser with
`browser-connection` through a relay link. This directory intentionally has no
build step and no dependencies.

## Install for development

1. Open `edge://extensions`.
2. Enable `Developer mode`.
3. Choose `Load unpacked`.
4. Select this `extension/edge-share` directory.
5. Open the extension popup, enter the relay URL, and click `Share`.

The popup generates a one-time browser session and a share link such as:

```text
https://relay.example.com/share/<session_id>#agent=<agent_token>
```

The extension connects as the browser side to:

```text
wss://relay.example.com/ws/browser/<session_id>?token=<browser_token>&agent_token=<agent_token>
```

For local development, `http://127.0.0.1:8765` becomes
`ws://127.0.0.1:8765/ws/browser/...`.

## Relay protocol

On WebSocket open the extension sends:

```json
{
"type": "hello",
"role": "browser",
"protocolVersion": 1,
"sessionId": "<session_id>",
"userAgent": "<navigator.userAgent>"
}
```

The relay forwards command messages from the agent:

```json
{
"type": "command",
"id": "request-1",
"command": "navigate",
"params": {
"url": "https://example.com"
}
}
```

The extension replies:

```json
{
"type": "response",
"id": "request-1",
"ok": true,
"result": {}
}
```

Failed commands return `ok: false` and an `error` string.

## Commands

All commands accept optional `params.tabId`. If omitted, the extension uses the
last selected tab or the active tab in the last focused window.

- `navigate`: requires `url`; uses `chrome.tabs.update`.
- `evaluate`: requires `expression`; runs JavaScript with `Runtime.evaluate`.
- `snapshot`: returns title, URL, visible text, active element, and common
interactive elements.
- `click`: requires `selector`; scrolls, dispatches mouse events, and calls
`click()`.
- `type`: requires `text`; uses `selector` when provided, otherwise the active
element. Set `replace: true` to replace existing input text.
- `press_key`: requires `key`; dispatches common keyboard events through CDP.
- `screenshot`: returns a base64 PNG by default, or JPEG with
`format: "jpeg"`.
- `list_tabs`: returns basic tab metadata.
- `activate_tab`: activates `tabId` or the current target tab.

## Notes and limits

- This extension is the browser side for `browser-connection-relay` and the
`browser-connection` shared-extension driver.
- `chrome.debugger` exposes useful CDP commands but is not identical to a full
remote debugging port.
- Pages such as `edge://`, extension pages, store pages, and policy-restricted
tabs may reject debugger, scripting, or screenshot actions.
- The share link should be treated as a bearer credential. Anyone with the link
can control the shared session until the user clicks `Stop` or the relay
expires the session.
- The extension uses broad host permissions so it can connect to arbitrary relay
hosts during development. A production build should narrow this to known relay
origins.
26 changes: 26 additions & 0 deletions extension/edge-share/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"manifest_version": 3,
"name": "Browser Connection Edge Share",
"version": "0.1.0",
"description": "Share this Edge browser with browser-connection through a relay link.",
"permissions": [
"activeTab",
"debugger",
"scripting",
"storage",
"tabs"
],
"host_permissions": [
"<all_urls>"
],
"background": {
"service_worker": "service_worker.js"
},
"action": {
"default_title": "Edge Share",
"default_popup": "popup.html"
},
"content_security_policy": {
"extension_pages": "script-src 'self'; object-src 'self'; connect-src 'self' http://* https://* ws://* wss://*;"
}
}
Loading
Loading