Skip to main content
Glama
browserview

@browserview/mcp

Official
by browserview
README.md
# @browserview/mcp

MCP (Model Context Protocol) server for [browserview.io](https://browserview.io) — disposable cloud Chromium sessions. Humans watch and control a session through a live viewer URL; agents drive the same browser over the Chrome DevTools Protocol (CDP) using Playwright or Puppeteer (`connectOverCDP`). This server lets any MCP-capable agent (Claude, OpenAI agents, Cursor, and others) create, inspect, share, and destroy sessions.

## Requirements

- Node.js 18+
- A browserview.io API key, provided via the `BROWSERVIEW_API_KEY` environment variable. Keys are minted in the [browserview.io console](https://browserview.io) and look like `bv_live_` + 40 hex chars.

Optional: set `BROWSERVIEW_BASE_URL` to override the API base URL (default `https://sessions.browserview.io`). The legacy `BROWSERVIEW_API_URL` variable is still honored as a fallback but is deprecated — prefer `BROWSERVIEW_BASE_URL`.

## Setup

### Claude Code

```sh
claude mcp add browserview -e BROWSERVIEW_API_KEY=your-key-here -- npx -y @browserview/mcp
```

### Claude Desktop

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "browserview": {
      "command": "npx",
      "args": ["-y", "@browserview/mcp"],
      "env": {
        "BROWSERVIEW_API_KEY": "your-key-here"
      }
    }
  }
}
```

### Cursor

Add to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "browserview": {
      "command": "npx",
      "args": ["-y", "@browserview/mcp"],
      "env": {
        "BROWSERVIEW_API_KEY": "your-key-here"
      }
    }
  }
}
```

### Generic stdio client

Run the server as a stdio subprocess:

```sh
BROWSERVIEW_API_KEY=your-key-here npx -y @browserview/mcp
```

## Tools

| Tool | Arguments | Description |
| --- | --- | --- |
| `create_session` | `start_url?`, `width?`, `height?`, `wait?`, `record?`, `agent?` | Create a browser session. Server defaults: `start_url` `about:blank`, 1280×800 viewport, `wait` true (blocks until the browser accepts CDP, typically ~5s), `record` false (set true to capture a session replay). Returns the session as JSON with an absolute `viewer_url` (a human can open it to watch/control), `watch_url` (view-only), and `cdp_url` + `cdp_token` (for Playwright/Puppeteer `connectOverCDP`). `agent: true` (or `{model, effort, max_steps, allowed_domains}`) enables the hosted agent for the session. |
| `list_sessions` | — | List all sessions (no URLs/tokens; use `get_session` for those). |
| `get_session` | `session_id` | Fetch one session with freshly issued URLs and tokens, plus health details: `restarts` (int, or null if unknown) and `degraded` (true once the in-session browser has restarted). |
| `destroy_session` | `session_id` | Permanently destroy a session. |
| `mint_session_token` | `session_id`, `scope` (`view` \| `control` \| `cdp` \| `agent`), `ttl_seconds?` | Mint a scoped access token for sharing a session without exposing your API key. `ttl_seconds` must be 1–604800 (7 days); default 3600. |
| `get_session_replay` | `session_id`, `wait?` | Replay manifest of a recorded session (works after destruction): video URL (seekable WebM), pages timeline, and per-stream JSONL event URLs (actions/console/network/errors), all with absolute epoch-ms timestamps. With `wait: true`, polls up to 2 minutes while the recording finalizes; a live session created without `record: true` fails immediately instead of polling. |
| `run_agent_task` | `task`, `session_id?`, `start_url?`, `keep_session?`, `model?`, `effort?`, `max_steps?`, `budget_credits?`, `allowed_domains?` | Have the hosted AI agent carry out a natural-language browser task. Creates an `agent: true` session when `session_id` is omitted (destroyed afterwards unless `keep_session` is true or the agent asked a question). Blocks until the turn ends; returns `answer`, `stop_reason`, `steps`, `cost_usd`, `usage`, `session_id`, `viewer_url`, and `pending_question` when the agent needs input. |
| `agent_send_message` | `session_id`, `content`, `model?`, `effort?`, `max_steps?`, `budget_credits?`, `allowed_domains?` | Send a follow-up instruction to an agent-enabled session's conversation and wait for the turn; steering when a turn is already running. Same result shape as `run_agent_task`. |
| `agent_reply` | `session_id`, `content` | Answer the agent's pending question (after `stop_reason: needs_input`); starts and waits for the next turn. `409` when nothing is pending. |
| `agent_interrupt` | `session_id` | Stop the running turn (`stop_reason: interrupted`). Returns `{ok, state}`. |
| `get_agent_conversation` | `session_id`, `after?`, `turn?`, `include_deltas?` | Agent status (`disabled` \| `idle` \| `running` \| `needs_input`), model, usage totals, pending question, and the event log condensed into a transcript (user messages, steps, questions, turn results). `after` pages by `seq`; `last_seq` is where to resume. |
| `list_agent_models` | — | The hosted agent's model catalog: id, provider, display name, list pricing per 1M tokens, capabilities, availability, and the default model. |

