# browser-mcp-server
Browser automation and web scraping MCP server powered by headless Chromium.
Standalone binary that exposes 27 browser automation and web scraping tools over MCP (Model Context Protocol) via stdio or HTTP transport using JSON-RPC 2.0.
## Features
- **20 browser session tools** — open, screenshot, click, fill, select, wait_for, evaluate, scroll, get_text, inspect, get_attribute, go_back, go_forward, close, press_key, hover, reload, get_cookies, set_cookie, clear_cookies
- **3 HTTP tools** — url_read (HTML to Markdown), url_read_raw, url_search (Brave/DuckDuckGo)
- **4 scraper tools** — fetch (HTTP-first with browser fallback), read_markdown (Readability), probe, submit_form
- **Stealth mode** — CDP patches, User-Agent spoofing, navigator overrides, plugin emulation
- **Session management** — multiple concurrent browser sessions with auto-cleanup
- **Dual transport** — stdio (default) or HTTP mode via `--transport` flag
- **HTTP transport** — MCP Streamable HTTP with Bearer token authentication and session management
## Architecture
Single crate, seven source modules:
| `src/main.rs` | CLI parsing (clap), entry point, transport selection, tool definitions, tool dispatch |
| `src/mcp.rs` | JSON-RPC 2.0 types, MCP tool result helpers, async stdio loop, async dispatch |
| `src/http.rs` | HTTP transport: axum server, Bearer auth, MCP HTTP session management |
| `src/browser.rs` | Chromium lifecycle, stealth patches, 20 browser tool handlers, session cleanup |
| `src/search.rs` | url_read, url_read_raw, url_search (Brave/DDG) |
| `src/content.rs` | read_markdown (Readability), probe, submit_form |
| `src/fetch.rs` | fetch (HTTP-first, browser fallback) |
## CLI Arguments
```
browser-mcp-server [OPTIONS]
Options:
--transport <MODE> Transport mode: stdio or http [default: stdio]
--host <HOST> Host to bind HTTP server [default: 127.0.0.1]
--port <PORT> Port for HTTP server [default: 8080]
--auth <TOKEN> Bearer token for HTTP authentication (optional)
--chrome-path <PATH> Path to Chrome/Chromium binary (auto-detected if not set)
--headless Run in headless mode [default: true]
--max-sessions <N> Max concurrent browser sessions [default: 5]
--session-timeout-secs <N> Session auto-close after inactivity [default: 300]
--page-load-timeout-ms <N> Per-navigation timeout [default: 60000]
--content-timeout-ms <N> Page content extraction timeout [default: 60000]
--max-content-bytes <N> Max HTML size before truncation [default: 1000000]
--no-sandbox Disable Chrome sandbox (required in Docker)
--data-dir <PATH> Data directory for screenshots & Chrome profile
--version Print version and exit
```
## Build
### Prerequisites
- Rust toolchain (stable)
- Chromium or Google Chrome (runtime dependency)
### Build
```bash
cargo build --release
```
### With Nix
```bash
nix develop # dev shell with all dependencies
nix build # build the package
```
## Runtime Dependencies
- **Chromium** or **Google Chrome** — auto-detected, or set `--chrome-path`
## Rust Dependencies
| `chromiumoxide` | Headless Chrome/Chromium via CDP |
| `htmd` | HTML to Markdown conversion |
| `readability` | Mozilla Readability content extraction |
| `reqwest` | HTTP client for lightweight tools |
| `futures` | Stream handling for Chrome events |
| `url` | URL parsing |
| `dirs` | Default data directory |
| `clap` | CLI argument parsing |
| `serde`, `serde_json` | JSON serialization for MCP protocol |
| `tracing`, `tracing-subscriber` | Structured logging to stderr |
| `axum` | HTTP server framework for MCP HTTP transport |
| `tokio` | Async runtime |
| `uuid` | Session ID generation (UUID v4) |
## MCP Protocol
The server supports two transport modes:
- **stdio** (default) — communicates over stdin/stdout, one JSON object per line
- **HTTP** — MCP Streamable HTTP on `POST /mcp` and `DELETE /mcp`
### HTTP Transport
Start the server in HTTP mode:
```bash
browser-mcp-server --transport http --port 8080 --auth secret123
```
**Authentication**: when `--auth` is set, all requests must include `Authorization: Bearer <token>`. Without `--auth`, authentication is disabled.
**Sessions**: the `initialize` request returns an `Mcp-Session-Id` header. All subsequent requests must include this header. Sessions are terminated via `DELETE /mcp`.
### Stdio Transport
The server communicates over stdin/stdout using JSON-RPC 2.0, one JSON object per line.
### Initialize
Request:
```json
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
```
Response:
```json
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"tools":{}},"serverInfo":{"name":"browser-mcp-server","version":"<version>"}}}
```
### List tools
Request:
```json
{"jsonrpc":"2.0","id":2,"method":"tools/list"}
```
### Open a page
Request:
```json
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"open","arguments":{"url":"https://example.com"}}}
```
## Usage
### Claude Desktop (stdio)
Add to `claude_desktop_config.json`:
```json
{
"mcpServers": {
"browser": {
"command": "/path/to/browser-mcp-server"
}
}
}
```
### HTTP mode
```bash
browser-mcp-server --transport http --port 8080 --auth mytoken
```
Connect any HTTP-capable MCP client to `http://127.0.0.1:8080/mcp`.
### Any MCP client (stdio)
The server reads JSON-RPC requests from stdin and writes responses to stdout. Logs go to stderr. Connect any MCP-compatible client using stdio transport.