Chrome DevTools MCP Setup for WSL2: Complete Guide

Chrome DevTools MCP Setup for WSL2: Complete Guide

·

Chrome DevTools MCP Setup for WSL2

Complete guide for running Chrome on Windows while controlling it from Claude Code in WSL2.

Overview

This setup allows Claude Code running in WSL2 to control Chrome browser running on Windows host through the Chrome DevTools Protocol.

Architecture:

Claude Code (WSL2) → 172.30.64.1:9222 → Port Proxy (Windows) → 127.0.0.1:9222 → Chrome (Windows)

Prerequisites

  • Windows 11 with WSL2 installed
  • Chrome installed on Windows
  • Claude Code running in WSL2
  • Administrator privileges on Windows

Quick Start

1. Start Chrome with Debugging

From WSL2, run:

./start-chrome-windows.sh

Or manually from Windows PowerShell:

Start-Process "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" -ArgumentList "--remote-debugging-port=9222","--user-data-dir=C:\Temp\chrome-debug"

2. Verify Connection

Test from WSL2:

curl -s http://172.30.64.1:9222/json/version

Expected output:

{
   "Browser": "Chrome/138.0.7204.97",
   "Protocol-Version": "1.3",
   ...
}

3. Restart Claude Code

The MCP configuration is already set up in ~/.claude.json. Just restart Claude Code to activate the chrome-devtools MCP server.

Configuration Details

MCP Configuration (~/.claude.json)

"chrome-devtools": {
  "command": "npx",
  "args": [
    "-y",
    "chrome-devtools-mcp@latest",
    "--remoteDebuggingPort",
    "9222"
  ],
  "env": {
    "CHROME_HOST": "172.30.64.1"
  }
}

Windows Port Proxy

Forwards connections from WSL2 network interface to Chrome:

Listen: 172.30.64.1:9222
Forward to: 127.0.0.1:9222

View configuration:

powershell.exe -Command "netsh interface portproxy show v4tov4"

Windows Firewall Rules

Two firewall rules allow inbound connections:

  • Chrome Remote Debugging: General rule for port 9222
  • Chrome Debug WSL: Specific rule for WSL adapter IP (172.30.64.1)

View rules:

powershell.exe -Command "Get-NetFirewallRule -DisplayName 'Chrome*Debug*' | Format-List DisplayName,Enabled,Action"

Setup Scripts

start-chrome-windows.sh

Starts Chrome on Windows with remote debugging enabled:

#!/bin/bash
# Start Chrome on Windows with remote debugging enabled for Claude Code in WSL2

echo "Starting Chrome on Windows with remote debugging..."
echo "Port 9222 will be accessible from WSL2 via 172.30.64.1"
echo

# Check if Chrome is already running
if powershell.exe -Command "Get-Process chrome -ErrorAction SilentlyContinue" > /dev/null 2>&1; then
    echo "⚠️  Chrome is already running. Stopping existing instances..."
    powershell.exe -Command "Stop-Process -Name chrome -Force" 2>/dev/null
    sleep 2
fi

# Start Chrome with debugging enabled
echo "🚀 Starting Chrome..."
powershell.exe -Command "Start-Process 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' -ArgumentList '--remote-debugging-port=9222','--user-data-dir=C:\Temp\chrome-debug' -WindowStyle Normal" 2>/dev/null

# Wait for Chrome to start
sleep 3

# Check if Chrome started successfully
if ! powershell.exe -Command "Get-Process chrome -ErrorAction SilentlyContinue" > /dev/null 2>&1; then
    echo "❌ Failed to start Chrome. Please check if Chrome is installed at:"
    echo "   C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe"
    exit 1
fi

# Verify debugging port is accessible
echo "🔍 Checking if Chrome debugging port is accessible..."
sleep 2

if curl -s http://172.30.64.1:9222/json/version > /dev/null 2>&1; then
    echo "✅ Chrome started successfully and is accessible from WSL2!"
    echo
    echo "Chrome DevTools Protocol endpoint: http://172.30.64.1:9222"
    echo
    echo "Test connection:"
    echo "  curl -s http://172.30.64.1:9222/json/version"
    echo
    echo "You can now restart Claude Code to use the chrome-devtools MCP server."
else
    echo "⚠️  Chrome started but debugging port is not accessible yet."
    echo "This may take a few more seconds. Try testing manually:"
    echo "  curl -s http://172.30.64.1:9222/json/version"
    echo
    echo "If connection fails, run: ./check-connection.sh"
fi

setup-network.sh

One-time network setup script that configures Windows port proxy and firewall rules:

#!/bin/bash
# One-time network setup for Chrome DevTools MCP in WSL2
# Configures Windows port proxy and firewall rules

echo "Chrome DevTools MCP Network Setup for WSL2"
echo "=========================================="
echo