## Connecting to the browser

`cdp_url` is deliberately token-free; pass `cdp_token` as an `x-session-token` header or a `?token=` query parameter:

```ts
// Playwright
const browser = await chromium.connectOverCDP(session.cdp_url, {
  headers: { "x-session-token": session.cdp_token },
});

// Puppeteer
const browser = await puppeteer.connect({
  browserURL: session.cdp_url + "?token=" + session.cdp_token,
});
```

Tokens expire after `token_ttl_seconds` (1 hour by default) — call `get_session` or `mint_session_token` for fresh ones. Hand `viewer_url` to a human to let them watch and take control of the same browser while the agent works.

## Hosted agent

Sessions created with `agent: true` include a hosted AI agent that drives the browser from natural-language instructions. `run_agent_task` is the one-shot path (create, run, destroy); `agent_send_message` / `agent_reply` continue a conversation in a session you keep. One conversation per session, one running turn at a time; the agent stops with `stop_reason: needs_input` and a `pending_question` when it needs a decision, and `agent_reply` resumes it. Turns can take minutes — the server heartbeats the stream and the tools block until `turn.end`. The message POST is never retried (a retry would double-send it); a dropped stream is resumed from the last `seq` via the events log. Usage is billed in agent credits (a `402` error names the `deny_reason`).

## Behavior notes

- **Retries**: requests that fail with 429 (`Retry-After: 30` for session/capacity limits on create, `Retry-After: 60` for per-IP/per-owner rate limits) or 503 (`Retry-After: 10` when the auth backend is temporarily down, `Retry-After: 60` when the recording backend is unavailable) are retried automatically up to 3 times, honoring the `Retry-After` header (capped at 30s per wait) or falling back to 1s/2s/4s backoff.
- **Timeout**: each request has a 90s timeout, sized for `create_session` with `wait: true` (which can block up to ~60s server-side).
- **URLs**: the API returns `viewer_url`/`watch_url`/`cdp_url` as paths relative to the API host; this server resolves them to absolute URLs before returning them.
- **Errors**: API errors surface the server's `detail` message plus retry hints when rate limited.
- **Lifecycle**: sessions are disposable — destroy them when done; the server also reaps sessions automatically when idle or past their maximum lifetime, so a crashed agent never leaks a browser.

## Development

```sh
npm install
npm run build
node dist/index.js
```

TDQS

A4.4/5.0

Scored across 6 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: create, list, get, destroy, mint token, and replay. The slight overlap between list_sessions and get_session is resolved by descriptions clarifying summaries vs. full details with tokens. No ambiguity exists between any tools.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case (create_session, destroy_session, list_sessions, get_session, mint_session_token, get_session_replay). The pluralization of list_sessions is the only minor deviation, but it is conventional and does not break the pattern.

Tool Count5/5

With 6 tools, the server is well-scoped for its purpose of managing cloud browser sessions. Each tool covers a distinct aspect of the session lifecycle and adds value without bloat.

Completeness5/5

The tool set covers the full session lifecycle: create, read (list and get), delete, token management, and replay for recorded sessions. No obvious gaps exist—session creation handles recording, and replay finalization is pollable. The surface is complete for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues