npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

open-browser-mcp

v1.0.1

Published

MCP server that connects AI agents to your real Chrome browser — cookies, sessions, extensions and all

Readme

Open Browser MCP

npm version License: MIT Node.js >= 18

MCP server that connects AI agents to your real Chrome browser — your actual profile with cookies, login sessions, extensions, and bookmarks. No isolated profiles, no Puppeteer, no Playwright.

Why this exists

Every other browser automation tool launches a sandboxed browser. That means no logged-in sessions, no cookies, no extensions. Open Browser MCP uses your real Chrome via a lightweight extension + CDP, so the agent works in the same browser context you do.

Architecture

MCP Client (Claude Code, Cursor, Windsurf, etc.)
        |  stdio
  MCP Server (Node.js)
        |  WebSocket (localhost:9877)
  Chrome Extension (Manifest V3)
        |  chrome.debugger CDP + content scripts
  Your Real Browser

The MCP server communicates with your editor via stdio (the standard MCP transport). A WebSocket bridge connects to a Chrome extension that uses chrome.debugger (CDP) for input events, network capture, screenshots, and more. Content scripts handle DOM reading and provide a fallback when CDP is unavailable.

Quick start

1. Install the MCP server

npm install -g open-browser-mcp

2. Install the Chrome extension

Option A: Chrome Web Store (recommended)

Install from the Chrome Web Store listing — one click, automatic updates.

Option B: Manual install (Developer mode)

  1. Download or clone this repository
  2. Open chrome://extensions in Chrome
  3. Enable Developer mode (toggle in the top right)
  4. Click Load unpacked
  5. Select the extension/ folder from this project

Manual installs do not auto-update. Pull the latest version and reload the extension to update.

3. Configure your MCP client

Add the server to your MCP client's configuration. The server uses stdio transport — it reads from stdin and writes to stdout, which is the standard MCP communication method.

Add to .claude/settings.json (project) or ~/.claude/settings.json (global):

{
  "mcpServers": {
    "browser": {
      "command": "open-browser-mcp"
    }
  }
}

Or use the CLI:

claude mcp add --transport stdio --scope user browser -- open-browser-mcp

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

{
  "mcpServers": {
    "browser": {
      "command": "open-browser-mcp"
    }
  }
}

Restart Cursor after editing.

Add to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "browser": {
      "command": "open-browser-mcp"
    }
  }
}

On Windows the path is %USERPROFILE%\.codeium\windsurf\mcp_config.json. You can also access it via Settings > Tools > Windsurf Settings > View Raw Config.

Add to ~/.codex/config.toml:

[mcp_servers.browser]
command = "open-browser-mcp"
args = []

Codex uses TOML format with mcp_servers (underscore). Stdio transport only.

Add to opencode.json (project root) or ~/.config/opencode/opencode.json (global):

{
  "mcp": {
    "browser": {
      "type": "local",
      "command": ["open-browser-mcp"],
      "enabled": true
    }
  }
}

OpenCode uses mcp (not mcpServers), and command is an array.

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

{
  "mcpServers": {
    "browser": {
      "command": "open-browser-mcp"
    }
  }
}

Pi also auto-discovers MCP configs from Claude Code, Cursor, and Windsurf.

Any MCP client that supports stdio transport can use this server. The general pattern is:

{
  "mcpServers": {
    "browser": {
      "command": "open-browser-mcp"
    }
  }
}

If running from source instead of a global npm install:

{
  "mcpServers": {
    "browser": {
      "command": "node",
      "args": ["/path/to/open-browser-mcp/server/index.js"]
    }
  }
}

4. Use it

Start your MCP client and try:

> Create a browser session and navigate to github.com
> Take a screenshot of the current page
> Click the sign-in button
> Fill in the username field with "myuser" and press Enter

The agent calls browser_create_session first (required), then uses the 58 available tools to interact with your browser.

Tools (58)

Organized by category. See docs/tools-reference.md for full parameter details.

Navigation