# Get WSL adapter IP from Windows
echo "🔍 Detecting WSL adapter IP address..."
WSL_IP=$(powershell.exe -Command "Get-NetIPAddress -InterfaceAlias 'vEthernet (WSL)' -AddressFamily IPv4 | Select-Object -ExpandProperty IPAddress" | tr -d '\r')

if [ -z "$WSL_IP" ]; then
    echo "❌ Failed to detect WSL adapter IP address"
    echo "Please run this command manually in PowerShell (as Administrator):"
    echo "  Get-NetIPAddress -InterfaceAlias 'vEthernet (WSL)' -AddressFamily IPv4"
    exit 1
fi

echo "✅ WSL adapter IP: $WSL_IP"
echo

# Check if running with admin privileges
echo "🔐 Checking administrator privileges..."
powershell.exe -Command "if (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) { exit 1 }" 2>/dev/null
if [ $? -ne 0 ]; then
    echo "❌ This script requires administrator privileges"
    echo
    echo "Please run PowerShell as Administrator and execute:"
    echo "  wsl -d Ubuntu bash /home/panxf/devtools/setup-network.sh"
    exit 1
fi

echo "✅ Running with administrator privileges"
echo

# Configure port proxy
echo "⚙️  Configuring port proxy..."
echo "   Forwarding: $WSL_IP:9222 → 127.0.0.1:9222"

# Remove existing port proxy rule if it exists
powershell.exe -Command "netsh interface portproxy delete v4tov4 listenport=9222 listenaddress=$WSL_IP" 2>/dev/null

# Add new port proxy rule
powershell.exe -Command "netsh interface portproxy add v4tov4 listenport=9222 listenaddress=$WSL_IP connectport=9222 connectaddress=127.0.0.1" 2>/dev/null

if [ $? -eq 0 ]; then
    echo "✅ Port proxy configured successfully"
else
    echo "❌ Failed to configure port proxy"
    exit 1
fi
echo

# Configure firewall rules
echo "🛡️  Configuring Windows Firewall rules..."

# Rule 1: General Chrome Remote Debugging
echo "   Creating rule: Chrome Remote Debugging"
powershell.exe -Command "Remove-NetFirewallRule -DisplayName 'Chrome Remote Debugging' -ErrorAction SilentlyContinue" 2>/dev/null
powershell.exe -Command "New-NetFirewallRule -DisplayName 'Chrome Remote Debugging' -Direction Inbound -LocalPort 9222 -Protocol TCP -Action Allow -Profile Any" 2>/dev/null | Out-Null

if [ $? -eq 0 ]; then
    echo "   ✅ Chrome Remote Debugging rule created"
else
    echo "   ❌ Failed to create Chrome Remote Debugging rule"
fi

# Rule 2: Specific WSL adapter rule
echo "   Creating rule: Chrome Debug WSL ($WSL_IP)"
powershell.exe -Command "Remove-NetFirewallRule -DisplayName 'Chrome Debug WSL' -ErrorAction SilentlyContinue" 2>/dev/null
powershell.exe -Command "New-NetFirewallRule -DisplayName 'Chrome Debug WSL' -Direction Inbound -LocalAddress $WSL_IP -LocalPort 9222 -Protocol TCP -Action Allow -Profile Any" 2>/dev/null | Out-Null

if [ $? -eq 0 ]; then
    echo "   ✅ Chrome Debug WSL rule created"
else
    echo "   ❌ Failed to create Chrome Debug WSL rule"
fi
echo

# Update Claude Code config with correct IP
echo "📝 Updating Claude Code MCP configuration..."
CLAUDE_CONFIG="$HOME/.claude.json"

if [ -f "$CLAUDE_CONFIG" ]; then
    # Check if chrome-devtools MCP exists
    if grep -q '"chrome-devtools"' "$CLAUDE_CONFIG"; then
        # Update CHROME_HOST with new IP
        sed -i.bak "s/\"CHROME_HOST\": \"[^\"]*\"/\"CHROME_HOST\": \"$WSL_IP\"/" "$CLAUDE_CONFIG"
        echo "✅ Updated CHROME_HOST to $WSL_IP in $CLAUDE_CONFIG"
    else
        echo "⚠️  chrome-devtools MCP not found in $CLAUDE_CONFIG"
        echo "   Please add it manually or run Claude Code to generate it"
    fi
else
    echo "⚠️  $CLAUDE_CONFIG not found"
fi
echo

