Skip to main content
Glama
README.md
# Browser MCP

Browser MCP is an Electron-based Model Context Protocol server that gives MCP clients control over a real local browser window. It exposes tools for starting browser sessions, reading page context, clicking, typing, dragging, scrolling, taking screenshots, inspecting console logs, and reviewing network requests.

The package is published on NPM as `@cypherpotato/browser-mcp`.

## Contents

- [How it works](#how-it-works)
- [Requirements](#requirements)
- [Installation](#installation)
- [MCP client configuration](#mcp-client-configuration)
- [Running the HTTP sentinel](#running-the-http-sentinel)
- [CLI reference](#cli-reference)
- [Tools](#tools)
- [Environment variables](#environment-variables)
- [Development](#development)
- [Troubleshooting](#troubleshooting)

## How it works

Browser MCP has two runtime layers:

1. A Node entrypoint named `browser-mcp-electron`.
2. An Electron browser host that opens and controls real browser windows.

By default, MCP clients should start the package with `--mcp`. That command starts or reuses a local HTTP sentinel, then proxies MCP messages over stdin/stdout for the client.

```mermaid
flowchart LR
  Client["MCP client"] --> Stdio["browser-mcp-electron --mcp"]
  Stdio --> Sentinel["Local HTTP sentinel"]
  Sentinel --> Electron["Electron browser host"]
  Electron --> Page["Live browser session"]
```

The sentinel stores its current local endpoint in the operating system temp directory under `browser-mcp-electron-sessions/sentinel.json`. The server only listens on `127.0.0.1`.

## Requirements

- Node.js 18 or newer.
- npm or another Node package manager.
- A desktop session capable of running Electron.
- Linux only: the usual Electron runtime libraries for your distribution.

## Installation

Install globally if your MCP client will call the binary directly:

```bash
npm install -g @cypherpotato/browser-mcp
```

Or run it without a global install:

```bash
npx @cypherpotato/browser-mcp --help
```

To verify the binary:

```bash
browser-mcp-electron --help
```

## MCP client configuration

Use the stdio bridge mode for normal MCP client integration:

```json
{
  "mcpServers": {
    "browser": {
      "command": "browser-mcp-electron",
      "args": ["--mcp"]
    }
  }
}
```

With `npx`:

```json
{
  "mcpServers": {
    "browser": {
      "command": "npx",
      "args": ["-y", "@cypherpotato/browser-mcp", "--mcp"]
    }
  }
}
```

Optional startup URL and profile directory:

```json
{
  "mcpServers": {
    "browser": {
      "command": "browser-mcp-electron",
      "args": [
        "--mcp",
        "--url",
        "https://example.com",
        "--data-dir",
        "~/.browser-mcp"
      ]
    }
  }
}
```

## Running the HTTP sentinel

For normal MCP client usage, configure the client to run `browser-mcp-electron --mcp`. That command starts the HTTP sentinel automatically when needed and reuses a healthy sentinel when one already exists.

Run the HTTP sentinel manually only when you want to manage the browser host separately from an MCP stdio client.

Start it in the foreground:

```bash
browser-mcp-electron --mcp-http --url https://example.com --data-dir ~/.browser-mcp
```

Start it in the background and return after it is healthy:

```bash
browser-mcp-electron --mcp-http-background --url https://example.com --data-dir ~/.browser-mcp
```

Pin the local sentinel port:

```bash
browser-mcp-electron --mcp-http-background --sentinel-port 55332
```

When `--mcp` runs later, it reuses a healthy sentinel when one exists. If no healthy sentinel exists, it starts one automatically.

## CLI reference

```text
browser-mcp-electron [--mcp] [--url <url>] [--data-dir <path>]
browser-mcp-electron --mcp-http [--url <url>] [--data-dir <path>]
browser-mcp-electron --mcp-http-background [--url <url>] [--data-dir <path>]
browser-mcp-electron --mcp-stdio [--url <url>] [--data-dir <path>]
```

| Option | Description |
| --- | --- |
| `--mcp` | Starts or reuses the local HTTP sentinel and proxies MCP over stdin/stdout. Recommended for MCP clients. |
| `--mcp-http` | Starts or reuses only the local HTTP MCP sentinel and keeps the process alive. |
| `--mcp-http-background` | Starts or reuses the local HTTP MCP sentinel, then returns after it is healthy. |
| `--mcp-stdio` | Starts the legacy MCP server directly over stdin/stdout. |
| `--url`, `-u` | Initial browser URL. Defaults to `https://www.google.com`. |
| `--data-dir` | Browser profile/session directory. Defaults to `~/.browser-mcp`. |
| `--sentinel-port` | Port for the HTTP sentinel. Defaults to `0`, which means a random available port. |
| `--help`, `-h` | Prints the CLI help. |

## Tools

### `browser_toggle_session`

Starts or stops a real Electron browser session.

Start a session:

```json
{
  "action": "start",
  "start_url": "https://example.com"
}
```

Stop a session:

```json
{
  "action": "stop",
  "session_id": 1
}
```

### `browser_get_context`

Lists active Browser MCP sessions with process ID, session ID, title, sanitized URL, and state.

Session states:

| State | Meaning |
| --- | --- |
| `idle` | Ready for actions. |
| `waiting` | Loading or running an action. |
| `user_input` | A JavaScript dialog is pending. Resolve it with `browser.setDialog(...)` or `browser.dismissDialog()`. |

### `browser_run_actions`

Runs an async JavaScript function body in the live page. The function receives a `browser` helper object.

Inspect the current page:

```javascript
return browser.snapshot();
```

Navigate:

```javascript
return browser.navigate("https://example.com");
```

Click and type:

```javascript
const input = document.querySelector("input[name=email]");
const rect = input.getBoundingClientRect();
await browser.leftClick(rect.left + 8, rect.top + rect.height / 2);
await browser.type("user@example.com");
return input.value;
```

Capture a screenshot:

```javascript
return await browser.screenshot();
```

Review network activity:

```javascript
const logs = await browser.networkLogs({ filterMethod: "POST", filterPath: "/api/" });
return await browser.inspectNetworkRequest(logs.requests[0].id);
```

Available helpers:

| Helper | Description |
| --- | --- |
| `browser.navigate(url)` | Schedules navigation after the script returns. |
| `browser.leftClick(x, y, duration?)` | Dispatches a left click at viewport coordinates. |
| `browser.rightClick(x, y, duration?)` | Dispatches a right click at viewport coordinates. |
| `browser.hover(x, y)` | Moves the pointer over a viewport coordinate. |
| `browser.drag(fromX, fromY, toX, toY, duration?, isLeftClick?)` | Drags between viewport coordinates. |
| `browser.scroll(x, y, delta)` | Scrolls at a viewport coordinate. |
| `browser.type(text)` | Types into the focused input, textarea, or contenteditable element. |
| `browser.sleep(ms)` | Waits inside the page action. |
| `browser.snapshot()` | Returns visible text, element hints, console issue counts, and viewport coordinates. |
| `browser.screenshot()` | Returns an MCP image. |
| `browser.consoleLogs()` | Returns recent console logs, warnings, and errors. |
| `browser.networkLogs(options?)` | Returns compact recent network requests. |
| `browser.inspectNetworkRequest(id)` | Returns detailed request/response information for a network request. |
| `browser.setDialog(value)` | Accepts a pending alert/confirm/prompt. |
| `browser.dismissDialog()` | Dismisses a pending alert/confirm/prompt. |

## Environment variables

| Variable | Description | Default |
| --- | --- | --- |
| `BROWSER_MCP_DATA_DIR` | Browser profile/session directory. | `~/.browser-mcp` |
| `BROWSER_MCP_URL` | Initial browser URL. | `https://www.google.com` |
| `BROWSER_MCP_SENTINEL_PORT` | HTTP sentinel port. Use `0` for a random available port. | `0` |
| `BROWSER_MCP_DEBUG_LOG` | Debug log path used by the launcher and Electron host. | OS temp file |
| `BROWSER_MCP_RPC_PORT` | Internal RPC port for detached Electron host mode. | unset |
| `BROWSER_MCP_RPC_TOKEN` | Internal RPC token for detached Electron host mode. | unset |

## Development

Install dependencies:

```bash
npm install
```

Run the app:

```bash
npm start
```

Run the recommended MCP mode from the local checkout:

```bash
npm run mcp
```

Check JavaScript syntax:

```bash
npm run check
```

Run tests:

```bash
npm test
```

The test suite starts a local HTTP test page and a Browser MCP HTTP sentinel, then validates the public MCP tools and browser actions.

## Troubleshooting

### The MCP client cannot find `browser-mcp-electron`

Use the `npx` configuration or provide the absolute path to the binary.

Windows:

```powershell
where.exe browser-mcp-electron
```

Linux/macOS:

```bash
command -v browser-mcp-electron
```

### The sentinel starts, but the MCP client opens a new one

Make sure both commands use the same user account and, if you pinned a port, the same `--sentinel-port` value. The sentinel registry is stored in the OS temp directory and is scoped to the current machine/user environment.

### Electron does not start on Linux

Install the Electron runtime libraries required by your distribution and start the sentinel from a graphical user session. For systemd, prefer a user service instead of a system service because Browser MCP needs access to the user's desktop session.

### A page action times out

Pass a larger `timeout_ms` to `browser_run_actions`:

```json
{
  "code": "await browser.sleep(15000); return browser.snapshot();",
  "timeout_ms": 20000
}
```

Action timeouts are clamped between 100 ms and 5 minutes.

### Multiple sessions are active

Pass the `session_id` returned by `browser_toggle_session` to `browser_run_actions`. When more than one session exists, Browser MCP requires explicit session selection.