| Tool | Description | |------|-------------| | browser_create_session | Required first step. Creates the "Open Browser" tab group and attaches CDP | | browser_navigate | Navigate to a URL. External domains prompt for user approval | | browser_close | Close a tab (defaults to active tab) | | browser_go_back | Go back in browser history | | browser_go_forward | Go forward in browser history |

Input & Interaction

| Tool | Description | |------|-------------| | browser_click | Click an element by @eN ref. Supports right-click and double-click | | browser_type | Type text into an input field. Use slowly:true for autocomplete fields | | browser_hover | Hover over an element to trigger hover states | | browser_drag | Drag one element to another | | browser_select_option | Select a dropdown option by value or visible text | | browser_press_key | Send keyboard events (Enter, Tab, Ctrl+A, etc.) | | browser_file_upload | Upload files to a file input element |

Reading & Inspection

| Tool | Description | |------|-------------| | browser_snapshot | Get all interactive elements with @eN refs, roles, and text. Primary inspection tool | | browser_read_page | Read full page as text or HTML with pagination | | browser_read_markdown | Convert page to clean markdown with boilerplate removed | | browser_find | Search by CSS selector or text. Returns up to 20 matches | | browser_javascript | Execute JavaScript on the page | | browser_read_console | Read captured console messages (log, warn, error) |

Verification

| Tool | Description | |------|-------------| | browser_verify_element_visible | Assert an element is visible (PASS/FAIL) | | browser_verify_text_visible | Assert text exists on the page (PASS/FAIL) | | browser_verify_list_visible | Assert all items in a list are visible (per-item PASS/FAIL) | | browser_verify_value | Assert an element has a specific value (PASS/FAIL) |

Mouse & Coordinates

| Tool | Description | |------|-------------| | browser_mouse_click_xy | Click at exact pixel coordinates. Use humanLike:true for captchas | | browser_mouse_move_xy | Move mouse to coordinates with optional Bezier movement | | browser_mouse_drag_xy | Drag between two coordinate positions |

Tabs

| Tool | Description | |------|-------------| | browser_tab_list | List all tabs in the session group | | browser_tab_switch | Switch to a tab by ID | | browser_tab_create | Create a new tab (optional URL) |

Screenshots & Media

| Tool | Description | |------|-------------| | browser_screenshot | Capture screenshot (viewport, full page, or clipped region) | | browser_pdf_save | Save page as PDF | | browser_captcha_screenshot | Focused screenshot of captcha widget area | | browser_resize | Resize the browser window |

Captcha

| Tool | Description | |------|-------------| | browser_solve_captcha | Detect and click captcha checkbox (Turnstile, reCAPTCHA, hCaptcha) | | browser_captcha_tiles | Analyze reCAPTCHA tile challenge grid with @tN refs | | browser_batch_click | Click multiple elements/coordinates in sequence |

Batch Operations

| Tool | Description | |------|-------------| | browser_batch | Execute multiple actions in one call (click, type, select, key, wait, scroll) |

Network & Storage

| Tool | Description | |------|-------------| | browser_network_requests | Read captured network requests (method, status, URL, timing) | | browser_get_cookies | Read cookies for current page or specific URLs | | browser_set_cookie | Set a cookie with name, value, domain, and flags | | browser_clear_storage | Clear localStorage, sessionStorage, and/or cookies | | browser_block_urls | Block URL patterns from loading (ads, trackers, etc.) |

Device Emulation

| Tool | Description | |------|-------------| | browser_emulate_device | Emulate mobile/tablet viewport, user agent, and network conditions | | browser_set_geolocation | Override GPS coordinates |

DevTools & Performance

| Tool | Description | |------|-------------| | browser_get_accessibility_tree | Get the computed accessibility tree (roles, names, values) | | browser_start_tracing | Start a Chrome performance trace | | browser_stop_tracing | Stop trace and return results | | browser_generate_locator | Generate CSS, XPath, and aria locators for an element | | browser_memory_snapshot | Get JS heap size, DOM node count, layout metrics | | browser_audit_accessibility | Run an accessibility audit (ARIA, contrast, labels) |

Timing & Waiting

| Tool | Description | |------|-------------| | browser_wait | Wait for time (ms) or CSS selector to appear | | browser_wait_for_text | Poll until specific text appears on the page | | browser_scroll | Scroll the page or scroll an element into view |