# Display configuration summary
echo "✅ Network setup completed!"
echo
echo "Configuration Summary:"
echo "====================="
echo "WSL Adapter IP: $WSL_IP"
echo "Port Proxy: $WSL_IP:9222 → 127.0.0.1:9222"
echo "Firewall Rules: Chrome Remote Debugging, Chrome Debug WSL"
echo
echo "Next Steps:"
echo "1. Start Chrome: ./start-chrome-windows.sh"
echo "2. Verify connection: curl -s http://$WSL_IP:9222/json/version"
echo "3. Restart Claude Code to use the chrome-devtools MCP server"
echo
echo "View configuration:"
echo "  Port Proxy: powershell.exe -Command 'netsh interface portproxy show v4tov4'"
echo "  Firewall: powershell.exe -Command \"Get-NetFirewallRule -DisplayName 'Chrome*Debug*' | Format-List\""

check-connection.sh

Diagnostic script to verify the entire setup:

#!/bin/bash
# Diagnostic script for Chrome DevTools MCP connection in WSL2

echo "Chrome DevTools MCP Connection Diagnostics"
echo "=========================================="
echo

# Get WSL adapter IP
echo "🔍 WSL Network Configuration"
echo "----------------------------"
WSL_IP=$(powershell.exe -Command "Get-NetIPAddress -InterfaceAlias 'vEthernet (WSL)' -AddressFamily IPv4 | Select-Object -ExpandProperty IPAddress" | tr -d '\r')

if [ -z "$WSL_IP" ]; then
    echo "❌ Failed to detect WSL adapter IP"
else
    echo "✅ WSL Adapter IP: $WSL_IP"
fi

DNS_SERVER=$(grep nameserver /etc/resolv.conf | awk '{print $2}')
echo "ℹ️  DNS Server: $DNS_SERVER"
echo

# Check Chrome process
echo "🌐 Chrome Process Status"
echo "------------------------"
CHROME_RUNNING=$(powershell.exe -Command "Get-Process chrome -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count" | tr -d '\r')

if [ "$CHROME_RUNNING" -gt 0 ]; then
    echo "✅ Chrome is running ($CHROME_RUNNING process(es))"

    # Check Chrome listening ports
    echo
    echo "🔌 Chrome Listening Ports"
    echo "-------------------------"
    powershell.exe -Command "netstat -ano | Select-String ':9222' | Select-String 'LISTENING'" 2>/dev/null | head -5
else
    echo "❌ Chrome is not running"
    echo "   Start Chrome: ./start-chrome-windows.sh"
fi
echo

# Check port proxy configuration
echo "🔀 Port Proxy Configuration"
echo "---------------------------"
PROXY_CONFIG=$(powershell.exe -Command "netsh interface portproxy show v4tov4 | Select-String '9222'" | tr -d '\r')

if [ -n "$PROXY_CONFIG" ]; then
    echo "✅ Port proxy configured:"
    powershell.exe -Command "netsh interface portproxy show v4tov4 | Select-String '9222'" 2>/dev/null
else
    echo "❌ Port proxy not configured for port 9222"
    echo "   Run: ./setup-network.sh"
fi
echo

# Check firewall rules
echo "🛡️  Firewall Rules"
echo "------------------"
FIREWALL_RULES=$(powershell.exe -Command "Get-NetFirewallRule -DisplayName 'Chrome*Debug*' -ErrorAction SilentlyContinue | Measure-Object | Select-Object -ExpandProperty Count" | tr -d '\r')

if [ "$FIREWALL_RULES" -gt 0 ]; then
    echo "✅ Firewall rules configured ($FIREWALL_RULES rule(s))"
    powershell.exe -Command "Get-NetFirewallRule -DisplayName 'Chrome*Debug*' | Select-Object DisplayName,Enabled,Action | Format-Table -AutoSize" 2>/dev/null
else
    echo "❌ No firewall rules found for Chrome debugging"
    echo "   Run: ./setup-network.sh"
fi
echo

# Check connectivity from WSL2
echo "🔗 WSL2 Connectivity Test"
echo "-------------------------"

if [ -z "$WSL_IP" ]; then
    echo "❌ Cannot test connectivity without WSL adapter IP"
