Share a remote Chrome browser
Run an isolated, headless Chrome tab on one computer and let agents use it through Ninja MCP. The host connects outward using WebRTC or your HTTP relay. Chrome's debugging endpoint stays on loopback; agents need no VPN or desktop streaming software.
Each agent gets its own credential. Controllers take turns using a tab lease; observers can read snapshots, request screenshots, and watch optional live tab audio/video.
Start the host
Install Chrome and Node.js 22.12 or later. In your Ninja MCP installation folder, install the optional browser packages:
npm install @vdoninja/mcp chrome-devtools-mcp@1.11.0 puppeteer-core@24.37.5
npx vdon-mcp-browser --setup ./private-browser
npx vdon-mcp-browser --worker --config ./private-browser/worker.json
The setup prompts for a connection and optional live media. For a direct connection without prompts, add --transport webrtc. From a checkout, use node scripts/vdo-mcp-browser.js in place of npx vdon-mcp-browser. Keep the generated directory outside source control and accessible only to the host account. It contains four credential files:
| File | Give it to |
|---|---|
worker.json |
The browser host only; it contains every client key. |
agent1.json, agent2.json |
One controller each. |
viewer.json |
An observer who may see the shared tab but cannot control it. |
Copy each client file privately to its intended agent's machine. Give additional clients distinct random 32-byte hex keys and add their IDs, keys, and controller or observer roles to worker.json. Restart the worker to apply credential changes. Use one client credential per active agent process.
Setup also writes mcp-client.json with the local agent registration. Adjust its absolute paths when copying it to another computer. --init remains available for creating WebRTC credentials without prompts.
The worker starts with one empty shared tab and an ephemeral Chrome profile. Your ordinary Chrome windows and logged-in profile are separate. To select a Chrome executable, add an absolute executable path to worker.json. When browser packages live elsewhere, set dependencies to their installation directory.
Connect an agent
The agent machine needs Ninja MCP, but does not need Chrome or the optional browser packages. Add this separate server to the agent's MCP configuration, using absolute paths:
{
"mcpServers": {
"ninja-browser": {
"command": "node",
"args": [
"/absolute/path/node_modules/@vdoninja/mcp/scripts/vdo-mcp-browser.js",
"--config",
"/absolute/private/path/agent1.json"
]
}
}
}
On Windows, use paths such as C:/Ninja/node_modules/@vdoninja/mcp/scripts/vdo-mcp-browser.js. Existing message, file, and state tools remain available through the ordinary Ninja MCP server.
Check the host packages or authenticate to the running worker from a client:
npx vdon-mcp-browser --doctor --config ./private-browser/worker.json
npx vdon-mcp-browser --doctor --config ./private-browser/agent1.json
The client check lists tabs without taking control. Its output distinguishes relay access from an authenticated worker response and names the route that returned the result.
Ask the agent to list tabs, claim the shared tab, navigate, and take a snapshot:
{ "name": "browser_tabs", "arguments": {} }
{ "name": "browser_claim", "arguments": { "pageId": 1 } }
{ "name": "browser_call", "arguments": { "pageId": 1, "lease": "<returned lease>", "action": "navigate", "url": "https://example.com" } }
{ "name": "browser_observe", "arguments": { "pageId": 1 } }
Use the returned snapshot token and element UID for input:
{ "name": "browser_call", "arguments": { "pageId": 1, "lease": "<returned lease>", "snapshot": "<snapshot token>", "action": "click", "uid": "<element uid>" } }
{ "name": "browser_observe", "arguments": { "pageId": 1, "screenshot": true } }
{ "name": "browser_release", "arguments": { "pageId": 1, "lease": "<returned lease>" } }
fill takes uid and value; key takes a page key such as Enter, Tab, or an arrow key. Navigation accepts HTTP and HTTPS URLs. Remote tools do not expose script evaluation, local file uploads, browser shortcuts, or the media publisher's private page. They share the initial tab; newly opened tabs are not exposed. Continue work in the shared tab by navigating it to the desired URL.
Watch live tab audio and video
Add this option to worker.json, then restart:
"media": { "enabled": true }
Call browser_media to get track status and a private VDO.Ninja viewing link. The host captures only the shared tab, including its audio, through Chrome tab capture and publishes it using the VDO.Ninja SDK. The publisher uses a separate browser context and fresh media credentials on every worker start. Microphone and desktop capture are not enabled. Recording is off.
Anyone holding the viewing link can watch and hear that stream. Share it only with intended viewers; restart the worker to replace the link. Media access does not grant control. The capture persists when the shared tab navigates, so stop the worker before opening content you do not want viewers to see.
Live media requires WebRTC even when commands use HTTP. If browser_media reports unavailable media or an ended track, use browser_observe screenshots and restart after restoring capture or connectivity. An optional media.host selects a different SDK signaling endpoint; clients then receive connection settings instead of a default VDO.Ninja link.
For a speaking agent that sees selected browser frames and uses these tools, open the optional browser companion. Live viewing and model sharing have separate controls.
Choose the host's access deliberately
All configured viewers can see the shared tab, and controllers can interact with sites using the host's network access. Run the worker under an account or container with only the network and filesystem access you intend to share. A separate Chrome profile is not an operating-system sandbox. Avoid signing into personal accounts in this shared tab.
Browser requests and results use a separate AES-GCM key for each client over either transport. Keep credential files private. Removing a client requires updating the host configuration and restarting; possession of that client's file grants its configured role until then.
The adapter uses the pinned Chrome DevTools MCP release and VDO.Ninja SDK. Chrome runs with its sandbox enabled. The worker binds no public browser-control port and changes no ordinary Ninja MCP transport defaults.