browser-mcp
Gives coding agents full control over a real Chrome browser, enabling navigation, clicking, typing, screenshotting, and more via an MCP server and Chrome extension.
README
Browser MCP
An MCP server + Chrome extension that gives coding agents (Claude Code, etc.) full control over a real Chrome browser. Multiple Claude Code sessions can share the same browser simultaneously.
Architecture
Claude Code #1 → MCP Server #1 ──┐
Claude Code #2 → MCP Server #2 ──┤ (pipe clients)
Claude Code #3 → MCP Server #3 ──┘
│ Named pipe
▼
relay.js (pipe server, spawned by Chrome)
│ Chrome Native Messaging
▼
background.js (Chrome Extension Service Worker)
│ Chrome Extension APIs
▼
Web Pages
The relay acts as a named pipe server. Each Claude Code session spawns its own MCP server process, which connects to the relay as a pipe client. The relay multiplexes requests and routes responses back to the correct MCP client by matching request IDs.
Prerequisites
- Node.js 18+ (must be in your system PATH)
- Chrome or Edge browser
- Claude Code (or any MCP-compatible client)
Setup
Step 1: Install dependencies and build
cd /path/to/browser-mcp
npm install
npm run build
This installs the MCP SDK and compiles the TypeScript server to dist/mcp-server.js.
macOS note: Do not keep this project in the
~/Downloads/folder. macOS System Policy blocks Chrome from launching native messaging hosts located in~/Downloads/. Move the project elsewhere first (e.g.~/browser-mcpor~/Projects/browser-mcp).
Step 2: Load the Chrome extension
- Open Chrome and navigate to
chrome://extensions - Enable Developer mode using the toggle in the top-right corner
- Click Load unpacked
- Select the
extension/folder inside this project (e.g.C:\Browser MCP\extension) - The extension "Browser MCP Bridge" will appear — copy the Extension ID shown underneath it
- It looks like:
abcdefghijklmnopqrstuvwxyz012345
- It looks like:
Step 3: Register the native messaging host
Run the installer script, passing your extension ID from the previous step:
node install.js <your-extension-id>
For example:
node install.js abcdefghijklmnopqrstuvwxyz012345
This does two things:
- Writes a native messaging host manifest file to the appropriate directory for each supported browser (Chrome, Chrome Canary, Edge, Edge Canary on macOS; Chrome, Edge on Windows/Linux)
- On Windows, registers the manifest path in the Windows registry
- Cleans up any stale relay processes or socket files from previous installations
Important: If you ever reinstall the extension and get a new extension ID, re-run this command with the new ID.
Step 4: Reload the extension
After running the installer, go back to chrome://extensions and click the reload button (circular arrow) on the Browser MCP Bridge extension. This allows the extension to pick up the newly registered native messaging host.
Step 5: Add the MCP server to Claude Code
Option A — CLI command:
claude mcp add browser-mcp -- node "C:/Browser MCP/dist/mcp-server.js"
Option B — Add manually to your Claude Code config file (.claude.json in your project root, or the global claude_desktop_config.json):
{
"mcpServers": {
"browser-mcp": {
"command": "node",
"args": ["C:/Browser MCP/dist/mcp-server.js"]
}
}
}
Step 6: Verify it works
Start a new Claude Code session and ask it something like:
"Open https://example.com in the browser and get the page text"
You should see a new tab open in Chrome and Claude returning the page content.
After Setup
Once setup is complete, you generally don't need to do anything when starting new sessions:
| Scenario | Action needed? |
|---|---|
| Open a new Claude Code terminal | No — a new MCP server connects to the existing relay automatically |
| Open multiple Claude Code terminals | No — all sessions share the relay and can use the browser |
| Restart Chrome | No — the extension and relay auto-start |
| Restart your computer | No — Chrome loads the extension on start, Claude Code spawns the MCP server on demand |
| Reinstall / update the extension | Re-run node install.js <new-extension-id> if the ID changed, then reload |
Available Tools
| Tool | Description |
|---|---|
browser_open |
Navigate to a URL. Returns final URL and page title. |
browser_back |
Go back to the previous page. |
browser_scroll |
Scroll the page up or down by a pixel amount. |
browser_state |
Get page URL, title, scroll position, and indexed list of all interactive elements. Call this after every navigation. |
browser_screenshot |
Capture a PNG screenshot of the visible page. |
browser_click |
Click an element by its index from browser_state. |
browser_type |
Type text into the currently focused input element. |
browser_input |
Click an element by index then type into it (combined click + type). |
browser_keys |
Send keyboard keys (e.g. Enter, Tab, Ctrl+A). |
browser_select |
Select a dropdown <select> option by index and option text. |
browser_eval |
Execute JavaScript in the page and return the result. |
browser_get_text |
Get text content of an element (by index) or the full page. |
browser_get_html |
Get HTML content by element index, CSS selector, or full body. |
browser_wait |
Wait for a CSS selector or text to appear on the page. |
browser_close |
Close a tab (or all managed tabs with all: true). |
browser_sessions |
List all open tabs managed by the extension. |
Usage Patterns
Web search
1. browser_open → navigate to https://www.bing.com
2. browser_state → find the search input element index
3. browser_input → type the search query into the input
4. browser_keys → press Enter to submit
5. browser_state → read the search result links and snippets
6. browser_open → navigate to a promising result URL
7. browser_get_text → extract the page content
Read a web page
1. browser_open → navigate to the URL
2. browser_get_text → extract readable text content
Fill out a form
1. browser_open → navigate to the form page
2. browser_state → get element indices for all form fields
3. browser_input → fill each field by its index
4. browser_click → click the submit button
How It Works
-
Chrome Extension (
extension/background.js) — A Manifest V3 service worker that controls Chrome tabs using the Extensions API. It connects to a native messaging host on load and executes browser commands (open, click, type, etc.) received over that channel. -
Relay (
relay/relay.js) — A small Node.js process spawned by Chrome as a native messaging host. It creates a named pipe server (\\.\pipe\browser-mcp-bridgeon Windows) and bridges between Chrome's native messaging protocol (length-prefixed JSON on stdin/stdout) and the named pipe (newline-delimited JSON). It tracks which pipe client sent each request and routes responses back correctly. -
MCP Server (
dist/mcp-server.js) — A Node.js process spawned by Claude Code for each session. It connects to the relay's named pipe as a client, registers 16 browser tools via the MCP protocol over stdio, and translates MCP tool calls into relay requests. Multiple MCP server instances can connect simultaneously. -
Request flow: MCP Client → MCP Server → Named Pipe → Relay → Chrome Native Messaging → Extension → Chrome Browser → response flows back the same path.
Troubleshooting
"Browser extension not connected"
This means the MCP server couldn't connect to the relay's named pipe. Possible causes:
- Extension not loaded — Go to
chrome://extensionsand verify "Browser MCP Bridge" is listed and enabled - Native messaging host not registered — Re-run
node install.js <extension-id> - Extension needs reload — Click the reload button on the extension card in
chrome://extensions - Chrome not running — The relay only exists while Chrome is running with the extension loaded
Extension loads but tools don't work
- Click "Inspect views: service worker" on the extension card in
chrome://extensionsto open the console - Look for
[BMCP-Bridge]log messages to diagnose connection issues
Native messaging errors
- Verify Node.js is in your system PATH: run
node --versionfrom a terminal - On Windows, verify registry entries exist:
HKCU\Software\Google\Chrome\NativeMessagingHosts\com.browser.mcp.relayHKCU\Software\Microsoft\Edge\NativeMessagingHosts\com.browser.mcp.relay
- Re-run
node install.js <extension-id>to regenerate the manifest and registry entries
macOS-specific issues
- "Native host has exited" immediately after connecting — Check if the project is located in
~/Downloads/. macOS System Policy blocks Chrome's native messaging subprocess from reading files in~/Downloads/. Move the project to another location (e.g.~/browser-mcp) and re-runnode install.js. - Quarantine attributes — Files downloaded from the internet have quarantine extended attributes that may block execution. Remove them with:
xattr -dr com.apple.quarantine /path/to/browser-mcp/ - Node.js not found by Chrome — Chrome launches native messaging hosts with a minimal PATH (
/usr/bin:/bin:/usr/sbin:/sbin) that doesn't include Homebrew (/opt/homebrew/bin) or nvm directories. The installer automatically resolves the absolute path tonodeand writes it intorelay.sh. If you change your Node.js installation, re-runnode install.js. - Check relay logs — The relay writes diagnostic logs to
/tmp/browser-mcp-relay.log(or$TMPDIR/browser-mcp-relay.log). Check this file for errors:cat /tmp/browser-mcp-relay.log - Stale relay process — If a previous relay process is still running, the new one will exit with EADDRINUSE. Re-running
node install.jsautomatically cleans up stale processes, or manually:pkill -f relay.js rm -f /tmp/browser-mcp-bridge.sock
Multiple Claude Code sessions
All sessions share the same browser. Tabs opened by one session are visible to others via browser_sessions. If two sessions try to interact with the same tab simultaneously, results may be unpredictable — each session should work with its own tabs.
Project Structure
Browser MCP/
├── src/
│ └── mcp-server.ts # MCP server (pipe client + tool definitions)
├── dist/
│ └── mcp-server.js # Compiled server (this is what Claude Code runs)
├── extension/
│ ├── manifest.json # Chrome MV3 extension manifest
│ ├── background.js # Service worker — executes browser commands
│ └── content.js # Fallback content extraction script
├── relay/
│ ├── relay.js # Native messaging relay (pipe server + request router)
│ ├── relay.bat # Windows wrapper for relay.js
│ └── relay.sh # macOS/Linux wrapper for relay.js (generated by install.js)
├── install.js # One-time setup: registers native messaging host
├── package.json
└── tsconfig.json
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.