else
    echo "Testing connection to http://$WSL_IP:9222/json/version..."

    RESPONSE=$(curl -s -m 5 http://$WSL_IP:9222/json/version 2>&1)
    CURL_EXIT=$?

    if [ $CURL_EXIT -eq 0 ]; then
        echo "✅ Connection successful!"
        echo
        echo "Chrome Version Info:"
        echo "$RESPONSE" | python3 -m json.tool 2>/dev/null || echo "$RESPONSE"
    else
        echo "❌ Connection failed (exit code: $CURL_EXIT)"
        echo
        echo "Error details:"
        echo "$RESPONSE"
        echo
        echo "Troubleshooting steps:"
        echo "1. Verify Chrome is running: powershell.exe -Command 'Get-Process chrome'"
        echo "2. Check port proxy: powershell.exe -Command 'netsh interface portproxy show v4tov4'"
        echo "3. Verify firewall rules: ./check-connection.sh"
        echo "4. Restart Chrome: ./start-chrome-windows.sh"
        echo "5. Re-run network setup: ./setup-network.sh"
    fi
fi
echo

# Check Claude Code MCP configuration
echo "⚙️  Claude Code MCP Configuration"
echo "---------------------------------"
CLAUDE_CONFIG="$HOME/.claude.json"

if [ -f "$CLAUDE_CONFIG" ]; then
    if grep -q '"chrome-devtools"' "$CLAUDE_CONFIG"; then
        echo "✅ chrome-devtools MCP server configured"

        # Extract CHROME_HOST value
        CHROME_HOST=$(grep -A 10 '"chrome-devtools"' "$CLAUDE_CONFIG" | grep '"CHROME_HOST"' | sed 's/.*"CHROME_HOST": "\([^"]*\)".*/\1/')

        if [ -n "$CHROME_HOST" ]; then
            echo "   CHROME_HOST: $CHROME_HOST"

            if [ "$CHROME_HOST" = "$WSL_IP" ]; then
                echo "   ✅ CHROME_HOST matches WSL adapter IP"
            else
                echo "   ⚠️  CHROME_HOST ($CHROME_HOST) differs from WSL adapter IP ($WSL_IP)"
                echo "   Consider updating: Run ./setup-network.sh"
            fi
        fi
    else
        echo "❌ chrome-devtools MCP not found in configuration"
    fi
else
    echo "❌ Claude Code configuration not found at $CLAUDE_CONFIG"
fi
echo

# Summary
echo "📊 Diagnostic Summary"
echo "--------------------"
echo "Chrome Running: $([ "$CHROME_RUNNING" -gt 0 ] && echo 'YES' || echo 'NO')"
echo "Port Proxy: $([ -n "$PROXY_CONFIG" ] && echo 'CONFIGURED' || echo 'NOT CONFIGURED')"
echo "Firewall: $([ "$FIREWALL_RULES" -gt 0 ] && echo 'CONFIGURED' || echo 'NOT CONFIGURED')"
echo "WSL2 Connection: $([ $CURL_EXIT -eq 0 ] && echo 'WORKING' || echo 'FAILED')"
echo

if [ "$CHROME_RUNNING" -gt 0 ] && [ -n "$PROXY_CONFIG" ] && [ "$FIREWALL_RULES" -gt 0 ] && [ $CURL_EXIT -eq 0 ]; then
    echo "✅ All systems operational!"
    echo "   You can now use chrome-devtools MCP in Claude Code"
    echo "   Restart Claude Code if it's already running"
else
    echo "⚠️  Some issues detected. Follow the troubleshooting steps above."
fi

Troubleshooting

Check if Chrome is Running

powershell.exe -Command "Get-Process chrome -ErrorAction SilentlyContinue | Select-Object Id,ProcessName"

Check Chrome Listening Ports

powershell.exe -Command "netstat -ano | Select-String ':9222' | Select-String 'LISTENING'"

Expected output:

TCP    127.0.0.1:9222         0.0.0.0:0              LISTENING       <PID>
TCP    172.30.64.1:9222       0.0.0.0:0              LISTENING       <PID>

Check WSL Adapter IP Address

If connection fails, verify the WSL adapter IP hasn't changed:

powershell.exe -Command "Get-NetIPAddress -InterfaceAlias 'vEthernet (WSL)' -AddressFamily IPv4 | Select-Object IPAddress"

If IP changed from 172.30.64.1, update:

  1. Port proxy configuration (run ./setup-network.sh)
  2. MCP configuration in ~/.claude.json (CHROME_HOST value)

Stop Chrome

powershell.exe -Command "Stop-Process -Name chrome -Force"

Network Architecture Details

Why Port Proxy is Needed

Chrome binds the debugging port to 127.0.0.1 (localhost only) for security. WSL2 runs in a separate network namespace and cannot access Windows localhost directly. The port proxy forwards connections from the WSL network interface (172.30.64.1) to Windows localhost (127.0.0.1).

IP Address Explanation

  • 127.0.0.1 - Windows localhost (Chrome listens here)
  • 172.30.64.1 - Windows WSL adapter IP (WSL2 connects here)
  • 10.255.255.254 - DNS server in WSL2 (not used for Chrome connection)

Security Notes

  • Chrome debugging port is only accessible from the local machine
  • Firewall rules restrict access to WSL2 subnet only
  • Use a separate Chrome profile (--user-data-dir) to avoid conflicts
  • Never expose debugging port to external networks

Resources

Changelog

2025-10-31

  • Initial setup completed
  • WSL adapter IP: 172.30.64.1
  • Port proxy configured: 172.30.64.1:9222 → 127.0.0.1:9222
  • Firewall rules created
  • MCP configuration updated
  • Connection verified working