Script Injection

| Tool | Description | |------|-------------| | browser_inject_script | Inject JS that runs before every page load (persists across navigations) |

Dialogs

| Tool | Description | |------|-------------| | browser_handle_dialog | Handle JavaScript alert/confirm/prompt dialogs |

Screen Recording

| Tool | Description | |------|-------------| | browser_screencast_start | Start recording as PNG frames at a given interval | | browser_screencast_stop | Stop recording and save frames to disk |

Domain Permissions

| Tool | Description | |------|-------------| | browser_set_domain_mode | Set permission mode (approval, allow_all, strict) | | browser_manage_domains | Add/remove domains from allowlist or blocklist |

Domain permission system

When the agent navigates to an external domain for the first time, a permission dialog appears in your browser. You choose how to handle it:

| Option | Behavior | |--------|----------| | This Session | Temporary approval — gone when Chrome closes | | This Project | Saved to {cwd}/.open-browser-mcp/domains.json | | All Projects | Saved to ~/.open-browser-mcp/domains.json | | Block | Reject the navigation |

Localhost URLs are always allowed without prompting.

Permission modes

Set via browser_set_domain_mode:

| Mode | Behavior | |------|----------| | approval (default) | Popup for each new domain | | allow_all | No domain checks | | strict | Only allowlisted domains, no popups, everything else blocked |

Pre-approving domains

Use browser_manage_domains to pre-approve domains so no popup appears:

> Pre-approve github.com and stackoverflow.com for this project

The agent calls browser_manage_domains with action:"allow" and domains:["github.com","stackoverflow.com"].

Visual indicator

Agent-controlled tabs show a pulsing pink border so you always know which tab the AI is operating on. The border appears when a session is created and disappears when it closes.

Configuration

Environment variables

| Variable | Default | Description | |----------|---------|-------------| | STATIC_PORT | 9876 | Port for the built-in test page server | | WS_PORT | 9877 | WebSocket bridge port (must match the extension) |

Runtime files

The server creates a .open-browser-mcp/ directory in your working directory for:

| Path | Purpose | |------|---------| | .open-browser-mcp/domains.json | Project-level domain permissions | | .open-browser-mcp/*.png | Saved screenshots | | .open-browser-mcp/screencasts/ | Screencast frame recordings |

Global domain config is stored at ~/.open-browser-mcp/domains.json.

Add .open-browser-mcp/ to your .gitignore.

Requirements

  • Node.js >= 18
  • Chrome (any recent version)
  • MCP client — Claude Code, Cursor, Windsurf, Codex, OpenCode, Pi, or any stdio-compatible MCP client

Running from source

git clone https://github.com/samonjoat/open-browser-mcp.git
cd open-browser-mcp
npm install

Then point your MCP client to the local server:

{
  "mcpServers": {
    "browser": {
      "command": "node",
      "args": ["C:/path/to/open-browser-mcp/server/index.js"]
    }
  }
}

Troubleshooting

Extension not connected

  • Verify the extension is loaded and enabled at chrome://extensions
  • Check that the extension's service worker is active (click "Service Worker" link on the extension card)
  • Ensure port 9877 is not in use by another process
  • The extension connects to ws://127.0.0.1:9877 — firewall or antivirus may block local WebSocket connections

"Debugger is already attached"

Another DevTools session or extension is using chrome.debugger on the same tab. Close other debugger connections and retry browser_create_session.

Port conflicts

If ports 9876 or 9877 are in use, set custom ports via environment variables:

STATIC_PORT=9880 WS_PORT=9881 open-browser-mcp

The extension's WebSocket URL is hardcoded to ws://127.0.0.1:9877. If you change WS_PORT, you must also update the extension's background.js to match.

Tools return "Not connected to Chrome extension"

The MCP server starts but the extension hasn't connected yet. Open Chrome with the extension loaded — the extension auto-connects on startup with exponential backoff retry.

Session idle after closing tabs

If you close all tabs in the "Open Browser" group, the session becomes idle. Call browser_create_session again to start a new session.

License

MIT