An MCP Server for Chrome DevTools, following the Chrome DevTools Protocol. Integrates with Claude Desktop and Claude Code.
SaferSkills independently audited chrome-devtools-mcp (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
A Model Context Protocol (MCP) server that provides Chrome DevTools Protocol integration through MCP. This allows you to debug web applications by connecting to Chrome's developer tools.
Available as a Claude Desktop Extension (.dxt) for easy one-click installation!
This MCP server acts as a bridge between Claude and Chrome's debugging capabilities. Once installed in Claude Desktop, you can:
Note: This is an MCP server that runs within Claude Desktop - you don't need to run any separate servers or processes.
Download the pre-built extension:
.dxt file from Releases.dxt fileThe extension includes all dependencies and is ready to use immediately!
Quick Install (most common):
git clone https://github.com/benjaminr/chrome-devtools-mcp.git
cd chrome-devtools-mcp
mcp install server.py -n "Chrome DevTools MCP" --with-editable .Note: Themcpcommand is part of the Python MCP SDK. Install it withpip install mcpif not already available.
All Installation Options:
# Clone the repository
git clone https://github.com/benjaminr/chrome-devtools-mcp.git
cd chrome-devtools-mcp
# The --with-editable flag uses pyproject.toml to install dependencies
# Basic installation with local dependencies
mcp install server.py --with-editable .
# Install with custom name
mcp install server.py -n "Chrome DevTools MCP" --with-editable .
# Install with environment variables
mcp install server.py -n "Chrome DevTools MCP" --with-editable . -v CHROME_DEBUG_PORT=9222
# Install with additional packages if needed
mcp install server.py -n "Chrome DevTools MCP" --with-editable . --with websockets --with aiohttp
# Install with environment file (copy .env.example to .env first)
cp .env.example .env
# Edit .env with your settings
mcp install server.py -n "Chrome DevTools MCP" --with-editable . -f .envFor Claude Code CLI users:
git clone https://github.com/benjaminr/chrome-devtools-mcp.git
cd chrome-devtools-mcpuv sync # Creates .venv and installs dependenciesIMPORTANT: Claude Code needs absolute paths to both the Python interpreter and the server script to work correctly.
Recommended setup using absolute paths:
# Get the absolute paths
SERVER_PATH="$(pwd)/server.py"
PYTHON_PATH="$(pwd)/.venv/bin/python"
# Add the server with absolute paths
claude mcp add chrome-devtools "$PYTHON_PATH" "$SERVER_PATH" -e CHROME_DEBUG_PORT=9222Alternative: Using the system Python (if dependencies are installed globally):
# Only if you've installed dependencies globally
claude mcp add chrome-devtools python "$(pwd)/server.py" -e CHROME_DEBUG_PORT=9222With custom scope:
# Add to user scope (available across all projects)
claude mcp add chrome-devtools "$(pwd)/.venv/bin/python" "$(pwd)/server.py" -s user -e CHROME_DEBUG_PORT=9222
# Add to project scope (only for this project)
claude mcp add chrome-devtools "$(pwd)/.venv/bin/python" "$(pwd)/server.py" -s project -e CHROME_DEBUG_PORT=9222# List configured MCP servers
claude mcp list
# Get details about the server (check that paths are absolute)
claude mcp get chrome-devtools
# The output should show absolute paths like:
# Command: /Users/you/chrome-devtools-mcp/.venv/bin/python
# Args: ["/Users/you/chrome-devtools-mcp/server.py"]Common Path Issues and Solutions:
/path/to/.venv/bin/python /path/to/server.pygit clone https://github.com/benjaminr/chrome-devtools-mcp.git
cd chrome-devtools-mcpWith uv (recommended):
uv syncWith pip:
pip install -r requirements.txtEdit your Claude Desktop config file:
~/Library/Application Support/Claude/claude_desktop_config.json%APPDATA%/Claude/claude_desktop_config.json{
"mcpServers": {
"chrome-devtools": {
"command": "python",
"args": ["/absolute/path/to/chrome-devtools-mcp/server.py"],
"env": {
"CHROME_DEBUG_PORT": "9222"
}
}
}
}After installation (either method), verify the server is available:
get_connection_status()For other MCP clients, run the server directly:
python server.pyOnce installed in Claude Desktop, you can start debugging any web application:
One-step setup (recommended):
start_chrome_and_connect("localhost:3000")Replace `localhost:3000` with your application's URL
If Chrome isn't found automatically:
start_chrome_and_connect("localhost:3000", chrome_path="/path/to/chrome")Use the `chrome_path` parameter to specify a custom Chrome location
This command will:
Manual setup (if you prefer step-by-step):
start_chrome()
navigate_to_url("localhost:3000")
connect_to_browser()Once connected, use these commands:
get_network_requests() - View HTTP trafficget_console_error_summary() - Analyse JavaScript errorsinspect_console_object("window") - Inspect any JavaScript objectstart_chrome(port?, url?, headless?, chrome_path?, auto_connect?) - Start Chrome with remote debugging and optional auto-connectionstart_chrome_and_connect(url, port?, headless?, chrome_path?) - Start Chrome, connect, and navigate in one stepconnect_to_browser(port?) - Connect to existing Chrome instancenavigate_to_url(url) - Navigate to a specific URLdisconnect_from_browser() - Disconnect from browserget_connection_status() - Check connection statusget_network_requests(filter_domain?, filter_status?, limit?) - Get network requests with filteringget_network_response(request_id) - Get detailed response data including bodyget_console_logs(level?, limit?) - Get browser console logsget_console_error_summary() - Get organized summary of errors and warningsexecute_javascript(code) - Execute JavaScript in browser contextclear_console() - Clear the browser consoleinspect_console_object(expression) - Deep inspect any JavaScript objectmonitor_console_live(duration_seconds) - Monitor console output in real-timeget_page_info() - Get comprehensive page metrics and performance dataevaluate_in_all_frames(code) - Execute JavaScript in all frames/iframesget_performance_metrics() - Get detailed performance metrics and resource timingget_storage_usage_and_quota(origin) - Get storage usage and quota informationclear_storage_for_origin(origin, storage_types?) - Clear storage by type and originget_all_cookies() - Get all browser cookiesclear_all_cookies() - Clear all browser cookiesset_cookie(name, value, domain, path?, expires?, http_only?, secure?, same_site?) - Set a cookieget_cookies(domain?) - Get browser cookies with optional domain filteringget_storage_key_for_frame(frame_id) - Get storage key for a specific frametrack_cache_storage(origin, enable?) - Enable/disable cache storage trackingtrack_indexeddb(origin, enable?) - Enable/disable IndexedDB trackingoverride_storage_quota(origin, quota_size_mb?) - Override storage quotaWhen your web application makes API calls that fail or return unexpected data:
Easy setup: Use the one-step command to start Chrome and navigate to your app:
Example workflow:
You: "I need to debug my React app at localhost:3000"
Claude: I'll start Chrome with debugging enabled and navigate to your app.
start_chrome_and_connect("localhost:3000")
Perfect! Chrome is now running with debugging enabled and connected to your app. Let me check for any failed network requests:
get_network_requests(filter_status=500)
I can see there are 3 failed requests to your API. Let me get the details of the first one:
get_network_response("request-123")Manual setup (if you prefer):
start_chrome()navigate_to_url("localhost:3000")connect_to_browser()get_network_requests() to see all API callsWhen your web application has JavaScript errors or unexpected behaviour:
get_console_error_summary() to see all errorsmonitor_console_live(10) to watch for new errors as you interactinspect_console_object("myVariable") to examine application stateExample workflow:
You: "My React component isn't updating properly"
Claude: Let me check the JavaScript console for any errors.
get_console_error_summary()
I can see there are 2 JavaScript errors. Let me also monitor the console while you interact with the component:
monitor_console_live(15)
Now try clicking the component that isn't working. I'll watch for any new errors or warnings.When your web application loads slowly or uses too much memory:
get_page_info() to see load times and resource countsget_performance_metrics() to see detailed timing dataExample workflow:
You: "My application takes too long to load"
Claude: Let me analyse the performance of your application.
get_page_info()
I can see your page has 47 scripts and took 3.2 seconds to load. Let me get more detailed performance data:
get_performance_metrics()
The main bottleneck is the initial JavaScript bundle which is 2.1MB. The DOM processing also takes 800ms.When login or session management isn't working:
get_cookies() to see authentication cookiesmonitor_console_live() and get_network_requests() during the login processExample workflow:
You: "Users can't stay logged in"
Claude: Let me check the authentication setup.
get_cookies()
I can see the auth cookie is present. Let me check what happens during login by monitoring the network:
get_network_requests(filter_domain="your-api.com")
I notice the login request returns a 200 but no Set-Cookie header. Let me also check localStorage:
execute_javascript("Object.keys(localStorage)")get_document(depth?, pierce?) - Retrieve DOM document structurequery_selector(node_id, selector) - Find single element by CSS selectorquery_selector_all(node_id, selector) - Find multiple elements by CSS selectorget_element_attributes(node_id) - Get all attributes of an elementget_element_outer_html(node_id) - Get outer HTML of an elementget_element_box_model(node_id) - Get layout informationdescribe_element(node_id, depth?) - Get detailed element descriptionget_element_at_position(x, y) - Get element at screen positionsearch_elements(query) - Search DOM elements by text/attributesfocus_element(node_id) - Focus a DOM elementget_computed_styles(node_id) - Get computed CSS stylesget_inline_styles(node_id) - Get inline stylesget_matched_styles(node_id) - Get all CSS rules matching an elementget_stylesheet_text(stylesheet_id) - Get stylesheet contentget_background_colors(node_id) - Get background colors and fontsget_platform_fonts(node_id) - Get platform font informationget_media_queries() - Get all media queriescollect_css_class_names(stylesheet_id) - Collect CSS class namesstart_css_coverage_tracking() - Start CSS coverage trackingstop_css_coverage_tracking() - Stop and get CSS coverage results| Task | Command |
|---|---|
| Start Chrome and connect to app | start_chrome_and_connect("localhost:3000") |
| Start Chrome (manual setup) | start_chrome() |
| Navigate to page | navigate_to_url("localhost:3000") |
| Connect to browser | connect_to_browser() |
| See all network requests | get_network_requests() |
| Find failed API calls | get_network_requests(filter_status=404) |
| Check for JavaScript errors | get_console_error_summary() |
| Watch console in real-time | monitor_console_live(10) |
| Check page load performance | get_page_info() |
| Examine a variable | inspect_console_object("window.myApp") |
| View cookies | get_cookies() |
| Run JavaScript | execute_javascript("document.title") |
CHROME_DEBUG_PORT - Chrome remote debugging port (default: 9222)npm run dev, python -m http.server, etc.) start_chrome_and_connect("localhost:3000")Replace with your application's URL
If you prefer step-by-step control:
start_chrome() - Launch Chrome with debuggingnavigate_to_url("your-app-url") - Navigate to your applicationconnect_to_browser() - Connect the MCP serverIf the server appears in Claude but shows as "disabled", try these steps:
~/Library/Logs/Claude/mcp*.log%APPDATA%/Claude/logs/mcp*.log # Reinstall with verbose output
mcp remove "Chrome DevTools MCP"
mcp install server.py -n "Chrome DevTools MCP" --with-editable . -v CHROME_DEBUG_PORT=9222
# Check installation status
mcp list
# Test the server manually
python3 server.py # Ensure all dependencies are available
pip install mcp websockets aiohttp
# Test imports
python3 -c "from server import mcp; print('OK')"pip install mcpmcp list to verify the server is installed--with-editable . to install local dependenciespip install -r requirements.txt.env file format or -v flag syntax--with-editable . flag for local package installationStep 1: Check MCP CLI Status
# List all installed servers
mcp list
# Check specific server status
mcp status "Chrome DevTools MCP"Step 2: Test Server Manually
# Test if server starts without errors
python3 server.py
# Test imports
python3 -c "from server import mcp; print(f'Server: {mcp.name}')"Step 3: Check Configuration
For Claude Desktop:
# View current configuration (macOS)
cat "~/Library/Application Support/Claude/claude_desktop_config.json"
# View current configuration (Windows)
type "%APPDATA%/Claude/claude_desktop_config.json"For Claude Code:
# List configured MCP servers
claude mcp list
# Get details about a specific server
claude mcp get chrome-devtools
# IMPORTANT: Verify paths are absolute, not relative
# Good example output:
# Command: /Users/you/chrome-devtools-mcp/.venv/bin/python
# Args: ["/Users/you/chrome-devtools-mcp/server.py"]
# Bad example output:
# Command: python
# Args: ["server.py"]
# Test the exact command Claude Code will use
/path/to/.venv/bin/python /path/to/server.py
# Check if server is working
claude mcp serve --helpStep 3.5: Fix Path Issues (Claude Code specific)
# If paths are relative, remove and re-add with absolute paths
claude mcp remove chrome-devtools
# Re-add with absolute paths
SERVER_PATH="$(pwd)/server.py"
PYTHON_PATH="$(pwd)/.venv/bin/python"
claude mcp add chrome-devtools "$PYTHON_PATH" "$SERVER_PATH" -e CHROME_DEBUG_PORT=9222Step 4: Reinstall if Needed
For MCP CLI:
# Clean reinstall
mcp remove "Chrome DevTools MCP"
mcp install server.py -n "Chrome DevTools MCP" --with-editable .
# Restart Claude Desktop completelyFor Claude Code:
# Remove and re-add the server
claude mcp remove chrome-devtools
claude mcp add chrome-devtools python server.py -e CHROME_DEBUG_PORT=9222
# Or update with different scope
claude mcp add chrome-devtools python server.py -s user -e CHROME_DEBUG_PORT=9222| Error | Solution |
|---|---|
| "Module not found" | Use --with-editable . flag |
| "No server object found" | Server should export mcp object (already fixed) |
| "Import error" | Check pip install mcp websockets aiohttp |
| "Permission denied" | Use absolute paths in config |
| "Server disabled" | Check Claude Desktop logs, restart Claude |
| "python: command not found" (Claude Code) | Use absolute path to venv Python: /path/to/.venv/bin/python |
| "server.py: No such file" (Claude Code) | Use absolute path to server: /path/to/server.py |
| "ModuleNotFoundError" (Claude Code) | Use venv Python that has dependencies installed |
For Claude Desktop: If MCP CLI isn't working, add this to Claude Desktop config manually:
{
"mcpServers": {
"chrome-devtools": {
"command": "python3",
"args": ["/absolute/path/to/chrome-devtools-mcp/server.py"],
"env": {
"CHROME_DEBUG_PORT": "9222"
}
}
}
}For Claude Code: If the claude mcp add command isn't working, you can use the JSON format with absolute paths:
# Get absolute paths first
SERVER_PATH="$(pwd)/server.py"
PYTHON_PATH="$(pwd)/.venv/bin/python"
# Add server using JSON configuration with absolute paths
claude mcp add-json chrome-devtools "{
\"command\": \"$PYTHON_PATH\",
\"args\": [\"$SERVER_PATH\"],
\"env\": {
\"CHROME_DEBUG_PORT\": \"9222\"
}
}"
# Or if you have it working in Claude Desktop, import from there
claude mcp add-from-claude-desktopExample of correct Claude Code configuration (with absolute paths):
{
"command": "/Users/you/chrome-devtools-mcp/.venv/bin/python",
"args": ["/Users/you/chrome-devtools-mcp/server.py"],
"env": {
"CHROME_DEBUG_PORT": "9222"
}
}start_chrome()get_connection_status() to check the connectionconnect_to_browser() or used start_chrome_and_connect()This section is for developers who want to test or modify the MCP server itself.
With uv (recommended):
git clone https://github.com/benjaminr/chrome-devtools-mcp.git
cd chrome-devtools-mcp
uv syncWith pip:
git clone https://github.com/benjaminr/chrome-devtools-mcp.git
cd chrome-devtools-mcp
pip install -e ".[dev]"# Format code
uv run ruff format .
# Lint code
uv run ruff check .
# Type checking
uv run mypy src/Install DXT packaging tools:
npm install -g @anthropic-ai/dxtBuild the extension:
# Quick build
make package
# Or manually
npx @anthropic-ai/dxt packUsing Makefile for development:
make help # Show all commands
make install # Install dependencies
make dev # Setup development environment + pre-commit
make check # Run all checks (lint + type + test)
make pre-commit # Run pre-commit hooks manually
make package # Build .dxt extension
make release # Full release buildThis project uses pre-commit hooks to ensure code quality:
Pre-commit hooks run automatically on git commit and can be run manually with make pre-commit.
MIT License
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.