Agent skill
mcp-chrome-devtools
Chrome DevTools orchestrator providing intelligent routing between CLI (bdg) and MCP (Code Mode) approaches. CLI prioritized for speed and token efficiency; MCP fallback for multi-tool integration scenarios.
Install this agent skill to your Project
npx add-skill https://github.com/MichelKerkmeester/opencode--spec-kit-skilled-agent-orchestration/tree/main/.opencode/skill/mcp-chrome-devtools
SKILL.md
Chrome DevTools Orchestrator - CLI + MCP Integration
Browser debugging and automation through two complementary approaches: CLI (bdg) for speed and token efficiency, MCP for multi-tool integration.
1. WHEN TO USE
Activation Triggers
Use when:
- User mentions "browser debugging", "Chrome DevTools", "CDP" explicitly
- User asks to inspect, test, or automate browser tasks with lightweight CLI approach
- User wants screenshots, HAR files, console logs, or network inspection via terminal
- User mentions "bdg" or "browser-debugger-cli" explicitly
- User needs quick DOM queries, cookie manipulation, or JavaScript execution in browser
- User wants terminal-based browser automation with Unix pipe composability
- User needs production-ready automation scripts for CI/CD browser testing
Automatic Triggers:
- "bdg", "browser-debugger-cli" mentioned explicitly
- "lightweight browser debugging" or "quick CDP access"
- "terminal-based browser automation"
- "screenshot without Puppeteer"
When NOT to Use
Do not use for:
- Complex UI testing suites requiring sophisticated frameworks (use Puppeteer/Playwright)
- Heavy multi-step automation workflows better suited for frameworks
- Cross-browser testing (bdg supports Chrome/Chromium/Edge only)
- Visual regression testing or complex test frameworks
- When user explicitly requests Puppeteer, Playwright, or Selenium
2. SMART ROUTING
Resource Loading Levels
| Level | When to Load | Resources |
|---|---|---|
| ALWAYS | Every skill invocation | Core CDP pattern reference |
| CONDITIONAL | If intent signals match | CLI/MCP/session/troubleshooting |
| ON_DEMAND | Only on explicit request | Full diagnostics set |
Smart Router Pseudocode
The authoritative routing logic for scoped loading, weighted intent scoring, and ambiguity handling.
from pathlib import Path
SKILL_ROOT = Path(__file__).resolve().parent
RESOURCE_BASES = (SKILL_ROOT / "references", SKILL_ROOT / "assets")
DEFAULT_RESOURCE = "references/cdp_patterns.md"
INTENT_SIGNALS = {
"CLI": {"weight": 4, "keywords": ["bdg", "browser-debugger-cli", "terminal", "cli"]},
"MCP": {"weight": 4, "keywords": ["mcp", "code mode", "multi-tool", "parallel sessions"]},
"INSTALL": {"weight": 4, "keywords": ["install", "setup", "not installed", "command -v bdg"]},
"TROUBLESHOOT": {"weight": 4, "keywords": ["error", "failed", "troubleshoot", "session issue"]},
"AUTOMATION": {"weight": 3, "keywords": ["ci", "pipeline", "automation", "production"]},
}
RESOURCE_MAP = {
"CLI": ["references/cdp_patterns.md", "references/session_management.md"],
"MCP": ["references/session_management.md", "references/cdp_patterns.md"],
"INSTALL": ["references/troubleshooting.md"],
"TROUBLESHOOT": ["references/troubleshooting.md"],
"AUTOMATION": ["examples/README.md"],
}
LOADING_LEVELS = {
"ALWAYS": [DEFAULT_RESOURCE],
"ON_DEMAND_KEYWORDS": ["full troubleshooting", "full session guide", "all patterns"],
"ON_DEMAND": ["references/troubleshooting.md", "references/session_management.md"],
}
def _task_text(task) -> str:
parts = [
str(getattr(task, "text", "")),
str(getattr(task, "query", "")),
" ".join(getattr(task, "keywords", []) or []),
]
return " ".join(parts).lower()
def _guard_in_skill(relative_path: str) -> str:
resolved = (SKILL_ROOT / relative_path).resolve()
resolved.relative_to(SKILL_ROOT)
if resolved.suffix.lower() != ".md":
raise ValueError(f"Only markdown resources are routable: {relative_path}")
return resolved.relative_to(SKILL_ROOT).as_posix()
def discover_markdown_resources() -> set[str]:
docs = []
for base in RESOURCE_BASES:
if base.exists():
docs.extend(p for p in base.rglob("*.md") if p.is_file())
docs.extend(p for p in (SKILL_ROOT / "examples").rglob("*.md") if (SKILL_ROOT / "examples").exists())
return {doc.relative_to(SKILL_ROOT).as_posix() for doc in docs}
def score_intents(task) -> dict[str, float]:
"""Weighted intent scoring from request text and capability signals."""
text = _task_text(task)
scores = {intent: 0.0 for intent in INTENT_SIGNALS}
for intent, cfg in INTENT_SIGNALS.items():
for keyword in cfg["keywords"]:
if keyword in text:
scores[intent] += cfg["weight"]
if getattr(task, "cli_available", False):
scores["CLI"] += 5
if getattr(task, "code_mode_configured", False):
scores["MCP"] += 4
if getattr(task, "has_error", False):
scores["TROUBLESHOOT"] += 4
return scores
def select_intents(scores: dict[str, float], ambiguity_delta: float = 1.0, max_intents: int = 2) -> list[str]:
ranked = sorted(scores.items(), key=lambda item: item[1], reverse=True)
if not ranked or ranked[0][1] <= 0:
return ["CLI"]
selected = [ranked[0][0]]
if len(ranked) > 1 and ranked[1][1] > 0 and (ranked[0][1] - ranked[1][1]) <= ambiguity_delta:
selected.append(ranked[1][0])
return selected[:max_intents]
def route_chrome_devtools_resources(task):
inventory = discover_markdown_resources()
intents = select_intents(score_intents(task), ambiguity_delta=1.0)
loaded = []
seen = set()
def load_if_available(relative_path: str) -> None:
guarded = _guard_in_skill(relative_path)
if guarded in inventory and guarded not in seen:
load(guarded)
loaded.append(guarded)
seen.add(guarded)
for relative_path in LOADING_LEVELS["ALWAYS"]:
load_if_available(relative_path)
for intent in intents:
for relative_path in RESOURCE_MAP.get(intent, []):
load_if_available(relative_path)
text = _task_text(task)
if any(keyword in text for keyword in LOADING_LEVELS["ON_DEMAND_KEYWORDS"]):
for relative_path in LOADING_LEVELS["ON_DEMAND"]:
load_if_available(relative_path)
if not loaded:
load_if_available(DEFAULT_RESOURCE)
return {"intents": intents, "resources": loaded}
3. HOW IT WORKS
Tool Comparison
| Feature | CLI (bdg) | MCP (Code Mode) | Puppeteer/Playwright |
|---|---|---|---|
| Setup | npm install -g browser-debugger-cli@alpha |
MCP config + server | Heavy dependencies |
| Discovery | --list, --describe, --search |
search_tools() |
API docs required |
| Token Cost | Lowest (self-doc) | Medium (progressive) | Highest (verbose) |
| CDP Access | 300+ methods across 53 domains | MCP-exposed subset | Full but complex |
| Best For | Debugging, inspection | Multi-tool workflows | Complex UI testing |
CLI Approach (Priority) - browser-debugger-cli (bdg)
Installation & Verification
# Check if installed
command -v bdg || echo "Install: npm install -g browser-debugger-cli@alpha"
# Installation
npm install -g browser-debugger-cli@alpha
# Verify
bdg --version 2>&1
MCP Approach (Fallback) - Chrome DevTools via Code Mode
When CLI unavailable or multi-tool integration needed.
Prerequisites
- Code Mode configured in
.utcp_config.json - Chrome DevTools MCP server registered with
--isolated=true
Isolated Instances
Key Feature: MCP uses --isolated=true flag for independent browser instances.
Benefits of isolated instances:
- Each instance runs in its own browser process
- Multiple parallel browser sessions possible
- No session conflicts between instances
- Register multiple instances for parallel testing (e.g.,
chrome_devtools_1,chrome_devtools_2)
Configuration example (.utcp_config.json):
{
"manual_call_templates": [
{
"name": "chrome_devtools_1",
"call_template_type": "mcp",
"config": {
"mcpServers": {
"chrome_devtools_1": {
"transport": "stdio",
"command": "npx",
"args": ["chrome-devtools-mcp@latest", "--isolated=true"],
"env": {}
}
}
}
},
{
"name": "chrome_devtools_2",
"call_template_type": "mcp",
"config": {
"mcpServers": {
"chrome_devtools_2": {
"transport": "stdio",
"command": "npx",
"args": ["chrome-devtools-mcp@latest", "--isolated=true"],
"env": {}
}
}
}
}
]
}
Configuration Check
cat .utcp_config.json | jq '.manual_call_templates[] | select(.name | startswith("chrome_devtools"))'
Invocation Pattern
Tool naming: {manual_name}.{manual_name}_{tool_name}
Single instance example:
await call_tool_chain({
code: `
await chrome_devtools_1.chrome_devtools_1_navigate_page({
url: "https://example.com"
});
const screenshot = await chrome_devtools_1.chrome_devtools_1_take_screenshot({});
return screenshot;
`,
timeout: 30000
});
Parallel instances example (comparing two pages):
await call_tool_chain({
code: `
// Instance 1: Production site
await chrome_devtools_1.chrome_devtools_1_navigate_page({
url: "https://example.com"
});
// Instance 2: Staging site (parallel)
await chrome_devtools_2.chrome_devtools_2_navigate_page({
url: "https://staging.example.com"
});
// Capture both screenshots
const prod = await chrome_devtools_1.chrome_devtools_1_take_screenshot({});
const staging = await chrome_devtools_2.chrome_devtools_2_take_screenshot({});
return { production: prod, staging: staging };
`,
timeout: 60000
});
Available MCP Tools
| Tool | Purpose | CLI Equivalent |
|---|---|---|
navigate_page |
Navigate to URL | bdg <url> |
take_screenshot |
Capture screenshot | bdg dom screenshot |
list_console_messages |
Get console logs | bdg console --list |
resize_page |
Set viewport size | N/A (use cdp) |
click |
Click on element | bdg cdp Input.dispatchMouseEvent |
fill |
Fill form field | bdg dom eval "document.querySelector(...).value = ..." |
hover |
Hover over element | bdg cdp Input.dispatchMouseEvent |
press_key |
Press keyboard key | bdg cdp Input.dispatchKeyEvent |
wait_for |
Wait for condition | N/A (scripting) |
new_page |
Open new page | N/A |
close_page |
Close page | bdg stop |
select_page |
Switch to page | N/A |
Note: Tool names use underscores (e.g., take_screenshot) not camelCase.
Full invocation pattern: {manual_name}.{manual_name}_{tool_name}()
- Example:
chrome_devtools_1.chrome_devtools_1_take_screenshot({})
When to Prefer MCP
- Already using Code Mode for other tools (Webflow, Figma, etc.)
- Need to chain browser operations with other MCP tools
- Parallel browser testing - compare multiple sites/viewports simultaneously
- Complex multi-step automation in TypeScript
- Type-safe tool invocation required
MCP Limitations
- Higher token cost than CLI
- Requires Code Mode infrastructure
- Subset of CDP methods (CLI has 300+ methods across 53 domains)
- Less self-documenting than CLI's
--list,--describe
MCP Session Cleanup
Important: Always close browser instances when done to prevent resource leaks.
// Cleanup pattern for MCP sessions
await call_tool_chain({
code: `
try {
// Your browser operations
await chrome_devtools_1.chrome_devtools_1_navigate_page({
url: "https://example.com"
});
const screenshot = await chrome_devtools_1.chrome_devtools_1_take_screenshot({});
return screenshot;
} finally {
// Always close the page when done
await chrome_devtools_1.chrome_devtools_1_close_page({});
}
`,
timeout: 30000
});
// For multi-instance cleanup
await call_tool_chain({
code: `
try {
// Operations on multiple instances...
} finally {
// Close all instances
await chrome_devtools_1.chrome_devtools_1_close_page({});
await chrome_devtools_2.chrome_devtools_2_close_page({});
}
`,
timeout: 30000
});
Best Practice: Wrap browser operations in try/finally to ensure cleanup even on errors.
4. RULES
✅ ALWAYS Rules
ALWAYS do these without asking:
-
ALWAYS check CLI availability first
- Run
command -v bdgbefore any operation - Prefer CLI over MCP when available
- Run
-
ALWAYS verify bdg installation before first use
command -v bdg || echo "Install: npm install -g browser-debugger-cli@alpha"
-
ALWAYS use discovery commands when exploring
- Start with
--list,--describe,--search - Document how you found the method
- Start with
-
ALWAYS verify session status before CDP commands
bdg status 2>&1 | jq '.state'
-
ALWAYS capture stderr with
2>&1- Essential for error handling
- All bdg commands should include this
-
ALWAYS stop sessions after operations
bdg stop 2>&1or use trap pattern
-
ALWAYS use jq for JSON processing
- Avoid string manipulation on JSON output
❌ NEVER Rules
NEVER do these:
-
NEVER execute CDP commands without verifying session
- Session must be
activestate first
- Session must be
-
NEVER hardcode CDP method lists
- Use self-discovery instead
- Methods change between versions
-
NEVER skip error handling
- Always use
2>&1pattern - Check exit codes in scripts
- Always use
-
NEVER leave sessions running
- Cleanup with
bdg stopor trap - Browser processes consume resources
- Cleanup with
-
NEVER assume method names
- Verify with
--describefirst - Method signatures vary
- Verify with
-
NEVER use on Windows without WSL
- PowerShell/Git Bash not supported
⚠️ ESCALATE IF
Ask user when:
-
ESCALATE IF bdg not installed on Windows
- WSL required for Windows support
- Ask if they have WSL configured
-
ESCALATE IF Chrome/Chromium not found
- May need
CHROME_PATHenvironment variable - Ask user to specify browser location
- May need
-
ESCALATE IF session fails after 3 retries
- May indicate deeper issue
- Ask about browser permissions/sandbox
-
ESCALATE IF task requires cross-browser testing
- bdg is Chrome-only
- Suggest Puppeteer/Playwright for cross-browser
-
ESCALATE IF complex UI testing needed
- May be better suited for Puppeteer/Playwright
- Ask about test framework preferences
5. SUCCESS CRITERIA
Browser Debugging Completion Checklist
Workflow complete when:
- ✅ CLI vs MCP approach selected based on availability
- ✅ bdg installation verified (or MCP configured)
- ✅ Session started successfully (
activestate) - ✅ CDP operations executed (exit code 0, valid JSON)
- ✅ Required data captured (screenshot, logs, cookies, etc.)
- ✅ Session stopped and cleaned up
- ✅ Output provided to user
- ✅ Error handling implemented (stderr captured)
- ✅ Method discovery documented
Quality Targets
- Session startup: < 5 seconds
- Screenshot capture: < 2 seconds
- Console log retrieval: < 1 second
- Error rate: 0% (all errors handled gracefully)
6. INTEGRATION POINTS
Framework Integration
This skill operates within the behavioral framework defined in AGENTS.md.
Key integrations:
- Gate 2: Skill routing via
skill_advisor.py - Tool Routing: Per AGENTS.md Section 6 decision tree
- Memory: Context preserved via Spec Kit Memory MCP
Related Skills
mcp-code-mode: Required for MCP fallback approach
- When CLI unavailable, Code Mode provides alternative
- Tool naming:
{manual_name}.{manual_name}_{tool_name}
sk-code--web: Phase 3 browser testing integration
- Use bdg for verification during implementation
- Example integration pattern:
bash
npm run dev & sleep 5 bdg http://localhost:3000 2>&1 bdg dom screenshot verification.png 2>&1 bdg console --list 2>&1 > console.json bdg stop 2>&1
Tool Usage Guidelines
Bash: All bdg commands, session management, error handling Read: Load reference files when detailed guidance needed Grep: Filter command output, search logs Glob: Find screenshot files, locate HAR exports
External Tools
browser-debugger-cli (bdg):
- Installation:
npm install -g browser-debugger-cli@alpha - Purpose: Primary CLI for browser debugging
- Fallback: Use MCP via Code Mode if unavailable
Chrome/Chromium:
- Installation: System package manager or direct download
- Purpose: Browser runtime for CDP connection
- Fallback: Set
CHROME_PATHif not auto-detected
7. QUICK REFERENCE
Essential CLI Commands
# Discovery
bdg cdp --list # List domains
bdg cdp --describe Page # Domain methods
bdg cdp --search screenshot # Find methods
# Session
bdg <url> # Start
bdg status # Check
bdg stop # Stop
# Helpers
bdg dom screenshot <path> # Screenshot
bdg console --list # Console
bdg network getCookies # Cookies
bdg dom query "<sel>" # DOM query
bdg dom eval "<expr>" # Execute JS
bdg network har <path> # HAR export
MCP Tools (Isolated Instances)
// Tool naming: {instance}.{instance}_{tool_name}
// Each instance runs isolated browser (--isolated=true)
// Instance 1
chrome_devtools_1.chrome_devtools_1_navigate_page({ url: "..." })
chrome_devtools_1.chrome_devtools_1_take_screenshot({})
chrome_devtools_1.chrome_devtools_1_list_console_messages({})
// Instance 2 (parallel testing)
chrome_devtools_2.chrome_devtools_2_navigate_page({ url: "..." })
chrome_devtools_2.chrome_devtools_2_take_screenshot({})
Error Handling Pattern
#!/bin/bash
trap "bdg stop 2>&1" EXIT INT TERM
command -v bdg || { echo "Install bdg first"; exit 1; }
bdg "$URL" 2>&1 || exit 1
# ... operations ...
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
cli-copilot
GitHub Copilot CLI orchestrator enabling external AI assistants to invoke the standalone 'copilot' binary for supplementary tasks including collaborative planning, cloud delegation, versatile code generation, and autonomous task execution.
system-spec-kit
Unified documentation and context preservation: spec folder workflow (levels 1-3+), CORE + ADDENDUM template architecture (v2.2), validation, and Spec Kit Memory for context preservation. Mandatory for all file modifications.
sk-code--full-stack
Stack-agnostic development orchestrator guiding developers through implementation, testing, and verification phases with automatic stack detection via marker files and bundled stack-specific knowledge.
cli-gemini
Gemini CLI orchestrator enabling any AI assistant to invoke Google's Gemini CLI for supplementary AI tasks including code generation, web research via Google Search, codebase architecture analysis, cross-AI validation, and parallel task processing.
sk-prompt-improver
Prompt engineering specialist that transforms vague requests into structured, scored AI prompts using 7 proven frameworks (RCAF, COSTAR, RACE, CIDI, TIDD-EC, CRISPE, CRAFT), DEPTH thinking methodology, and CLEAR scoring across text modes.
mcp-figma
Figma design file access via MCP providing 18 tools for file retrieval, image export, component/style extraction, team management, and collaborative commenting. Accessed via Code Mode for token-efficient workflows.
Didn't find tool you were looking for?