Skip to main content
Glama
README.md
# chrome-debug-mcp

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Rust](https://img.shields.io/badge/rust-stable-brightgreen.svg)](https://www.rust-lang.org)
[![chrome-debug-mcp MCP server](https://glama.ai/mcp/servers/raultov/chrome-debug-mcp/badges/score.svg)](https://glama.ai/mcp/servers/raultov/chrome-debug-mcp)

**chrome-debug-mcp** is an asynchronous Rust-based **Model Context Protocol (MCP)** server that allows AI agents and Large Language Models to natively control, automate, and debug Chromium-based browsers via the **Chrome DevTools Protocol (CDP)**.

Using [`cdp-browser-lite`](https://crates.io/crates/cdp-browser-lite) underneath (which itself re-exports the `cdp-lite` client), this MCP server directly hooks into the browser avoiding heavy abstractions, enabling live-debugging sessions directly from your editor or chat-interface. Starting from v0.2.0, it can also manage the Chrome process lifecycle automatically.

<div align="center">
  <a href="https://glama.ai/mcp/servers/raultov/chrome-debug-mcp">
    <img src="https://glama.ai/mcp/servers/raultov/chrome-debug-mcp/badges/card.svg" alt="chrome-debug-mcp MCP server" />
  </a>
</div>

---

## ✨ Features

This server natively implements a suite of tools categorized by CDP domains and native process management:

**πŸ›‘οΈ Privacy & Security**
* **Isolated Profiles (Default)**: Every time the MCP server launches Chrome, it creates a **fresh, temporary user profile** in your system's temporary directory. This profile is completely independent of your main browser profile, and it is **removed when the browser stops** β€” cookies, history, saved passwords, or session data from one session never bleed into the next.
* **Incognito-like Experience**: No cookies, history, saved passwords, or session data from your personal accounts are shared with the managed instance by default.
* **Identity Protection**: Even if an LLM has full control over the browser, it cannot access your logged-in sessions (e.g., Google, GitHub, banking) or impersonate you unless explicitly authorized.
* **Cookie Import (`--allow-cookie-import`)**: When started with the `--allow-cookie-import` flag, the server allows tools (`navigate`, `open_instance`, `restart_chrome`) to accept `copy_cookies: true` to seed the isolated ephemeral profile with your real Chrome session cookies.
  * **Opt-in & Human Consent**: Off by default. The LLM must explicitly ask the user for confirmation before setting `copy_cookies: true`.
  * **Cross-Platform Compatibility**:
    * **Linux**: Supported (AES-128-CBC `v11` decrypted via desktop keyring). Imports `os_crypt.selected_backend` to prevent silent decryption failures.
    * **macOS**: Supported (Keychain `v10` decrypted via Chrome binary ACL).
    * **Windows**: Supported (`v10`/`v20` via DPAPI/App-Bound Encryption in `os_crypt`).
  * **Destructive Relaunch Guard**: If `navigate` is called with `copy_cookies: true` on an already-running instance, it returns an error detailing all open tabs and requires `confirm_restart: true` before restarting the instance with the seeded cookies.
  * **Security**: Password databases (`Login Data`) are **never copied**.
* **User Profile Mode**: Use the `--user-profile` flag to launch Chrome using your **existing system profile**. This is useful when you want the LLM to work within your active sessions (cookies, saved logins, etc.) without having to re-authenticate on every site. **Use with caution as this provides the LLM access to your personal browser data.**
  * ⚠️ **Note on `--user-profile`**: Due to Chrome's singleton architecture, if your browser is already open, it will delegate the request and **fail to open the debugging port**. You must either **close all existing Chrome instances** before starting the MCP, or start your browser manually with the `--remote-debugging-port=9222` flag.

**πŸš€ Chrome Instance & Tab Management**
* **Multi-Instance Support**: Spawns and controls multiple concurrent, independent Chrome processes on dynamic ports, each with its own isolated profile directory. Limit the number of instances using the `--max-instances` flag.
* **Instance Registry Tools**: Use `open_instance`, `list_instances`, and `close_instance` to create, audit, and clean up additional instances. All existing tools accept an optional `instance_id` to route commands to the targeted browser.
* **Multi-Tab Support (New)**: Controls multiple concurrent tabs within a single Chrome instance, multiplexing the event streams and commands over a single WebSocket connection.
  * **Auto-Discovery**: Popups opened by target pages (e.g. `window.open()`) are automatically discovered, attached, and registered in the session's tab registry.
  * **Cache Isolation**: State caches (console messages, network traffic, debugger parsed scripts, WebMCP tools) are strictly isolated per tab so events do not bleed across targets.
* **Tab Registry Tools (New)**:
  * `open_tab` β€” Opens a new tab, optionally with a custom label and target URL. Returns JSON with the `tab_id` to reuse in other tools.
  * `list_tabs` β€” Lists all open and registered tabs for the instance as JSON (`tab_id`, `label`, `target_id`, `url`) plus the currently active tab. When no tabs are registered, tools fall back to the instance's default single-tab connection.
  * `close_tab` β€” Closes a specific tab by ID and cleans up its cache state. Returns the new active tab.
  * `switch_tab` β€” Changes the default active tab used when `tab_id` is omitted in tool calls, and optionally brings it to the foreground.
* **LLM-Friendly Interface**: The lifecycle tools (`open_instance`, `close_instance`, `open_tab`, `list_tabs`, `switch_tab`, `close_tab`) return structured JSON so agents can chain calls without regex-parsing prose, and their descriptions follow the standard MCP template (side effects, prerequisites, returns, alternatives) so models rank them correctly.
* **Target Routing (New)**: All tab-scoped tools accept an optional `tab_id` parameter to target commands and retrieve cache state from a specific tab. If omitted, the default active tab is targeted.
* **Isolated Profiles**: Launches Chrome using a fresh, temporary profile by default, ensuring it doesn't share cookies, passwords, or session data with your main browser.
* **User Profile Support**: Optionally use `--user-profile` to leverage your existing browser sessions and cookies.
* **Dynamic Port Management**: Automatically detects if the default port (9222) is in use. 
  * If the port is occupied by a Chrome instance exposing CDP (user-started or another managed `chrome-debug-mcp` instance), it **automatically attaches** to it instead of spawning a new one.
  * Managed profiles are ephemeral, so there is no persistent per-port state; a second server sharing a port simply shares the same browser (and never kills an attached instance).
* **Docker & Headless Support**: Full compatibility with Docker environments. Use the `--headless` flag to run Chrome without a GUI inside containers.

* **Remote/Host Connection**: Use the `--host` argument to connect to a Chrome instance running on a different machine or the host machine (e.g., `--host host.docker.internal` from inside a container).
* **Optional Automation Infobar**: Add the `--enable-automation` flag to explicitly show the native "Chrome is being controlled by automated test software" message. By default, this is disabled for stealthier interaction.
* **Proxy Support**: `restart_chrome` now accepts an optional `proxy_server` argument to launch Chrome routing traffic through a proxy.
* **Auto-Launch**: Automatically detects if Chrome is running on the specified port. If not, it spawns a new instance with the required flags.
* `restart_chrome`: Restarts the managed Chrome instance.
* **Capability Presets**: `restart_chrome` accepts an optional `features` array so a client can opt into extra browser capabilities per restart. It is a **closed set** β€” arbitrary Chrome flags are deliberately not accepted, to keep the tool from becoming a command line injection point:
  * `WEB_MCP` β€” enables the experimental WebMCP surface (`--enable-features=WebMCPTesting`, `--categoryExperimentalWebmcp=true`), for sites that expose tools to the browser.
  * `WEBGL_SOFTWARE` β€” forces SwiftShader software WebGL (`--use-gl=angle`, `--use-angle=swiftshader`, `--enable-unsafe-swiftshader`), for GPU-less environments such as containers.

  Presets apply to the instance started by that call; a later `restart_chrome` that omits `features` clears them, mirroring how `proxy_server` behaves.
* `stop_chrome`: Shuts down the managed Chrome instance gracefully (SIGTERM/SIGINT with fallback to SIGKILL).
* **Robust Lifecycle**: Fixed issues with dangling Chrome processes. Ephemeral profiles are deleted on stop, and `cdp-browser-lite` sweeps orphaned profile dirs left behind by abrupt kills; the "Chrome didn't shut down correctly" restore bubble is suppressed via launch flags and profile patching.
* **⚠️ Behaviour change**: Managed Chrome instances are now **terminated when the MCP server process exits** (including crashes). Previously a managed Chrome survived a server crash and was re-attached on restart; from now on it is killed. Attached (user-started) Chrome instances are never killed.

**πŸ” Proxy Authentication**
* `enable_proxy_auth`: Automatically handles proxy authentication challenges by hooking into the `Fetch` CDP domain and supplying user-provided credentials (username & password).
* **Robustness Improvements**: Now features a 30-second timeout for slower residential proxies, and defaults to only intercepting `Document` requests to prevent breaking background requests.
* **Pre-warming**: Automatically navigates to a `prewarm_url` (defaults to `http://api.ipify.org?format=json`) to establish the proxy tunnel reliably before your main navigation task. You can optionally restrict the interception to a specific `resource_type`.

**πŸ–±οΈ User Input**
* `click_element`: Simulates a native mouse click on a specific element by using a CSS selector. It calculates the center coordinates of the element and dispatches CDP mouse events directly.
* `fill_input`: Fills an input field in the DOM with specified text. It focuses the element via CSS selector and then uses native CDP `Input.insertText`.
* `scroll`: Scrolls the page by pixels, viewport heights (pages), or to a specific element. Essential for interacting with lazy-loaded content or infinite scrolling.

**πŸ“‘ Network Inspection**
* `get_network_logs`: Retrieve intercepted network requests (REST/HTTP) and WebSocket frames.
* **Advanced Filtering**: Filter logs by URL, resource type, WebSocket direction, or payload content.
* **Payload Inspection**: Access full request/response headers, REST response bodies, and WebSocket frames.
* **Context Optimized**: Optional "summary mode" to avoid flooding the LLM context window.

**πŸͺ΅ Console & Errors**
* `get_console_logs`: Retrieve console logs from the browser. This includes console.log/warn/error calls, exceptions, and network errors. Crucial for troubleshooting page scripts and errors. Includes optional log level filtering and a `clear` flag to manage state efficiently.

**⚑ Performance & Profiling**
* `get_performance_metrics`: Retrieve run-time performance metrics from the browser (e.g., JS heap size, DOM nodes, layout duration). Useful for getting a quick snapshot of the page's memory and computational overhead.
* `profile_page_performance`: Record and analyze a performance trace of the page. It automatically calculates Core Web Vitals (FCP, LCP, DCL, Load) and identifies the top Long Tasks (main thread blocking operations). You can optionally reload the page with cache disabled to simulate a cold start.

**🌐 Page & Runtime Control**
* `capture_screenshot`: Take a screenshot of the current page (or full page layout) and return it to the LLM client as a base64 encoded image block.
* `navigate`: Navigate the active tab to a specific URL.
* `reload`: Reload the current page.
* `inspect_dom`: Fetch the entire HTML or a smart snippet around a search query.
  * **Context Search**: Search for specific text and get a configurable number of characters around it.
  * **Token Efficiency**: Drastically reduce context window usage for large pages.
* `evaluate_js`: Run an arbitrary JavaScript expression globally on the page context.

**🐞 Live Debugging & Execution Control**
* `pause_on_load`: Enables the debugger and triggers a page reload, pausing execution on the very first parsed script statement.
* `search_scripts`: Search across all parsed script contexts for a query to accurately find lines and columns for breakpoints.
* `set_breakpoint`: Set a precise JS breakpoint using `script_id`, `url`, or exact `script_hash`.
* `evaluate_on_call_frame`: Evaluate a JavaScript expression directly inside the *local scope* of the currently paused debugger call frame.
* `step_over`: Step over the next expression line.
* `resume`: Unpause and resume the execution.
* `remove_breakpoint`: Remove a previously set breakpoint.

**🧩 WebMCP (page-exposed tools)**
Requires restarting Chrome with the `WEB_MCP` capability preset (see `restart_chrome`).
* `webmcp_list_tools`: Lists the tools the current page exposes to the browser (name, description, `inputSchema`, `frameId`).
* `webmcp_invoke_tool`: Invokes a page tool by name. `input` is a **JSON object string** (e.g. `"{}"` or `"{\"product\":\"knot\"}"`), matching the tool's `inputSchema`. Blocks up to 30s waiting for the result.
* `webmcp_get_invocation`: Returns the status (`Pending`/`Completed`/`Error`/`Canceled`) and result of an invocation by `invocationId` β€” non-blocking.
* `webmcp_list_invocations`: Lists all invocations in the session with their status, with optional `status` filter.

  ⚠️ **Consent dialogs**: page tools with side effects (clipboard writes, form submissions…) may show an on-page confirmation dialog that a human must click. In that case `webmcp_invoke_tool` returns a timeout error containing the `invocationId` β€” the invocation stays `Pending` (it is NOT canceled), so you can poll it with `webmcp_get_invocation` after the user approves or denies it.

**πŸ§ͺ Stability & Reliability**
* **Extensive Unit Testing**: Comprehensive test suite ensuring the reliability of event processing and tool deserialization, particularly in the `debugger` domain.
* **Side-Effect Free Tests**: All unit tests are designed to run in isolation, without launching real Chrome instances or modifying the filesystem.
* **Internal Refactoring**: Decoupled core logic through traits and dependency injection to ensure long-term maintainability.

---

## βš™οΈ Configuration

By default, the MCP Server discovers the Chrome executable through `cdp-browser-lite`'s cross-platform search: `CHROME_PATH` first (absolute priority), then common binaries in your `PATH` (`google-chrome`, `google-chrome-stable`, `chromium`, `chromium-browser`), then OS-specific locations (`/Applications/Google Chrome.app/...` on macOS, the `chrome.exe` install dir on Windows, `/usr/bin/google-chrome`, `/opt/google/chrome/chrome` and `/snap/bin/chromium` on Linux). This is a strict superset of the paths the server previously hardcoded.

**Arguments:**
* `--local`: Restricts navigation to local addresses only (`localhost`, `127.0.0.1`, `192.168.x.x`, or `*.local`). Highly recommended for security.
* `--headless`: Runs Chrome in headless mode (no GUI). Essential for Docker or server environments.
* `--user-profile`: Use the default system user profile (sessions, cookies, etc.) instead of a fresh one. This is useful for avoiding repeated logins during research sessions.
* `--host`: Specifies the target host for the Chrome instance (default: `127.0.0.1`). Use `host.docker.internal` to connect to a host machine from a container.
* `--port`: Specifies the remote debugging port (default: `9222`).
* `--enable-automation`: Enables the "controlled by automated software" infobar.
* `--max-instances`: Limits the maximum number of concurrent Chrome instances (default: 8). Ignored if `--user-profile` is set.

**Environment Variables:**
* `CHROME_PATH`: Explicitly define the path to the Chrome executable.

---

## 🐳 Docker & Headless Usage (v1.0.0)

`chrome-debug-mcp` is fully container-ready. This allows several powerful use cases for LLMs:

### 1. Cloud Deployment (via Glama)
The easiest way to use this server. Glama spawns a Docker container with Chrome pre-installed. The LLM gets immediate access to a browser in the cloud without any local setup.

### 2. Isolated Local Use
Run everything inside Docker to avoid installing Chrome or Rust on your host machine:
```bash
docker build -t chrome-mcp .
docker run -i --rm chrome-mcp --headless
```

### 3. Hybrid Mode (Container controlling Host)
The MCP server runs inside a secure Docker container but controls the Chrome instance on your actual desktop. This allows the LLM to assist you in your real browsing session:
1. Start your local Chrome with: `--remote-debugging-port=9222`
   * *Note: If you need proxy support in this mode, you must also start Chrome with the `--proxy-server="http://your-proxy:port"` flag.*
2. Run the container:
```bash
# On macOS/Windows
docker run -i --rm chrome-mcp --host host.docker.internal
```

---

## πŸš€ Quick Start

The easiest way to install and run the MCP Server natively is via Rust's Cargo or by downloading the pre-compiled binaries. You **do not** need to start Chrome manually anymore, the MCP Server will automatically launch a visible instance of Chrome with the correct debugging flags.

### 1. Installation

**Option A: Pre-compiled Binaries (Recommended)**
Go to the [Releases](https://github.com/raultov/chrome-debug-mcp/releases) page and download the native executable for your platform (macOS, Windows, Linux). We provide `.msi` installers for Windows and shell scripts for UNIX systems.

**Option B: Install via Cargo**
```bash
cargo install --git https://github.com/raultov/chrome-debug-mcp
```

**Option C: Install via Shell Script (Unix)**
```bash
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/raultov/chrome-debug-mcp/releases/latest/download/chrome-debug-mcp-installer.sh | sh
```

### 2. Configure your MCP Client
This server is fully tested and confirmed to work with **Claude Code**, **agy**, and **codex**. Configure your AI client to execute the server using any of the following modes.

#### **Universal Configuration (JSON)**
Most MCP clients (like Claude Code or any JSON-based config) use this structure. Here are the three main usage modes:

```json
{
  "mcpServers": {
    "chrome-debug-mcp": {
      "command": "chrome-debug-mcp",
      "args": [],
      "env": {}
    },
    "chrome-docker": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "chrome-debug-mcp:v1.0.9", "--headless"]
    },
    "chrome-docker-hybrid": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "--net=host",
        "chrome-debug-mcp:v1.0.9",
        "--host",
        "127.0.0.1"
      ]
    }
  }
}
```
*Note: The `chrome-docker-hybrid` mode using `--net=host` is the recommended way on Linux to allow the container to access your local Chrome instance on `127.0.0.1`.*

#### **Claude Code**
To add and activate the server in Claude Code:
```bash
claude mcp add chrome-debug-mcp chrome-debug-mcp
```

### 3. Usage
Once connected, the AI agent will automatically handle starting Chrome when the first command is executed. The browser will remain visible so you can visually track the debugging process.

### 4. Agent Workflows & Multi-Instance Guidance

LLMs can operate this server using a few optimized patterns:

#### A. Isolated Multi-Instance Scenarios
When running automated browser sessions, you can launch separate Chrome processes to prevent cookie pollution or tab collision:
1. Call `open_instance` with `label: "user-session-1"` or optional proxy server configs. This returns a unique `instance_id` (e.g. `chrome-2`).
2. Pass the `instance_id` explicitly to downstream tools like `navigate`, `evaluate_js`, or `webmcp_list_tools`.
3. Clear up resources using `close_instance` once finished.

#### B. Working with WebMCP
If you navigate to a page that supports WebMCP (e.g., https://www.knot.kz/#/agent-tools):
1. Tools registered by the web page can be retrieved using `webmcp_list_tools`.
2. By default, `WEB_MCP` is disabled for safety. If the tools list is empty, call `restart_chrome` with `features: ["WEB_MCP"]` and then `reload`.
3. Invoke page tools using `webmcp_invoke_tool`, providing input JSON arguments. If a consent dialog pauses execution on the web page, the tool will timeout after 30 seconds but keep the invocation pending. You can poll its result using `webmcp_get_invocation`.

---

## πŸ›  Compilation (From Source)

If you wish to compile from source:

```bash
git clone https://github.com/raultov/chrome-debug-mcp
cd chrome-debug-mcp
cargo build --release
```

### Development & Code Quality

```bash
make check                                  # Run all local quality gates (fmt, clippy, test, dupes)

# Or run gates individually:
cargo clippy --all-targets -- -D warnings  # Must pass
cargo fmt -- --check                        # Must pass
cargo test --all-targets                    # Run unit tests
cargo dupes check                           # Code duplication check
```

The resulting binary will be located in `target/release/chrome-debug-mcp`. This project utilizes `cargo-dist` to handle cross-platform native distribution seamlessly via GitHub Actions.

---

## πŸ“– Why this MCP Server?

Other integration servers like Puppeteer/Playwright wrappers are high-level, heavy, and typically fail at exposing **real, interactive step-by-step debuggers**. This MCP server uses raw CDP messages mapping them 1:1 to LLM tools, which allows intelligent agents to *literally* step over JS, read local scope variables natively, search inside V8 compiler contexts, and understand exactly why a script is crashing.

---

## πŸ“œ License

This project is licensed under the **MIT License**. See the [LICENSE](LICENSE) file for more details.

TDQS

A3.9/5.0

Scored across 35 tools

Disambiguation3/5

Most core browser and debugging tools are distinct (navigate, click, fill, evaluate), but there is notable overlap between lifecycle and state tools (stop_chrome vs close_instance, restart vs close, get_network_logs vs get_custom_events) and between stepping commands (step_over description incorrectly mentions 'step_over enters functions' while 'step_out' is mentioned but not defined). This ambiguity can cause agent misselection in edge cases.

Naming Consistency4/5

Tool names mostly follow a consistent verb_noun pattern (open_tab, close_tab, list_tabs, set_breakpoint, resume, step_over). There are minor inconsistencies: 'webmcp_*' prefix is a different convention, and some verbs like 'restart', 'stop', 'close' create near-synonyms. Overall pattern is predictable and readable.

Tool Count4/5

With 35 tools, the count is on the heavier side, but the server covers a broad scope: browser lifecycle, tab management, DOM interaction, debugging, performance, network, console, and experimental CDP. Most tools earn their place; a few like enable_proxy_auth and webmcp_* could be bundled, but none feel redundant.

Completeness4/5

The tool surface covers the full browser automation lifecycle (open/close instances and tabs, navigate, interact, inspect, debug, monitor performance, and network). Missing operations include no explicit 'step_out' despite being referenced, and limited screenshot options (no element-specific capture). Minor gaps that agents can work around with evaluate_js or send_cdp_command.

Maintenance

ActivityMaintained
ResponsivenessWithin a week