Initial commit

This commit is contained in:
Zhongwei Li
2025-11-30 09:03:44 +08:00
commit 51eac46940
41 changed files with 5371 additions and 0 deletions

View File

@@ -0,0 +1,12 @@
{
"serverName": "chrome-devtools",
"serverVersion": "0.10.2",
"serverVersionInfo": {
"name": "chrome_devtools",
"title": "Chrome DevTools MCP server",
"version": "0.10.2"
},
"generatedAt": "2025-11-23T22:51:09.827Z",
"mcp2scriptsVersion": "0.3.1",
"mcp2restUrl": "http://localhost:28888"
}

View File

@@ -0,0 +1,159 @@
---
name: mcp-chrome-devtools
description: Automate Chrome browser via DevTools Protocol. Navigate pages, interact with elements, inspect network/console, analyze performance, and capture screenshots for web testing and automation tasks.
server-version: 0.10.2
---
# Chrome DevTools Skill
Control Chrome browser programmatically using the Chrome DevTools Protocol. This skill provides 26 tools for browser automation, web scraping, testing, and performance analysis.
## Prerequisites
- Node.js 18+ installed
- mcp2rest running on http://localhost:28888
- chrome-devtools server loaded in mcp2rest
- Package: `chrome-devtools-mcp@latest`
- Dependencies installed (already done during generation)
## Quick Start
Launch a browser, navigate to a page, and interact with elements:
```bash
# 1. Open a new page
node scripts/new_page.js --url https://example.com
# 2. Take a text snapshot to identify elements
node scripts/take_snapshot.js
# 3. Click a button (use UID from snapshot output)
node scripts/click.js --uid button_submit_abc123
```
**Expected Output:**
- Page opens in Chrome browser
- Snapshot shows page structure with element UIDs
- Button is clicked and any action triggers
## Tool Groups
This skill provides 26 tools organized into 4 groups:
### 1. Page Management
Browser window and tab operations: creating pages, navigation, switching contexts.
**Tools:** new_page, list_pages, close_page, navigate_page, select_page, resize_page
See: @workflows/page-management.md for detailed workflows
### 2. Element Interaction
User input simulation: clicking, typing, form filling, drag & drop.
**Tools:** click, fill, fill_form, hover, drag, upload_file, press_key
See: @workflows/element-interaction.md for detailed workflows
### 3. Inspection & Debugging
Monitoring and debugging: snapshots, screenshots, console logs, network requests.
**Tools:** take_snapshot, take_screenshot, list_console_messages, get_console_message, list_network_requests, get_network_request
See: @workflows/inspection-debugging.md for detailed workflows
### 4. Performance Analysis
Scripting and performance tools: JavaScript execution, performance tracing, device emulation.
**Tools:** evaluate_script, wait_for, handle_dialog, emulate, performance_start_trace, performance_stop_trace, performance_analyze_insight
See: @workflows/performance-analysis.md for detailed workflows
## Common Workflows
### Workflow: Automated Form Submission
Complete end-to-end form filling and submission:
- [ ] **Open page:** `node scripts/new_page.js --url https://example.com/login`
- [ ] **Get structure:** `node scripts/take_snapshot.js` (identify UIDs)
- [ ] **Fill email:** `node scripts/fill.js --uid email_input_xyz --value test@example.com`
- [ ] **Fill password:** `node scripts/fill.js --uid pass_input_abc --value mypassword`
- [ ] **Submit form:** `node scripts/click.js --uid submit_btn_def`
- [ ] **Verify:** `node scripts/wait_for.js --text "Welcome" --timeout 5000`
- [ ] **Capture result:** `node scripts/take_screenshot.js --format png --filePath result.png`
**Input Example:**
```
Email field UID: input_email_1a2b3c
Password field UID: input_password_4d5e6f
Submit button UID: button_submit_7g8h9i
```
**Expected Output:**
Form submitted successfully, redirected to dashboard, screenshot saved.
### Workflow: Web Scraping with Network Monitoring
Capture page data and network activity:
- [ ] **Start monitoring:** `node scripts/new_page.js --url https://example.com/data`
- [ ] **Wait for load:** `node scripts/wait_for.js --text "Data loaded" --timeout 10000`
- [ ] **Get page snapshot:** `node scripts/take_snapshot.js --verbose true --filePath snapshot.txt`
- [ ] **List network calls:** `node scripts/list_network_requests.js --resourceTypes fetch,xhr`
- [ ] **Get specific request:** `node scripts/get_network_request.js --reqid request_123`
- [ ] **Extract via script:** `node scripts/evaluate_script.js --function "() => document.querySelector('.data').textContent"`
**Expected Output:**
Page data extracted, network requests logged, specific API responses captured.
### Workflow: Performance Testing
Analyze page performance and Core Web Vitals:
- [ ] **Open page:** `node scripts/new_page.js --url https://example.com`
- [ ] **Start tracing:** `node scripts/performance_start_trace.js --reload true --autoStop false`
- [ ] **Wait for page:** `node scripts/wait_for.js --text "Content loaded" --timeout 15000`
- [ ] **Stop tracing:** `node scripts/performance_stop_trace.js`
- [ ] **Review insights:** Check trace output for performance metrics and CWV scores
- [ ] **Analyze specific insight:** `node scripts/performance_analyze_insight.js --insightSetId set_123 --insightName LargestContentfulPaint`
**Expected Output:**
Performance trace with metrics, CWV scores (LCP, FID, CLS), actionable insights.
### Workflow: Multi-Page Session Management
Work with multiple browser tabs:
- [ ] **List current pages:** `node scripts/list_pages.js`
- [ ] **Open new tab:** `node scripts/new_page.js --url https://example.com/page1`
- [ ] **Open another tab:** `node scripts/new_page.js --url https://example.com/page2`
- [ ] **List all pages:** `node scripts/list_pages.js` (note page indices)
- [ ] **Switch to page 0:** `node scripts/select_page.js --pageIdx 0`
- [ ] **Interact with page 0:** `node scripts/take_snapshot.js`
- [ ] **Switch to page 1:** `node scripts/select_page.js --pageIdx 1`
- [ ] **Close page 1:** `node scripts/close_page.js --pageIdx 1`
**Expected Output:**
Multiple tabs managed, context switching works, specific pages closed.
## State Persistence
This server maintains state between script calls:
- Browser instance stays open across multiple commands
- Page context persists until explicitly changed with `select_page.js`
- Console messages and network requests accumulate since last navigation
- State resets when mcp2rest server restarts
## Reference
- **Complete tool listing:** @reference/all-tools.md
- **Troubleshooting guide:** @reference/troubleshooting.md
- **Advanced examples:** @reference/advanced-examples.md
## Quick Tips
1. **Always take snapshots first:** Use `take_snapshot.js` to get element UIDs before interaction
2. **Use wait_for for dynamic content:** Don't assume instant loading
3. **Handle dialogs proactively:** Use `handle_dialog.js` if alerts/confirms appear
4. **Check console for errors:** Use `list_console_messages.js` to debug issues
5. **Monitor network for API calls:** Use `list_network_requests.js` to track backend communication

View File

@@ -0,0 +1,737 @@
# Advanced Examples
Complex workflows and advanced usage patterns for chrome-devtools.
## Table of Contents
- [E2E Testing Workflows](#e2e-testing-workflows)
- [Web Scraping Patterns](#web-scraping-patterns)
- [Performance Optimization](#performance-optimization)
- [CI/CD Integration](#cicd-integration)
- [Cross-Browser Testing Simulation](#cross-browser-testing-simulation)
- [Advanced JavaScript Extraction](#advanced-javascript-extraction)
---
## E2E Testing Workflows
### Complete User Registration Flow
Test full registration process with validation:
```bash
#!/bin/bash
# test_registration.sh
echo "Starting registration flow test..."
# 1. Open registration page
node scripts/new_page.js --url https://example.com/register
# 2. Wait for page load
node scripts/wait_for.js --text "Create Account" --timeout 10000
# 3. Get form structure
node scripts/take_snapshot.js --filePath registration_form.txt
# 4. Fill registration form (update UIDs from snapshot)
node scripts/fill_form.js --elements '[
{"uid":"input_firstname","value":"John"},
{"uid":"input_lastname","value":"Doe"},
{"uid":"input_email","value":"john.doe@example.com"},
{"uid":"input_password","value":"SecurePass123!"},
{"uid":"input_password_confirm","value":"SecurePass123!"},
{"uid":"select_country","value":"United States"}
]'
# 5. Screenshot before submission
node scripts/take_screenshot.js --filePath before_submit.png
# 6. Accept terms checkbox
node scripts/click.js --uid checkbox_terms
# 7. Submit form
node scripts/click.js --uid button_register
# 8. Wait for success message
if node scripts/wait_for.js --text "Registration successful" --timeout 15000; then
echo "✓ Registration succeeded"
# 9. Capture success state
node scripts/take_screenshot.js --filePath registration_success.png
node scripts/take_snapshot.js --filePath success_page.txt
# 10. Check for welcome email notification
node scripts/wait_for.js --text "Verification email sent" --timeout 5000
echo "✓ Test passed: Registration flow complete"
exit 0
else
echo "✗ Registration failed"
# Capture error state
node scripts/take_screenshot.js --filePath registration_error.png
node scripts/list_console_messages.js --types error > console_errors.txt
echo "✗ Test failed: See error screenshots and logs"
exit 1
fi
```
### Shopping Cart Checkout Flow
Test complete e-commerce checkout:
```bash
#!/bin/bash
# test_checkout.sh
echo "Testing checkout flow..."
# 1. Navigate to product page
node scripts/new_page.js --url https://example.com/products/widget-123
# 2. Wait and verify product loads
node scripts/wait_for.js --text "Add to Cart" --timeout 10000
node scripts/take_snapshot.js > product_page.txt
# 3. Add to cart
node scripts/click.js --uid button_add_to_cart
node scripts/wait_for.js --text "Added to cart" --timeout 5000
# 4. Go to cart
node scripts/click.js --uid link_view_cart
node scripts/wait_for.js --text "Shopping Cart" --timeout 5000
# 5. Verify cart contents
node scripts/take_snapshot.js --filePath cart_contents.txt
node scripts/evaluate_script.js --function "() => document.querySelector('.cart-total').textContent" > cart_total.txt
# 6. Proceed to checkout
node scripts/click.js --uid button_checkout
node scripts/wait_for.js --text "Shipping Information" --timeout 10000
# 7. Fill shipping info
node scripts/fill_form.js --elements '[
{"uid":"input_address","value":"123 Main Street"},
{"uid":"input_city","value":"San Francisco"},
{"uid":"input_state","value":"CA"},
{"uid":"input_zip","value":"94102"}
]'
# 8. Continue to payment
node scripts/click.js --uid button_continue
node scripts/wait_for.js --text "Payment Method" --timeout 10000
# 9. Select payment method
node scripts/click.js --uid radio_credit_card
# 10. Fill payment info (test mode)
node scripts/fill_form.js --elements '[
{"uid":"input_card_number","value":"4242424242424242"},
{"uid":"input_card_expiry","value":"12/25"},
{"uid":"input_card_cvc","value":"123"}
]'
# 11. Place order
node scripts/click.js --uid button_place_order
node scripts/wait_for.js --text "Order Confirmed" --timeout 20000
# 12. Capture confirmation
node scripts/take_screenshot.js --filePath order_confirmation.png
node scripts/evaluate_script.js --function "() => ({orderNumber: document.querySelector('.order-number').textContent, total: document.querySelector('.order-total').textContent})" > order_details.json
echo "✓ Checkout flow completed successfully"
```
---
## Web Scraping Patterns
### Multi-Page Data Extraction
Scrape data across paginated results:
```bash
#!/bin/bash
# scrape_listings.sh
BASE_URL="https://example.com/listings"
OUTPUT_FILE="all_listings.json"
MAX_PAGES=10
echo "[" > $OUTPUT_FILE
for page in $(seq 1 $MAX_PAGES); do
echo "Scraping page $page..."
# Navigate to page
if [ $page -eq 1 ]; then
node scripts/new_page.js --url "$BASE_URL"
else
node scripts/navigate_page.js --url "$BASE_URL?page=$page"
fi
# Wait for listings to load
node scripts/wait_for.js --text "listings found" --timeout 10000
# Extract listings data
LISTINGS=$(node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.listing')).map(item => ({
title: item.querySelector('.title').textContent.trim(),
price: item.querySelector('.price').textContent.trim(),
location: item.querySelector('.location').textContent.trim(),
url: item.querySelector('a').href
}))")
# Append to output (remove outer brackets)
echo "$LISTINGS" | jq '.[]' >> $OUTPUT_FILE
# Check if there's a next page
HAS_NEXT=$(node scripts/evaluate_script.js --function "() => document.querySelector('.pagination .next') !== null")
if [ "$HAS_NEXT" != "true" ]; then
echo "Reached last page at page $page"
break
fi
# Add comma separator
if [ $page -lt $MAX_PAGES ]; then
echo "," >> $OUTPUT_FILE
fi
# Be polite: wait between requests
sleep 2
done
echo "]" >> $OUTPUT_FILE
echo "✓ Scraped listings saved to $OUTPUT_FILE"
# Summary statistics
TOTAL=$(cat $OUTPUT_FILE | jq 'length')
echo "Total listings extracted: $TOTAL"
```
### Dynamic Content Scraping with Infinite Scroll
Extract data from infinite scroll pages:
```bash
#!/bin/bash
# scrape_infinite_scroll.sh
echo "Scraping infinite scroll content..."
# Open page
node scripts/new_page.js --url https://example.com/feed
# Wait for initial content
node scripts/wait_for.js --text "Post" --timeout 10000
# Initialize
PREVIOUS_COUNT=0
SCROLL_ATTEMPTS=0
MAX_SCROLLS=20
OUTPUT_FILE="feed_items.json"
while [ $SCROLL_ATTEMPTS -lt $MAX_SCROLLS ]; do
# Count current items
CURRENT_COUNT=$(node scripts/evaluate_script.js --function "() => document.querySelectorAll('.feed-item').length")
echo "Scroll $SCROLL_ATTEMPTS: Found $CURRENT_COUNT items"
# Check if we got new items
if [ "$CURRENT_COUNT" -eq "$PREVIOUS_COUNT" ]; then
echo "No new items loaded, reached end"
break
fi
PREVIOUS_COUNT=$CURRENT_COUNT
# Scroll to bottom
node scripts/evaluate_script.js --function "() => window.scrollTo(0, document.body.scrollHeight)"
# Wait for new content to load
sleep 2
SCROLL_ATTEMPTS=$((SCROLL_ATTEMPTS + 1))
done
# Extract all items
echo "Extracting all $CURRENT_COUNT items..."
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.feed-item')).map(item => ({
author: item.querySelector('.author').textContent.trim(),
content: item.querySelector('.content').textContent.trim(),
timestamp: item.querySelector('.timestamp').textContent.trim(),
likes: item.querySelector('.likes').textContent.trim()
}))" > $OUTPUT_FILE
echo "✓ Extracted $CURRENT_COUNT items to $OUTPUT_FILE"
```
---
## Performance Optimization
### Automated Performance Regression Testing
Compare performance across builds:
```bash
#!/bin/bash
# performance_regression_test.sh
BASELINE_URL="https://staging.example.com"
CURRENT_URL="https://production.example.com"
echo "Running performance regression tests..."
# Test baseline (staging)
echo "Testing baseline: $BASELINE_URL"
node scripts/new_page.js --url "$BASELINE_URL"
node scripts/performance_start_trace.js --reload true --autoStop false
node scripts/wait_for.js --text "Ready" --timeout 30000
node scripts/performance_stop_trace.js > baseline_trace.json
BASELINE_LCP=$(cat baseline_trace.json | jq -r '.metrics.LCP.value')
BASELINE_FID=$(cat baseline_trace.json | jq -r '.metrics.FID.value')
BASELINE_CLS=$(cat baseline_trace.json | jq -r '.metrics.CLS.value')
echo "Baseline: LCP=$BASELINE_LCP, FID=$BASELINE_FID, CLS=$BASELINE_CLS"
# Test current (production)
echo "Testing current: $CURRENT_URL"
node scripts/navigate_page.js --url "$CURRENT_URL"
node scripts/performance_start_trace.js --reload true --autoStop false
node scripts/wait_for.js --text "Ready" --timeout 30000
node scripts/performance_stop_trace.js > current_trace.json
CURRENT_LCP=$(cat current_trace.json | jq -r '.metrics.LCP.value')
CURRENT_FID=$(cat current_trace.json | jq -r '.metrics.FID.value')
CURRENT_CLS=$(cat current_trace.json | jq -r '.metrics.CLS.value')
echo "Current: LCP=$CURRENT_LCP, FID=$CURRENT_FID, CLS=$CURRENT_CLS"
# Compare (allow 10% regression threshold)
THRESHOLD=1.1
FAILED=false
LCP_RATIO=$(echo "scale=2; $CURRENT_LCP / $BASELINE_LCP" | bc)
if (( $(echo "$LCP_RATIO > $THRESHOLD" | bc -l) )); then
echo "✗ LCP regression detected: ${CURRENT_LCP}ms vs ${BASELINE_LCP}ms"
FAILED=true
else
echo "✓ LCP within threshold"
fi
FID_RATIO=$(echo "scale=2; $CURRENT_FID / $BASELINE_FID" | bc)
if (( $(echo "$FID_RATIO > $THRESHOLD" | bc -l) )); then
echo "✗ FID regression detected: ${CURRENT_FID}ms vs ${BASELINE_FID}ms"
FAILED=true
else
echo "✓ FID within threshold"
fi
CLS_RATIO=$(echo "scale=2; $CURRENT_CLS / $BASELINE_CLS" | bc)
if (( $(echo "$CLS_RATIO > $THRESHOLD" | bc -l) )); then
echo "✗ CLS regression detected: ${CURRENT_CLS} vs ${BASELINE_CLS}"
FAILED=true
else
echo "✓ CLS within threshold"
fi
if [ "$FAILED" = true ]; then
echo "Performance regression test FAILED"
exit 1
else
echo "Performance regression test PASSED"
exit 0
fi
```
### Network Performance Testing Matrix
Test performance across network conditions:
```bash
#!/bin/bash
# network_performance_matrix.sh
URL="https://example.com"
OUTPUT_DIR="performance_results"
mkdir -p $OUTPUT_DIR
# Define network profiles
declare -A NETWORKS
NETWORKS["fast"]='{"downloadThroughput":10000000,"uploadThroughput":10000000,"latency":10}'
NETWORKS["4g"]='{"downloadThroughput":1600000,"uploadThroughput":750000,"latency":150}'
NETWORKS["3g"]='{"downloadThroughput":180000,"uploadThroughput":84000,"latency":562}'
NETWORKS["slow-3g"]='{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'
echo "Testing performance across network conditions..."
# Open page once
node scripts/new_page.js --url "$URL"
for profile in "${!NETWORKS[@]}"; do
echo "Testing network profile: $profile"
# Apply network emulation
node scripts/emulate.js --networkConditions "${NETWORKS[$profile]}"
# Run performance trace
node scripts/performance_start_trace.js --reload true --autoStop false
node scripts/wait_for.js --text "Ready" --timeout 60000
node scripts/performance_stop_trace.js > "$OUTPUT_DIR/${profile}_trace.json"
# Extract key metrics
LCP=$(cat "$OUTPUT_DIR/${profile}_trace.json" | jq -r '.metrics.LCP.value')
FID=$(cat "$OUTPUT_DIR/${profile}_trace.json" | jq -r '.metrics.FID.value')
CLS=$(cat "$OUTPUT_DIR/${profile}_trace.json" | jq -r '.metrics.CLS.value')
echo "$profile: LCP=${LCP}ms, FID=${FID}ms, CLS=$CLS"
# Capture screenshot
node scripts/take_screenshot.js --filePath "$OUTPUT_DIR/${profile}_loaded.png"
done
# Reset to normal
node scripts/emulate.js --cpuThrottlingRate 1
echo "✓ Performance testing complete. Results in $OUTPUT_DIR/"
```
---
## CI/CD Integration
### GitHub Actions Workflow
```yaml
# .github/workflows/e2e-tests.yml
name: E2E Tests
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
e2e-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install mcp2skill-tools
run: |
npm install -g mcp2skill-tools
- name: Start mcp2rest
run: |
mcp2rest start
mcp2rest add chrome-devtools
- name: Install skill dependencies
run: |
cd ~/.claude/skills/mcp-chrome-devtools/scripts
npm install
- name: Run E2E tests
run: |
cd tests
bash test_registration.sh
bash test_checkout.sh
bash test_search.sh
- name: Upload test artifacts
if: always()
uses: actions/upload-artifact@v3
with:
name: test-results
path: |
**/*.png
**/*.txt
**/*.json
- name: Stop mcp2rest
if: always()
run: mcp2rest stop
```
### Jenkins Pipeline
```groovy
// Jenkinsfile
pipeline {
agent any
environment {
NODE_VERSION = '18'
}
stages {
stage('Setup') {
steps {
sh 'npm install -g mcp2skill-tools'
sh 'mcp2rest start'
sh 'mcp2rest add chrome-devtools'
}
}
stage('Install Dependencies') {
steps {
dir('~/.claude/skills/mcp-chrome-devtools/scripts') {
sh 'npm install'
}
}
}
stage('E2E Tests') {
parallel {
stage('Registration Flow') {
steps {
sh 'bash tests/test_registration.sh'
}
}
stage('Checkout Flow') {
steps {
sh 'bash tests/test_checkout.sh'
}
}
stage('Search Flow') {
steps {
sh 'bash tests/test_search.sh'
}
}
}
}
stage('Performance Tests') {
steps {
sh 'bash tests/performance_regression_test.sh'
}
}
}
post {
always {
archiveArtifacts artifacts: '**/*.png,**/*.txt,**/*.json', allowEmptyArchive: true
sh 'mcp2rest stop'
}
failure {
emailext (
subject: "E2E Tests Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}",
body: "Check console output at ${env.BUILD_URL}",
to: "team@example.com"
)
}
}
}
```
---
## Cross-Browser Testing Simulation
### Device Emulation Matrix
```bash
#!/bin/bash
# device_matrix_test.sh
URL="https://example.com"
OUTPUT_DIR="device_screenshots"
mkdir -p $OUTPUT_DIR
# Define device viewports
declare -A DEVICES
DEVICES["desktop_1080"]="1920 1080"
DEVICES["desktop_720"]="1280 720"
DEVICES["laptop"]="1366 768"
DEVICES["ipad_portrait"]="768 1024"
DEVICES["ipad_landscape"]="1024 768"
DEVICES["iphone_portrait"]="375 667"
DEVICES["iphone_landscape"]="667 375"
DEVICES["android_portrait"]="360 640"
DEVICES["android_landscape"]="640 360"
echo "Testing across device viewports..."
# Open page
node scripts/new_page.js --url "$URL"
for device in "${!DEVICES[@]}"; do
echo "Testing device: $device"
# Parse dimensions
read -r width height <<< "${DEVICES[$device]}"
# Resize window
node scripts/resize_page.js --width $width --height $height
# Wait for reflow
sleep 2
# Capture screenshot
node scripts/take_screenshot.js --fullPage true --filePath "$OUTPUT_DIR/${device}.png"
# Capture snapshot for debugging
node scripts/take_snapshot.js --filePath "$OUTPUT_DIR/${device}_snapshot.txt"
done
echo "✓ Device matrix testing complete. Screenshots in $OUTPUT_DIR/"
```
---
## Advanced JavaScript Extraction
### Extract Structured Data from SPA
```bash
#!/bin/bash
# extract_spa_data.sh
echo "Extracting data from Single Page Application..."
# Open SPA
node scripts/new_page.js --url https://example.com/dashboard
# Wait for app to initialize
node scripts/wait_for.js --text "Dashboard" --timeout 15000
# Wait for data to load (check for spinner to disappear)
node scripts/evaluate_script.js --function "() => new Promise(resolve => {
const checkSpinner = setInterval(() => {
if (!document.querySelector('.loading-spinner')) {
clearInterval(checkSpinner);
resolve(true);
}
}, 100);
})"
# Extract React/Vue component state
APP_STATE=$(node scripts/evaluate_script.js --function "() => {
// Try to access React DevTools state
const root = document.querySelector('#root');
const reactInternals = root._reactRootContainer || root._reactInternalFiber;
// Or access Vue instance
const vueInstance = root.__vue__;
// Extract data from global state (Redux, Vuex, etc.)
return {
redux: window.__REDUX_DEVTOOLS_EXTENSION__ ? window.store.getState() : null,
vuex: window.__VUEX_DEVTOOLS_GLOBAL_HOOK__ ? window.$store.state : null,
// Or extract directly from DOM
domData: Array.from(document.querySelectorAll('.data-item')).map(item => ({
id: item.dataset.id,
title: item.querySelector('.title').textContent,
value: item.querySelector('.value').textContent
}))
};
}")
echo "$APP_STATE" | jq '.' > app_state.json
echo "✓ Extracted application state to app_state.json"
```
### Monitor Real-Time Updates
```bash
#!/bin/bash
# monitor_realtime_updates.sh
echo "Monitoring real-time updates..."
# Open page with real-time data
node scripts/new_page.js --url https://example.com/live-feed
# Set up monitoring script
node scripts/evaluate_script.js --function "() => {
window.updates = [];
window.observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
if (mutation.type === 'childList') {
mutation.addedNodes.forEach(node => {
if (node.classList && node.classList.contains('update-item')) {
window.updates.push({
timestamp: new Date().toISOString(),
content: node.textContent,
type: node.dataset.type
});
}
});
}
});
});
const container = document.querySelector('.updates-container');
window.observer.observe(container, { childList: true, subtree: true });
return 'Monitoring started';
}"
# Wait for updates to accumulate
echo "Collecting updates for 60 seconds..."
sleep 60
# Retrieve collected updates
UPDATES=$(node scripts/evaluate_script.js --function "() => window.updates")
echo "$UPDATES" | jq '.' > realtime_updates.json
# Clean up
node scripts/evaluate_script.js --function "() => { window.observer.disconnect(); return 'Monitoring stopped'; }"
echo "✓ Collected updates saved to realtime_updates.json"
```
---
## Complex Workflow Orchestration
### Multi-User Simulation
```bash
#!/bin/bash
# simulate_multi_user.sh
echo "Simulating multi-user interactions..."
# User 1: Admin workflow
(
echo "User 1: Admin actions"
node scripts/new_page.js --url https://example.com/admin
node scripts/wait_for.js --text "Admin Panel" --timeout 10000
# ... admin actions ...
) &
# User 2: Customer workflow
(
echo "User 2: Customer actions"
node scripts/new_page.js --url https://example.com/shop
node scripts/wait_for.js --text "Products" --timeout 10000
# ... customer actions ...
) &
# Wait for both users to complete
wait
echo "✓ Multi-user simulation complete"
```
This advanced examples reference provides production-ready patterns for complex automation, testing, and data extraction workflows.

View File

@@ -0,0 +1,772 @@
# Complete Tool Reference
Alphabetical listing of all 26 chrome-devtools tools with full parameters and examples.
## Table of Contents
- [click](#click)
- [close_page](#close_page)
- [drag](#drag)
- [emulate](#emulate)
- [evaluate_script](#evaluate_script)
- [fill](#fill)
- [fill_form](#fill_form)
- [get_console_message](#get_console_message)
- [get_network_request](#get_network_request)
- [handle_dialog](#handle_dialog)
- [hover](#hover)
- [list_console_messages](#list_console_messages)
- [list_network_requests](#list_network_requests)
- [list_pages](#list_pages)
- [navigate_page](#navigate_page)
- [new_page](#new_page)
- [performance_analyze_insight](#performance_analyze_insight)
- [performance_start_trace](#performance_start_trace)
- [performance_stop_trace](#performance_stop_trace)
- [press_key](#press_key)
- [resize_page](#resize_page)
- [select_page](#select_page)
- [take_screenshot](#take_screenshot)
- [take_snapshot](#take_snapshot)
- [upload_file](#upload_file)
- [wait_for](#wait_for)
---
## click
Clicks on an element identified by its UID.
**Group:** Element Interaction
**Required Parameters:**
- `--uid UID` - Element unique identifier from snapshot
**Optional Parameters:**
- `--dblClick BOOLEAN` - Double click instead of single click (default: false)
**Examples:**
```bash
# Single click
node scripts/click.js --uid button_submit_abc123
# Double click
node scripts/click.js --uid file_icon_xyz789 --dblClick true
```
**Related Tools:** hover, fill, take_snapshot
---
## close_page
Closes a page by its index. Cannot close the last remaining page.
**Group:** Page Management
**Required Parameters:**
- `--pageIdx NUMBER` - Index of page to close (from list_pages)
**Examples:**
```bash
node scripts/close_page.js --pageIdx 2
```
**Notes:** Always keep at least one page open. Close pages from highest to lowest index to avoid index shifting.
**Related Tools:** list_pages, new_page, select_page
---
## drag
Drags one element onto another element.
**Group:** Element Interaction
**Required Parameters:**
- `--from-uid UID` - UID of element to drag
- `--to-uid UID` - UID of target drop zone
**Examples:**
```bash
node scripts/drag.js --from-uid task_item_abc --to-uid dropzone_xyz
```
**Related Tools:** hover, click, take_snapshot
---
## emulate
Emulates network conditions and CPU throttling.
**Group:** Performance Analysis
**Optional Parameters:**
- `--networkConditions JSON` - Network throttling config
- `--cpuThrottlingRate NUMBER` - CPU throttling multiplier (1 = normal)
**Network Conditions Format:**
```json
{
"downloadThroughput": 50000,
"uploadThroughput": 50000,
"latency": 2000
}
```
**Examples:**
```bash
# Slow 3G
node scripts/emulate.js --networkConditions '{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'
# 4x CPU slowdown
node scripts/emulate.js --cpuThrottlingRate 4
# Combined
node scripts/emulate.js --networkConditions '{"downloadThroughput":100000,"uploadThroughput":50000,"latency":100}' --cpuThrottlingRate 2
# Reset to normal
node scripts/emulate.js --cpuThrottlingRate 1
```
**Common Presets:**
- Slow 3G: 50KB/s down, 50KB/s up, 2000ms latency
- Fast 3G: 180KB/s down, 84KB/s up, 562ms latency
- 4G: 1.6MB/s down, 750KB/s up, 150ms latency
**Related Tools:** performance_start_trace, performance_stop_trace
---
## evaluate_script
Executes JavaScript in the page context and returns JSON-serializable results.
**Group:** Performance Analysis
**Required Parameters:**
- `--function STRING` - JavaScript function as string
**Optional Parameters:**
- `--args JSON_ARRAY` - Function arguments as JSON array
**Examples:**
```bash
# Simple extraction
node scripts/evaluate_script.js --function "() => document.title"
# With parameters
node scripts/evaluate_script.js --function "(x, y) => x + y" --args '[5, 3]'
# Extract array of data
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('h2')).map(h => h.textContent)"
# Complex object extraction
node scripts/evaluate_script.js --function "() => ({title: document.title, links: document.querySelectorAll('a').length})"
```
**Important:** Return values must be JSON-serializable (no DOM nodes, functions, or circular references).
**Related Tools:** take_snapshot, wait_for
---
## fill
Types text into inputs/textareas or selects dropdown options.
**Group:** Element Interaction
**Required Parameters:**
- `--uid UID` - Element unique identifier
- `--value STRING` - Text to type or option to select
**Examples:**
```bash
# Text input
node scripts/fill.js --uid input_username_abc --value "john.doe"
# Textarea
node scripts/fill.js --uid textarea_comment_def --value "This is a long comment"
# Dropdown select
node scripts/fill.js --uid select_country_ghi --value "United States"
```
**Related Tools:** fill_form, click, take_snapshot
---
## fill_form
Fills multiple form fields at once.
**Group:** Element Interaction
**Required Parameters:**
- `--elements JSON_ARRAY` - Array of {uid, value} objects
**Format:**
```json
[
{"uid": "input_email", "value": "test@example.com"},
{"uid": "input_password", "value": "secret123"}
]
```
**Examples:**
```bash
node scripts/fill_form.js --elements '[{"uid":"input_email","value":"test@example.com"},{"uid":"input_password","value":"secret123"}]'
# Multi-line for readability (bash)
node scripts/fill_form.js --elements '[
{"uid":"input_name","value":"John Doe"},
{"uid":"input_email","value":"john@example.com"},
{"uid":"select_country","value":"USA"}
]'
```
**Related Tools:** fill, click, take_snapshot
---
## get_console_message
Retrieves a specific console message by ID.
**Group:** Inspection & Debugging
**Required Parameters:**
- `--msgid STRING` - Message ID from list_console_messages
**Examples:**
```bash
node scripts/get_console_message.js --msgid msg_abc123
```
**Related Tools:** list_console_messages
---
## get_network_request
Gets details of a specific network request.
**Group:** Inspection & Debugging
**Optional Parameters:**
- `--reqid STRING` - Request ID from list_network_requests (if omitted, returns currently selected request in DevTools)
**Examples:**
```bash
# Specific request
node scripts/get_network_request.js --reqid req_abc123
# Currently selected in DevTools
node scripts/get_network_request.js
```
**Output includes:** URL, method, status code, headers, request/response body, timing.
**Related Tools:** list_network_requests
---
## handle_dialog
Handles browser dialogs (alert, confirm, prompt).
**Group:** Performance Analysis
**Required Parameters:**
- `--action STRING` - Either "accept" or "dismiss"
**Optional Parameters:**
- `--promptText STRING` - Text to enter in prompt dialog (only for prompts)
**Examples:**
```bash
# Accept alert
node scripts/handle_dialog.js --action accept
# Dismiss confirm
node scripts/handle_dialog.js --action dismiss
# Accept prompt with input
node scripts/handle_dialog.js --action accept --promptText "My Answer"
```
**Notes:** Dialog must already be open when calling this tool.
**Related Tools:** click, wait_for
---
## hover
Hovers the mouse over an element.
**Group:** Element Interaction
**Required Parameters:**
- `--uid UID` - Element unique identifier
**Examples:**
```bash
node scripts/hover.js --uid tooltip_trigger_abc
# Common pattern: hover then click
node scripts/hover.js --uid menu_trigger_xyz
node scripts/click.js --uid menu_item_settings
```
**Use Cases:** Triggering tooltips, dropdown menus, hover effects.
**Related Tools:** click, take_snapshot
---
## list_console_messages
Lists console messages (logs, warnings, errors) from the current page.
**Group:** Inspection & Debugging
**Optional Parameters:**
- `--pageSize NUMBER` - Number of messages per page
- `--pageIdx NUMBER` - Page index for pagination (0-based)
- `--types STRING` - Comma-separated types: log,warn,error,info
- `--includePreservedMessages BOOLEAN` - Include messages from before current navigation
**Examples:**
```bash
# All messages
node scripts/list_console_messages.js
# Only errors
node scripts/list_console_messages.js --types error
# Errors and warnings
node scripts/list_console_messages.js --types error,warn
# Paginated
node scripts/list_console_messages.js --pageSize 10 --pageIdx 0
```
**Related Tools:** get_console_message
---
## list_network_requests
Lists network requests made by the current page.
**Group:** Inspection & Debugging
**Optional Parameters:**
- `--pageSize NUMBER` - Number of requests per page
- `--pageIdx NUMBER` - Page index for pagination (0-based)
- `--resourceTypes STRING` - Comma-separated types: fetch,xhr,document,script,stylesheet,image
- `--includePreservedRequests BOOLEAN` - Include requests from before current navigation
**Examples:**
```bash
# All requests
node scripts/list_network_requests.js
# Only API calls
node scripts/list_network_requests.js --resourceTypes fetch,xhr
# Only scripts and stylesheets
node scripts/list_network_requests.js --resourceTypes script,stylesheet
# Paginated
node scripts/list_network_requests.js --pageSize 20 --pageIdx 0
```
**Related Tools:** get_network_request
---
## list_pages
Lists all open browser pages with their indices and URLs.
**Group:** Page Management
**No Parameters**
**Examples:**
```bash
node scripts/list_pages.js
```
**Output Example:**
```
Page 0: https://example.com (selected)
Page 1: https://google.com
Page 2: https://github.com
```
**Related Tools:** new_page, select_page, close_page
---
## navigate_page
Navigates the currently selected page.
**Group:** Page Management
**Optional Parameters:**
- `--url STRING` - URL to navigate to
- `--type STRING` - Navigation type: navigate, reload, back, forward
- `--ignoreCache BOOLEAN` - Bypass cache on reload
- `--timeout NUMBER` - Navigation timeout in milliseconds
**Examples:**
```bash
# Navigate to URL
node scripts/navigate_page.js --url https://example.com/page2
# Reload page
node scripts/navigate_page.js --type reload
# Reload ignoring cache
node scripts/navigate_page.js --type reload --ignoreCache true
# Go back
node scripts/navigate_page.js --type back
# Go forward
node scripts/navigate_page.js --type forward
```
**Related Tools:** new_page, wait_for
---
## new_page
Creates a new browser page (tab).
**Group:** Page Management
**Required Parameters:**
- `--url STRING` - URL to open
**Optional Parameters:**
- `--timeout NUMBER` - Page load timeout in milliseconds (default: 30000)
**Examples:**
```bash
node scripts/new_page.js --url https://example.com
# With longer timeout
node scripts/new_page.js --url https://slow-site.com --timeout 60000
```
**Notes:** New page becomes the selected page automatically.
**Related Tools:** list_pages, select_page, close_page
---
## performance_analyze_insight
Gets detailed information about a specific performance insight.
**Group:** Performance Analysis
**Required Parameters:**
- `--insightSetId STRING` - Insight set ID from performance trace
- `--insightName STRING` - Name of specific insight to analyze
**Examples:**
```bash
node scripts/performance_analyze_insight.js --insightSetId set_abc123 --insightName LargestContentfulPaint
node scripts/performance_analyze_insight.js --insightSetId set_abc123 --insightName CumulativeLayoutShift
```
**Common Insight Names:**
- LargestContentfulPaint
- FirstContentfulPaint
- CumulativeLayoutShift
- TotalBlockingTime
- TimeToInteractive
**Related Tools:** performance_start_trace, performance_stop_trace
---
## performance_start_trace
Starts performance trace recording.
**Group:** Performance Analysis
**Required Parameters:**
- `--reload BOOLEAN` - Reload page before tracing
- `--autoStop BOOLEAN` - Automatically stop when page loads
**Examples:**
```bash
# Start with page reload
node scripts/performance_start_trace.js --reload true --autoStop false
# Start without reload
node scripts/performance_start_trace.js --reload false --autoStop true
```
**Notes:** Only one trace can be active at a time. Call performance_stop_trace to get results.
**Related Tools:** performance_stop_trace, performance_analyze_insight
---
## performance_stop_trace
Stops the active performance trace and returns results.
**Group:** Performance Analysis
**No Parameters**
**Examples:**
```bash
node scripts/performance_stop_trace.js
```
**Output includes:**
- Core Web Vitals scores (LCP, FID, CLS)
- Performance insights
- Insight set IDs for detailed analysis
- Timing metrics
**Related Tools:** performance_start_trace, performance_analyze_insight
---
## press_key
Presses a key or key combination.
**Group:** Element Interaction
**Required Parameters:**
- `--key STRING` - Key or key combination to press
**Examples:**
```bash
# Single key
node scripts/press_key.js --key Enter
node scripts/press_key.js --key Tab
node scripts/press_key.js --key Escape
# Arrow keys
node scripts/press_key.js --key ArrowDown
node scripts/press_key.js --key ArrowUp
# Key combinations (use + separator)
node scripts/press_key.js --key "Control+S"
node scripts/press_key.js --key "Control+Shift+P"
node scripts/press_key.js --key "Alt+F4"
```
**Common Keys:** Enter, Tab, Escape, Space, Backspace, Delete, ArrowUp, ArrowDown, ArrowLeft, ArrowRight
**Modifiers:** Control, Shift, Alt, Meta (Command on Mac)
**Related Tools:** fill, click
---
## resize_page
Resizes the browser window to specific dimensions.
**Group:** Page Management
**Required Parameters:**
- `--width NUMBER` - Width in pixels
- `--height NUMBER` - Height in pixels
**Examples:**
```bash
# Desktop
node scripts/resize_page.js --width 1920 --height 1080
# Laptop
node scripts/resize_page.js --width 1366 --height 768
# Tablet
node scripts/resize_page.js --width 768 --height 1024
# Mobile
node scripts/resize_page.js --width 375 --height 667
```
**Common Dimensions:**
- Desktop: 1920x1080, 1440x900, 1366x768
- Tablet: 768x1024 (iPad), 600x960
- Mobile: 375x667 (iPhone), 360x640 (Android)
**Related Tools:** take_screenshot, emulate
---
## select_page
Switches the active context to a specific page.
**Group:** Page Management
**Required Parameters:**
- `--pageIdx NUMBER` - Page index from list_pages
**Examples:**
```bash
node scripts/select_page.js --pageIdx 0
node scripts/select_page.js --pageIdx 2
```
**Notes:** All subsequent commands operate on the selected page.
**Related Tools:** list_pages, new_page
---
## take_screenshot
Captures a visual screenshot of the page or element.
**Group:** Inspection & Debugging
**Optional Parameters:**
- `--format STRING` - Image format: png or jpeg (default: png)
- `--quality NUMBER` - JPEG quality 0-100 (default: 90)
- `--uid STRING` - Element UID to screenshot (if omitted, screenshots viewport)
- `--fullPage BOOLEAN` - Capture full scrollable page (default: false)
- `--filePath STRING` - Path to save image file
**Examples:**
```bash
# Full page PNG
node scripts/take_screenshot.js --fullPage true --filePath page.png
# Viewport only
node scripts/take_screenshot.js --filePath viewport.png
# Specific element
node scripts/take_screenshot.js --uid element_abc123 --filePath element.png
# Compressed JPEG
node scripts/take_screenshot.js --format jpeg --quality 80 --filePath page.jpg
```
**Related Tools:** take_snapshot
---
## take_snapshot
Captures text-based page structure with element UIDs.
**Group:** Inspection & Debugging
**Optional Parameters:**
- `--verbose BOOLEAN` - Include more details (default: false)
- `--filePath STRING` - Path to save snapshot file
**Examples:**
```bash
# Console output
node scripts/take_snapshot.js
# Verbose mode
node scripts/take_snapshot.js --verbose true
# Save to file
node scripts/take_snapshot.js --filePath snapshot.txt
# Both
node scripts/take_snapshot.js --verbose true --filePath detailed_snapshot.txt
```
**Output Format:**
```
Page: https://example.com
Title: Example Domain
button "Submit" [uid: button_submit_abc123]
input "Email" [uid: input_email_def456]
link "About" [uid: link_about_ghi789]
```
**Important:** Always use UIDs from the most recent snapshot. UIDs regenerate on each snapshot.
**Related Tools:** click, fill, hover, drag, take_screenshot
---
## upload_file
Uploads a file through a file input element.
**Group:** Element Interaction
**Required Parameters:**
- `--uid UID` - File input element UID
- `--filePath STRING` - Absolute path to file to upload
**Examples:**
```bash
# Upload document
node scripts/upload_file.js --uid input_file_abc --filePath /Users/username/documents/resume.pdf
# Upload image
node scripts/upload_file.js --uid input_avatar_xyz --filePath /Users/username/pictures/profile.jpg
```
**Notes:**
- Use absolute paths (not relative)
- Use forward slashes in paths
- Verify file exists before upload
**Related Tools:** click, fill, wait_for
---
## wait_for
Waits for specific text to appear on the page.
**Group:** Performance Analysis
**Required Parameters:**
- `--text STRING` - Text to wait for (exact match)
**Optional Parameters:**
- `--timeout NUMBER` - Maximum wait time in milliseconds (default: 30000)
**Examples:**
```bash
# Wait up to 30 seconds (default)
node scripts/wait_for.js --text "Loading complete"
# Wait up to 10 seconds
node scripts/wait_for.js --text "Welcome" --timeout 10000
# Wait for error message
node scripts/wait_for.js --text "Error occurred" --timeout 5000
```
**Notes:**
- Text match is exact (case-sensitive)
- Times out if text doesn't appear within timeout period
- Use after navigation, clicks, or any action that triggers loading
**Related Tools:** click, navigate_page, take_snapshot

View File

@@ -0,0 +1,743 @@
# Troubleshooting Guide
Common issues and solutions for chrome-devtools skill.
## Table of Contents
- [Connection Issues](#connection-issues)
- [Page Management Problems](#page-management-problems)
- [Element Interaction Issues](#element-interaction-issues)
- [Snapshot and Screenshot Problems](#snapshot-and-screenshot-problems)
- [Console and Network Debugging](#console-and-network-debugging)
- [Performance Analysis Issues](#performance-analysis-issues)
- [General Best Practices](#general-best-practices)
---
## Connection Issues
### Problem: "Cannot connect to mcp2rest"
**Symptoms:**
- Scripts fail with connection error
- "ECONNREFUSED" error on port 28888
**Solutions:**
1. **Check if mcp2rest is running:**
```bash
curl http://localhost:28888/health
```
Expected: `{"status": "healthy"}`
2. **Start mcp2rest if not running:**
```bash
mcp2rest start
```
3. **Verify chrome-devtools server is loaded:**
```bash
curl http://localhost:28888/servers
```
Should list chrome-devtools with "connected" status.
4. **Reload server if disconnected:**
```bash
mcp2rest reload chrome-devtools
```
### Problem: "Server not found"
**Symptoms:**
- Server not listed in mcp2rest
- Tools return "server not configured" error
**Solutions:**
1. **Check installed servers:**
```bash
mcp2rest list
```
2. **Add chrome-devtools server:**
```bash
mcp2rest add chrome-devtools
```
3. **Restart mcp2rest:**
```bash
mcp2rest restart
```
---
## Page Management Problems
### Problem: "Cannot close last page"
**Symptoms:**
- close_page fails with error about last page
**Solution:**
Always keep at least one page open. Open a new page before closing the last one:
```bash
# Check current pages
node scripts/list_pages.js
# Open new page first
node scripts/new_page.js --url https://example.com
# Now close the old page
node scripts/close_page.js --pageIdx 1
```
### Problem: "Page index out of range"
**Symptoms:**
- select_page or close_page fails
- "Invalid page index" error
**Solutions:**
1. **Always list pages first:**
```bash
node scripts/list_pages.js
```
2. **Use indices from the current list:**
Page indices shift when pages are closed. Always get fresh indices.
3. **Close pages in reverse order:**
```bash
# If closing multiple pages, start from highest index
node scripts/close_page.js --pageIdx 3
node scripts/close_page.js --pageIdx 2
node scripts/close_page.js --pageIdx 1
```
### Problem: "Navigation timeout"
**Symptoms:**
- new_page or navigate_page times out
- Page doesn't load within timeout period
**Solutions:**
1. **Increase timeout:**
```bash
node scripts/new_page.js --url https://slow-site.com --timeout 60000
```
2. **Check network connectivity:**
Verify the URL loads in a regular browser.
3. **Use emulation to debug slow loading:**
```bash
# Test without throttling first
node scripts/emulate.js --cpuThrottlingRate 1
node scripts/new_page.js --url https://example.com
```
### Problem: "Wrong page context"
**Symptoms:**
- Commands execute on wrong page
- Unexpected elements in snapshot
**Solutions:**
1. **Check selected page:**
```bash
node scripts/list_pages.js
# Look for "(selected)" indicator
```
2. **Explicitly select target page:**
```bash
node scripts/select_page.js --pageIdx 0
```
3. **Pattern: Always select before interaction:**
```bash
node scripts/list_pages.js
node scripts/select_page.js --pageIdx 1
node scripts/take_snapshot.js
```
---
## Element Interaction Issues
### Problem: "Element UID not found"
**Symptoms:**
- click, fill, or hover fails
- "UID does not exist" error
**Solutions:**
1. **Take fresh snapshot:**
UIDs regenerate on each snapshot. Never reuse old UIDs.
```bash
# Always take new snapshot before interaction
node scripts/take_snapshot.js
# Use UIDs from this output
node scripts/click.js --uid <fresh-uid>
```
2. **Verify element exists:**
Check the snapshot output to confirm the element is present.
3. **Wait for page to load:**
```bash
node scripts/wait_for.js --text "Page loaded" --timeout 10000
node scripts/take_snapshot.js
```
### Problem: "Click doesn't trigger action"
**Symptoms:**
- Element is clicked but nothing happens
- No error, but expected behavior doesn't occur
**Solutions:**
1. **Wait for page to fully load:**
```bash
node scripts/wait_for.js --text "Ready" --timeout 5000
node scripts/click.js --uid button_abc
```
2. **Try hover first:**
Some elements require hover to become clickable.
```bash
node scripts/hover.js --uid element_abc
node scripts/click.js --uid element_abc
```
3. **Check if element is visible:**
Hidden or off-screen elements may not be clickable. Use take_snapshot with verbose to check visibility.
4. **Use double-click if needed:**
```bash
node scripts/click.js --uid element_abc --dblClick true
```
### Problem: "Fill doesn't work on input"
**Symptoms:**
- Text not entered into field
- Select dropdown not changing
**Solutions:**
1. **Verify element type:**
Use take_snapshot to confirm it's an input/textarea/select.
2. **Click to focus first:**
```bash
node scripts/click.js --uid input_abc
node scripts/fill.js --uid input_abc --value "text"
```
3. **For custom components, use press_key:**
```bash
node scripts/click.js --uid custom_input
node scripts/press_key.js --key "H"
node scripts/press_key.js --key "i"
```
4. **For dropdowns, use exact option value:**
Check the HTML to find the correct option value.
### Problem: "Drag and drop doesn't work"
**Symptoms:**
- Drag operation completes but element doesn't move
- "Invalid UID" error
**Solutions:**
1. **Verify both UIDs are current:**
```bash
node scripts/take_snapshot.js
# Use UIDs from this output
node scripts/drag.js --from-uid <fresh-from> --to-uid <fresh-to>
```
2. **Add wait between operations:**
```bash
node scripts/drag.js --from-uid item1 --to-uid zone1
node scripts/wait_for.js --text "Moved" --timeout 3000
```
3. **Check if dropzone accepts the element:**
Some drag-and-drop UIs have restrictions on what can be dropped where.
### Problem: "File upload fails"
**Symptoms:**
- upload_file fails
- File path error
**Solutions:**
1. **Use absolute paths:**
```bash
# Good
node scripts/upload_file.js --uid input_file --filePath /Users/username/file.pdf
# Bad
# node scripts/upload_file.js --uid input_file --filePath ./file.pdf
```
2. **Use forward slashes:**
```bash
# Good
/Users/username/documents/file.pdf
# Bad (Windows-style)
# C:\Users\username\documents\file.pdf
```
3. **Verify file exists:**
```bash
ls -la /Users/username/documents/file.pdf
```
4. **Check file input UID:**
Take fresh snapshot and verify the element is a file input.
---
## Snapshot and Screenshot Problems
### Problem: "Snapshot shows different UIDs each time"
**Symptoms:**
- UIDs change on each snapshot
- Previously working UIDs stop working
**Solution:**
**This is expected behavior.** UIDs are dynamically generated on each snapshot. Always use the most recent snapshot:
```bash
# Pattern: Always snapshot before interaction
node scripts/take_snapshot.js
# Immediately use UIDs from output
node scripts/click.js --uid <current-uid>
```
### Problem: "Screenshot is blank or black"
**Symptoms:**
- Screenshot file is created but shows blank/black image
**Solutions:**
1. **Wait for page to render:**
```bash
node scripts/wait_for.js --text "Content" --timeout 10000
node scripts/take_screenshot.js --filePath page.png
```
2. **Try full page screenshot:**
```bash
node scripts/take_screenshot.js --fullPage true --filePath page.png
```
3. **Verify element is visible:**
For element screenshots, ensure the element isn't hidden or off-screen.
4. **Check page actually loaded:**
```bash
node scripts/take_snapshot.js
# Verify page content appears in snapshot
```
### Problem: "Screenshot file not saving"
**Symptoms:**
- No error but file not created
- "File not found" when opening
**Solutions:**
1. **Use absolute path:**
```bash
node scripts/take_screenshot.js --filePath /Users/username/screenshots/page.png
```
2. **Ensure directory exists:**
```bash
mkdir -p /Users/username/screenshots
node scripts/take_screenshot.js --filePath /Users/username/screenshots/page.png
```
3. **Check file permissions:**
Ensure you have write access to the target directory.
---
## Console and Network Debugging
### Problem: "Console messages not showing up"
**Symptoms:**
- list_console_messages returns empty or incomplete results
**Solutions:**
1. **Messages accumulate since navigation:**
Console messages are captured from the current page navigation onwards.
2. **Reload if needed:**
```bash
node scripts/navigate_page.js --type reload
# Wait for page load
node scripts/wait_for.js --text "Ready" --timeout 10000
# Now check console
node scripts/list_console_messages.js
```
3. **Include preserved messages:**
```bash
node scripts/list_console_messages.js --includePreservedMessages true
```
4. **Ensure page has errors to show:**
Use take_snapshot or evaluate_script to verify page loaded correctly.
### Problem: "Network requests list is empty"
**Symptoms:**
- list_network_requests returns no results
- Expected API calls not showing
**Solutions:**
1. **Requests are captured from navigation onwards:**
```bash
# Navigate first to capture requests
node scripts/navigate_page.js --url https://example.com
# Wait for page to load
node scripts/wait_for.js --text "Loaded" --timeout 10000
# Now check requests
node scripts/list_network_requests.js
```
2. **Filter by resource type:**
```bash
# Maybe filtering too strictly
node scripts/list_network_requests.js --resourceTypes fetch,xhr,document
```
3. **Include preserved requests:**
```bash
node scripts/list_network_requests.js --includePreservedRequests true
```
### Problem: "Cannot find console message or network request ID"
**Symptoms:**
- get_console_message or get_network_request fails
- "Invalid ID" error
**Solutions:**
1. **List first to get IDs:**
```bash
# For console
node scripts/list_console_messages.js
# Copy message ID from output
node scripts/get_console_message.js --msgid <id-from-list>
# For network
node scripts/list_network_requests.js
# Copy request ID from output
node scripts/get_network_request.js --reqid <id-from-list>
```
2. **IDs are session-specific:**
IDs don't persist across page navigations. Get fresh IDs after navigation.
---
## Performance Analysis Issues
### Problem: "evaluate_script returns null or error"
**Symptoms:**
- Script execution fails
- Returns null unexpectedly
- "Evaluation failed" error
**Solutions:**
1. **Return JSON-serializable values only:**
```bash
# Good: primitives, arrays, plain objects
node scripts/evaluate_script.js --function "() => document.title"
node scripts/evaluate_script.js --function "() => [1, 2, 3]"
node scripts/evaluate_script.js --function "() => ({key: 'value'})"
# Bad: DOM nodes, functions, circular references
# node scripts/evaluate_script.js --function "() => document.querySelector('div')"
```
2. **Extract values from DOM elements:**
```bash
# Instead of returning DOM nodes, extract their properties
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('a')).map(a => a.href)"
```
3. **Check for JavaScript errors:**
```bash
node scripts/list_console_messages.js --types error
```
4. **Verify function syntax:**
```bash
# Arrow function
node scripts/evaluate_script.js --function "() => document.title"
# Function with parameters
node scripts/evaluate_script.js --function "(x, y) => x + y" --args '[5, 3]'
```
### Problem: "wait_for times out"
**Symptoms:**
- wait_for exceeds timeout
- Text never appears
**Solutions:**
1. **Increase timeout:**
```bash
node scripts/wait_for.js --text "Loaded" --timeout 30000
```
2. **Verify text actually appears:**
```bash
# Check with snapshot
node scripts/take_snapshot.js
# Look for the expected text
```
3. **Text match is exact:**
Check spelling, capitalization, and spacing.
```bash
# Case-sensitive match
# "Welcome" ≠ "welcome" ≠ "Welcome!"
```
4. **Wait for network first:**
```bash
# If text appears after API call, wait longer
node scripts/wait_for.js --text "Data loaded" --timeout 20000
```
### Problem: "Dialog not handled"
**Symptoms:**
- handle_dialog fails
- "No dialog present" error
**Solutions:**
1. **Dialog must be open first:**
```bash
# Trigger dialog
node scripts/click.js --uid button_delete
# Immediately handle it
node scripts/handle_dialog.js --action accept
```
2. **Some "dialogs" are custom HTML:**
If it's not a real browser dialog (alert/confirm/prompt), use click instead:
```bash
# For custom modal dialogs
node scripts/take_snapshot.js
node scripts/click.js --uid button_modal_ok
```
3. **Timing matters:**
Handle dialog immediately after triggering action.
### Problem: "Performance trace shows unexpected results"
**Symptoms:**
- CWV scores don't match expectations
- Missing performance data
**Solutions:**
1. **Ensure page fully loads:**
```bash
node scripts/performance_start_trace.js --reload true --autoStop false
node scripts/wait_for.js --text "Loaded" --timeout 20000
node scripts/performance_stop_trace.js
```
2. **Use reload for consistent measurement:**
```bash
# For initial page load measurement
node scripts/performance_start_trace.js --reload true --autoStop false
```
3. **Clear browser state:**
Navigation with cache clear:
```bash
node scripts/navigate_page.js --url https://example.com --ignoreCache true
```
4. **Disable emulation if active:**
```bash
node scripts/emulate.js --cpuThrottlingRate 1
```
### Problem: "Emulation not working"
**Symptoms:**
- Page loads at normal speed despite emulation
- No visible effect from throttling
**Solutions:**
1. **Emulation persists for session:**
Reset to normal first, then apply:
```bash
# Reset
node scripts/emulate.js --cpuThrottlingRate 1
# Then apply desired emulation
node scripts/emulate.js --cpuThrottlingRate 4
```
2. **Network conditions must be valid JSON:**
```bash
# All three properties required
node scripts/emulate.js --networkConditions '{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'
```
3. **Verify effect with performance trace:**
```bash
node scripts/emulate.js --cpuThrottlingRate 4
node scripts/performance_start_trace.js --reload true --autoStop false
node scripts/wait_for.js --text "Loaded" --timeout 60000
node scripts/performance_stop_trace.js
# Check timing metrics in output
```
---
## General Best Practices
### Always Snapshot Before Interaction
UIDs are dynamic. Take a fresh snapshot before every interaction:
```bash
# Good pattern
node scripts/take_snapshot.js
node scripts/click.js --uid <current-uid>
# Bad pattern (will fail)
# node scripts/take_snapshot.js
# ... do other things ...
# node scripts/click.js --uid <old-uid> # UID expired!
```
### Wait After Actions
Allow time for UI updates:
```bash
node scripts/click.js --uid button_submit
node scripts/wait_for.js --text "Success" --timeout 5000
node scripts/take_snapshot.js
```
### Use Absolute Paths
Always use absolute paths for files:
```bash
# Good
/Users/username/documents/file.pdf
/home/user/screenshots/page.png
# Bad
./file.pdf
../screenshots/page.png
```
### Check Connection First
Before running workflows, verify mcp2rest is healthy:
```bash
curl http://localhost:28888/health
```
### List Before Selecting
Always list pages before selecting or closing:
```bash
node scripts/list_pages.js
node scripts/select_page.js --pageIdx 1
```
### Handle Errors Gracefully
Check console and network for debugging:
```bash
# After error occurs
node scripts/list_console_messages.js --types error
node scripts/list_network_requests.js
node scripts/take_screenshot.js --filePath error_state.png
```
### Use Verbose for Debugging
Get more details when troubleshooting:
```bash
node scripts/take_snapshot.js --verbose true
```
### Save Outputs for Analysis
Redirect output to files for later review:
```bash
node scripts/list_console_messages.js > console_log.txt
node scripts/list_network_requests.js > network_log.txt
node scripts/take_snapshot.js --filePath snapshot.txt
```
---
## Getting Help
If you encounter issues not covered here:
1. **Check tool documentation:** @reference/all-tools.md
2. **Review workflows:** @workflows/[tool-group].md
3. **Test with minimal example:** Isolate the problem with simplest reproduction
4. **Check mcp2rest status:** Ensure server is connected and healthy
5. **Restart mcp2rest:** Sometimes a fresh start helps: `mcp2rest restart`

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: click
*
* Clicks on the provided element
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('click')
.description('Clicks on the provided element')
.option('--uid <value>', 'The uid of an element on the page from the page content snapshot (required)')
.option('--dblClick', 'Set to true for double clicks. Default is false.')
.parse();
const options = program.opts();
// Validate required options
if (!options.uid) {
console.error('Error: --uid is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.uid !== undefined) {
args['uid'] = options.uid;
}
if (options.dblClick) {
args['dblClick'] = true;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'click', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: close_page
*
* Closes the page by its index. The last open page cannot be closed.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('close_page')
.description('Closes the page by its index. The last open page cannot be closed.')
.option('--pageIdx <value>', 'The index of the page to close. Call list_pages to list pages. (required)', parseFloat)
.addHelpText('after', ' Note: --pageIdx is required')
.parse();
const options = program.opts();
// Validate required options
if (!options.pageIdx) {
console.error('Error: --pageIdx is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.pageIdx !== undefined) {
args['pageIdx'] = options.pageIdx;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'close_page', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: drag
*
* Drag an element onto another element
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('drag')
.description('Drag an element onto another element')
.option('--from-uid <value>', 'The uid of the element to drag (required)')
.option('--to-uid <value>', 'The uid of the element to drop into (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.fromUid) {
console.error('Error: --from-uid is required');
process.exit(1);
}
if (!options.toUid) {
console.error('Error: --to-uid is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.fromUid !== undefined) {
args['from_uid'] = options.fromUid;
}
if (options.toUid !== undefined) {
args['to_uid'] = options.toUid;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'drag', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,39 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: emulate
*
* Emulates various features on the selected page.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('emulate')
.description('Emulates various features on the selected page.')
.option('--networkConditions <value>', 'Throttle network. Set to \"No emulation\" to disable. If omitted, conditions remain unchanged.. Choices: "No emulation", "Offline", "Slow 3G", "Fast 3G", "Slow 4G", "Fast 4G"')
.option('--cpuThrottlingRate <value>', 'Represents the CPU slowdown factor. Set the rate to 1 to disable throttling. If omitted, throttling remains unchanged.', parseFloat)
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.networkConditions !== undefined) {
args['networkConditions'] = options.networkConditions;
}
if (options.cpuThrottlingRate !== undefined) {
args['cpuThrottlingRate'] = options.cpuThrottlingRate;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'emulate', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,55 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: evaluate_script
*
* Evaluate a JavaScript function inside the currently selected page. Returns the response as JSON
so returned values have to JSON-serializable.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('evaluate_script')
.description('Evaluate a JavaScript function inside the currently selected page. Returns the response as JSON\nso returned values have to JSON-serializable.')
.option('--function <value>', 'A JavaScript function declaration to be executed by the tool in the currently selected page.
Example without arguments: `() => {
return document.title
}` or `async () => {
return await fetch(\"example.com\")
}`.
Example with arguments: `(el) => {
return el.innerText;
}`
(required)')
.option('--args <items...>', 'An optional list of arguments to pass to the function.')
.parse();
const options = program.opts();
// Validate required options
if (!options.function) {
console.error('Error: --function is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.function !== undefined) {
args['function'] = options.function;
}
if (options.args !== undefined) {
args['args'] = options.args;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'evaluate_script', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: fill
*
* Type text into a input, text area or select an option from a <select> element.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('fill')
.description('Type text into a input, text area or select an option from a <select> element.')
.option('--uid <value>', 'The uid of an element on the page from the page content snapshot (required)')
.option('--value <value>', 'The value to fill in (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.uid) {
console.error('Error: --uid is required');
process.exit(1);
}
if (!options.value) {
console.error('Error: --value is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.uid !== undefined) {
args['uid'] = options.uid;
}
if (options.value !== undefined) {
args['value'] = options.value;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'fill', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: fill_form
*
* Fill out multiple form elements at once
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('fill_form')
.description('Fill out multiple form elements at once')
.option('--elements <items...>', 'Elements from snapshot to fill out. (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.elements) {
console.error('Error: --elements is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.elements !== undefined) {
args['elements'] = options.elements;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'fill_form', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: get_console_message
*
* Gets a console message by its ID. You can get all messages by calling list_console_messages.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('get_console_message')
.description('Gets a console message by its ID. You can get all messages by calling list_console_messages.')
.option('--msgid <value>', 'The msgid of a console message on the page from the listed console messages (required)', parseFloat)
.addHelpText('after', ' Note: --msgid is required')
.parse();
const options = program.opts();
// Validate required options
if (!options.msgid) {
console.error('Error: --msgid is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.msgid !== undefined) {
args['msgid'] = options.msgid;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'get_console_message', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,35 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: get_network_request
*
* Gets a network request by an optional reqid, if omitted returns the currently selected request in the DevTools Network panel.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('get_network_request')
.description('Gets a network request by an optional reqid, if omitted returns the currently selected request in the DevTools Network panel.')
.option('--reqid <value>', 'The reqid of the network request. If omitted returns the currently selected request in the DevTools Network panel.', parseFloat)
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.reqid !== undefined) {
args['reqid'] = options.reqid;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'get_network_request', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: handle_dialog
*
* If a browser dialog was opened, use this command to handle it
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('handle_dialog')
.description('If a browser dialog was opened, use this command to handle it')
.option('--action <value>', 'Whether to dismiss or accept the dialog (required). Choices: "accept", "dismiss"')
.option('--promptText <value>', 'Optional prompt text to enter into the dialog.')
.parse();
const options = program.opts();
// Validate required options
if (!options.action) {
console.error('Error: --action is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.action !== undefined) {
args['action'] = options.action;
}
if (options.promptText !== undefined) {
args['promptText'] = options.promptText;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'handle_dialog', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: hover
*
* Hover over the provided element
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('hover')
.description('Hover over the provided element')
.option('--uid <value>', 'The uid of an element on the page from the page content snapshot (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.uid) {
console.error('Error: --uid is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.uid !== undefined) {
args['uid'] = options.uid;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'hover', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: list_console_messages
*
* List all console messages for the currently selected page since the last navigation.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('list_console_messages')
.description('List all console messages for the currently selected page since the last navigation.')
.option('--pageSize <value>', 'Maximum number of messages to return. When omitted, returns all requests.', (val) => parseInt(val, 10))
.option('--pageIdx <value>', 'Page number to return (0-based). When omitted, returns the first page.', (val) => parseInt(val, 10))
.option('--types <items...>', 'Filter messages to only return messages of the specified resource types. When omitted or empty, returns all messages.')
.option('--includePreservedMessages', 'Set to true to return the preserved messages over the last 3 navigations.')
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.pageSize !== undefined) {
args['pageSize'] = options.pageSize;
}
if (options.pageIdx !== undefined) {
args['pageIdx'] = options.pageIdx;
}
if (options.types !== undefined) {
args['types'] = options.types;
}
if (options.includePreservedMessages) {
args['includePreservedMessages'] = true;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'list_console_messages', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: list_network_requests
*
* List all requests for the currently selected page since the last navigation.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('list_network_requests')
.description('List all requests for the currently selected page since the last navigation.')
.option('--pageSize <value>', 'Maximum number of requests to return. When omitted, returns all requests.', (val) => parseInt(val, 10))
.option('--pageIdx <value>', 'Page number to return (0-based). When omitted, returns the first page.', (val) => parseInt(val, 10))
.option('--resourceTypes <items...>', 'Filter requests to only return requests of the specified resource types. When omitted or empty, returns all requests.')
.option('--includePreservedRequests', 'Set to true to return the preserved requests over the last 3 navigations.')
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.pageSize !== undefined) {
args['pageSize'] = options.pageSize;
}
if (options.pageIdx !== undefined) {
args['pageIdx'] = options.pageIdx;
}
if (options.resourceTypes !== undefined) {
args['resourceTypes'] = options.resourceTypes;
}
if (options.includePreservedRequests) {
args['includePreservedRequests'] = true;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'list_network_requests', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: list_pages
*
* Get a list of pages open in the browser.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('list_pages')
.description('Get a list of pages open in the browser.')
// No options required
.parse();
const options = program.opts();
const args = {};
// Call the tool
try {
const result = await callTool('chrome-devtools', 'list_pages', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env node
/**
* MCP REST Client for chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
*
* Shared MCP REST client for tool scripts.
*/
import axios from 'axios';
// MCP2REST endpoint (configurable via environment variable)
const MCP_REST_URL = process.env.MCP_REST_URL || 'http://localhost:28888';
/**
* Call an MCP tool via mcp2rest REST API.
*
* @param {string} server - Server name (e.g., "chrome-devtools")
* @param {string} tool - Tool name (e.g., "click")
* @param {object} args - Tool arguments as object
* @returns {Promise<string>} Tool result as formatted string
*/
export async function callTool(server, tool, args) {
const url = `${MCP_REST_URL}/call`;
const payload = {
server,
tool,
arguments: args || {},
};
try {
const response = await axios.post(url, payload, {
headers: { 'Content-Type': 'application/json' },
timeout: 30000,
});
const data = response.data;
if (data.success) {
// Extract and format result
const result = data.result || {};
const content = result.content || [];
// Format output nicely
const outputParts = [];
for (const item of content) {
if (item.type === 'text') {
outputParts.push(item.text || '');
} else if (item.type === 'image') {
// For images, just note their presence
const dataLen = (item.data || '').length;
outputParts.push(`[Image data: ${dataLen} bytes]`);
} else if (item.type === 'resource') {
outputParts.push(JSON.stringify(item.resource || {}, null, 2));
}
}
return outputParts.length > 0 ? outputParts.join('\n') : JSON.stringify(result, null, 2);
} else {
const error = data.error || {};
const errorMsg = error.message || 'Unknown error';
const errorCode = error.code || 'UNKNOWN';
console.error(`Error [${errorCode}]: ${errorMsg}`);
process.exit(1);
}
} catch (error) {
if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') {
console.error(`Error: Cannot connect to mcp2rest at ${MCP_REST_URL}`);
console.error('Make sure mcp2rest is running.');
} else if (error.code === 'ETIMEDOUT' || error.code === 'ECONNABORTED') {
console.error('Error: Request timed out after 30 seconds');
} else if (error.response) {
console.error(`Error: HTTP ${error.response.status} - ${error.response.data}`);
} else {
console.error(`Error: ${error.message}`);
}
process.exit(1);
}
}

View File

@@ -0,0 +1,47 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: navigate_page
*
* Navigates the currently selected page to a URL.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('navigate_page')
.description('Navigates the currently selected page to a URL.')
.option('--type <value>', 'Navigate the page by URL, back or forward in history, or reload.. Choices: "url", "back", "forward", "reload"')
.option('--url <value>', 'Target URL (only type=url)')
.option('--ignoreCache', 'Whether to ignore cache on reload.')
.option('--timeout <value>', 'Maximum wait time in milliseconds. If set to 0, the default timeout will be used.', (val) => parseInt(val, 10))
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.type !== undefined) {
args['type'] = options.type;
}
if (options.url !== undefined) {
args['url'] = options.url;
}
if (options.ignoreCache) {
args['ignoreCache'] = true;
}
if (options.timeout !== undefined) {
args['timeout'] = options.timeout;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'navigate_page', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: new_page
*
* Creates a new page
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('new_page')
.description('Creates a new page')
.option('--url <value>', 'URL to load in a new page. (required)')
.option('--timeout <value>', 'Maximum wait time in milliseconds. If set to 0, the default timeout will be used.', (val) => parseInt(val, 10))
.parse();
const options = program.opts();
// Validate required options
if (!options.url) {
console.error('Error: --url is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.url !== undefined) {
args['url'] = options.url;
}
if (options.timeout !== undefined) {
args['timeout'] = options.timeout;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'new_page', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,18 @@
{
"name": "mcp-chrome-devtools-skill",
"version": "1.0.0",
"description": "Claude Code skill scripts for chrome-devtools MCP server",
"type": "module",
"dependencies": {
"axios": "^1.6.2",
"commander": "^11.1.0"
},
"keywords": [
"mcp",
"claude-code",
"skill",
"chrome-devtools"
],
"author": "",
"license": "MIT"
}

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: performance_analyze_insight
*
* Provides more detailed information on a specific Performance Insight of an insight set that was highlighted in the results of a trace recording.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('performance_analyze_insight')
.description('Provides more detailed information on a specific Performance Insight of an insight set that was highlighted in the results of a trace recording.')
.option('--insightSetId <value>', 'The id for the specific insight set. Only use the ids given in the \"Available insight sets\" list. (required)')
.option('--insightName <value>', 'The name of the Insight you want more information on. For example: \"DocumentLatency\" or \"LCPBreakdown\" (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.insightSetId) {
console.error('Error: --insightSetId is required');
process.exit(1);
}
if (!options.insightName) {
console.error('Error: --insightName is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.insightSetId !== undefined) {
args['insightSetId'] = options.insightSetId;
}
if (options.insightName !== undefined) {
args['insightName'] = options.insightName;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'performance_analyze_insight', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: performance_start_trace
*
* Starts a performance trace recording on the selected page. This can be used to look for performance problems and insights to improve the performance of the page. It will also report Core Web Vital (CWV) scores for the page.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('performance_start_trace')
.description('Starts a performance trace recording on the selected page. This can be used to look for performance problems and insights to improve the performance of the page. It will also report Core Web Vital (CWV) scores for the page.')
.option('--reload', 'Determines if, once tracing has started, the page should be automatically reloaded.')
.option('--autoStop', 'Determines if the trace recording should be automatically stopped.')
.parse();
const options = program.opts();
// Validate required options
if (!options.reload) {
console.error('Error: --reload is required');
process.exit(1);
}
if (!options.autoStop) {
console.error('Error: --autoStop is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.reload) {
args['reload'] = true;
}
if (options.autoStop) {
args['autoStop'] = true;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'performance_start_trace', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: performance_stop_trace
*
* Stops the active performance trace recording on the selected page.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('performance_stop_trace')
.description('Stops the active performance trace recording on the selected page.')
// No options required
.parse();
const options = program.opts();
const args = {};
// Call the tool
try {
const result = await callTool('chrome-devtools', 'performance_stop_trace', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: press_key
*
* Press a key or key combination. Use this when other input methods like fill() cannot be used (e.g., keyboard shortcuts, navigation keys, or special key combinations).
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('press_key')
.description('Press a key or key combination. Use this when other input methods like fill() cannot be used (e.g., keyboard shortcuts, navigation keys, or special key combinations).')
.option('--key <value>', 'A key or a combination (e.g., \"Enter\", \"Control+A\", \"Control++\", \"Control+Shift+R\"). Modifiers: Control, Shift, Alt, Meta (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.key) {
console.error('Error: --key is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.key !== undefined) {
args['key'] = options.key;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'press_key', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: resize_page
*
* Resizes the selected page's window so that the page has specified dimension
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('resize_page')
.description('Resizes the selected page\'s window so that the page has specified dimension')
.option('--width <value>', 'Page width (required)', parseFloat)
.addHelpText('after', ' Note: --width is required')
.option('--height <value>', 'Page height (required)', parseFloat)
.addHelpText('after', ' Note: --height is required')
.parse();
const options = program.opts();
// Validate required options
if (!options.width) {
console.error('Error: --width is required');
process.exit(1);
}
if (!options.height) {
console.error('Error: --height is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.width !== undefined) {
args['width'] = options.width;
}
if (options.height !== undefined) {
args['height'] = options.height;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'resize_page', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: select_page
*
* Select a page as a context for future tool calls.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('select_page')
.description('Select a page as a context for future tool calls.')
.option('--pageIdx <value>', 'The index of the page to select. Call list_pages to list pages. (required)', parseFloat)
.addHelpText('after', ' Note: --pageIdx is required')
.parse();
const options = program.opts();
// Validate required options
if (!options.pageIdx) {
console.error('Error: --pageIdx is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.pageIdx !== undefined) {
args['pageIdx'] = options.pageIdx;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'select_page', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: take_screenshot
*
* Take a screenshot of the page or element.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('take_screenshot')
.description('Take a screenshot of the page or element.')
.option('--format <value>', 'Type of format to save the screenshot as. Default is \"png\". Choices: "png", "jpeg", "webp"')
.option('--quality <value>', 'Compression quality for JPEG and WebP formats (0-100). Higher values mean better quality but larger file sizes. Ignored for PNG format.', parseFloat)
.option('--uid <value>', 'The uid of an element on the page from the page content snapshot. If omitted takes a pages screenshot.')
.option('--fullPage', 'If set to true takes a screenshot of the full page instead of the currently visible viewport. Incompatible with uid.')
.option('--filePath <value>', 'The absolute path, or a path relative to the current working directory, to save the screenshot to instead of attaching it to the response.')
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.format !== undefined) {
args['format'] = options.format;
}
if (options.quality !== undefined) {
args['quality'] = options.quality;
}
if (options.uid !== undefined) {
args['uid'] = options.uid;
}
if (options.fullPage) {
args['fullPage'] = true;
}
if (options.filePath !== undefined) {
args['filePath'] = options.filePath;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'take_screenshot', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: take_snapshot
*
* Take a text snapshot of the currently selected page based on the a11y tree. The snapshot lists page elements along with a unique
identifier (uid). Always use the latest snapshot. Prefer taking a snapshot over taking a screenshot. The snapshot indicates the element selected
in the DevTools Elements panel (if any).
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('take_snapshot')
.description('Take a text snapshot of the currently selected page based on the a11y tree. The snapshot lists page elements along with a unique\nidentifier (uid). Always use the latest snapshot. Prefer taking a snapshot over taking a screenshot. The snapshot indicates the element selected\nin the DevTools Elements panel (if any).')
.option('--verbose', 'Whether to include all possible information available in the full a11y tree. Default is false.')
.option('--filePath <value>', 'The absolute path, or a path relative to the current working directory, to save the snapshot to instead of attaching it to the response.')
.parse();
const options = program.opts();
// Build arguments object
const args = {};
if (options.verbose) {
args['verbose'] = true;
}
if (options.filePath !== undefined) {
args['filePath'] = options.filePath;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'take_snapshot', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: upload_file
*
* Upload a file through a provided element.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('upload_file')
.description('Upload a file through a provided element.')
.option('--uid <value>', 'The uid of the file input element or an element that will open file chooser on the page from the page content snapshot (required)')
.option('--filePath <value>', 'The local path of the file to upload (required)')
.parse();
const options = program.opts();
// Validate required options
if (!options.uid) {
console.error('Error: --uid is required');
process.exit(1);
}
if (!options.filePath) {
console.error('Error: --filePath is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.uid !== undefined) {
args['uid'] = options.uid;
}
if (options.filePath !== undefined) {
args['filePath'] = options.filePath;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'upload_file', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env node
/**
* MCP Server: chrome-devtools
* Server Version: 0.10.2
* Generated: 2025-11-23
* Tool: wait_for
*
* Wait for the specified text to appear on the selected page.
*/
import { program } from 'commander';
import { callTool } from './mcp_client.js';
program
.name('wait_for')
.description('Wait for the specified text to appear on the selected page.')
.option('--text <value>', 'Text to appear on the page (required)')
.option('--timeout <value>', 'Maximum wait time in milliseconds. If set to 0, the default timeout will be used.', (val) => parseInt(val, 10))
.parse();
const options = program.opts();
// Validate required options
if (!options.text) {
console.error('Error: --text is required');
process.exit(1);
}
// Build arguments object
const args = {};
if (options.text !== undefined) {
args['text'] = options.text;
}
if (options.timeout !== undefined) {
args['timeout'] = options.timeout;
}
// Call the tool
try {
const result = await callTool('chrome-devtools', 'wait_for', args);
console.log(result);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}

View File

@@ -0,0 +1,310 @@
# Element Interaction Workflows
User input simulation for clicking, typing, form filling, and drag & drop operations.
## Tools in This Group
### click
Clicks on an element identified by its UID.
**Required:** `--uid UID`
**Optional:** `--dblClick [true|false]`
```bash
# Single click
node scripts/click.js --uid button_submit_abc123
# Double click
node scripts/click.js --uid file_icon_xyz789 --dblClick true
```
### fill
Types text into inputs, textareas, or selects options in dropdown menus.
**Required:** `--uid UID --value VALUE`
```bash
# Fill text input
node scripts/fill.js --uid input_username_abc --value john.doe
# Fill textarea
node scripts/fill.js --uid textarea_comment_def --value "This is a comment"
# Select dropdown option
node scripts/fill.js --uid select_country_ghi --value "United States"
```
### fill_form
Fills multiple form fields at once using a JSON array.
**Required:** `--elements JSON_ARRAY`
```bash
node scripts/fill_form.js --elements '[{"uid":"input_email","value":"test@example.com"},{"uid":"input_password","value":"secret123"}]'
```
### hover
Hovers the mouse over an element.
**Required:** `--uid UID`
```bash
node scripts/hover.js --uid tooltip_trigger_abc
```
### drag
Drags one element onto another element.
**Required:** `--from-uid FROM_UID --to-uid TO_UID`
```bash
node scripts/drag.js --from-uid draggable_item_abc --to-uid dropzone_xyz
```
### upload_file
Uploads a file through a file input element.
**Required:** `--uid UID --filePath FILEPATH`
```bash
node scripts/upload_file.js --uid input_file_upload --filePath /Users/username/documents/resume.pdf
```
### press_key
Presses a key or key combination (for keyboard shortcuts, navigation, special keys).
**Required:** `--key KEY`
```bash
# Single key
node scripts/press_key.js --key Enter
# Key combination
node scripts/press_key.js --key "Control+S"
# Navigation
node scripts/press_key.js --key ArrowDown
```
## Workflows
### Workflow: Login Form Automation
Complete login process with validation:
- [ ] Open login page: `node scripts/new_page.js --url https://example.com/login`
- [ ] Wait for form: `node scripts/wait_for.js --text "Sign In" --timeout 5000`
- [ ] Get element UIDs: `node scripts/take_snapshot.js`
- [ ] Fill username: `node scripts/fill.js --uid input_username_a1b2 --value testuser`
- [ ] Fill password: `node scripts/fill.js --uid input_password_c3d4 --value mypassword123`
- [ ] Submit form: `node scripts/click.js --uid button_submit_e5f6`
- [ ] Wait for redirect: `node scripts/wait_for.js --text "Dashboard" --timeout 10000`
- [ ] Verify login: `node scripts/take_screenshot.js --filePath logged_in.png`
**Input Example:**
```
Username field UID: input_username_a1b2
Password field UID: input_password_c3d4
Submit button UID: button_submit_e5f6
```
**Expected Output:**
User logged in successfully, redirected to dashboard.
### Workflow: Multi-Field Form with Dropdowns
Fill complex form with various input types:
- [ ] Navigate to form: `node scripts/new_page.js --url https://example.com/signup`
- [ ] Get structure: `node scripts/take_snapshot.js`
- [ ] Fill first name: `node scripts/fill.js --uid input_firstname --value John`
- [ ] Fill last name: `node scripts/fill.js --uid input_lastname --value Doe`
- [ ] Fill email: `node scripts/fill.js --uid input_email --value john.doe@example.com`
- [ ] Select country: `node scripts/fill.js --uid select_country --value "United States"`
- [ ] Select state: `node scripts/fill.js --uid select_state --value California`
- [ ] Fill textarea: `node scripts/fill.js --uid textarea_bio --value "Software engineer with 5 years experience"`
- [ ] Submit: `node scripts/click.js --uid button_register`
- [ ] Verify: `node scripts/wait_for.js --text "Registration successful" --timeout 10000`
**Expected Output:**
All form fields filled correctly, registration completed.
### Workflow: Bulk Form Filling
Use fill_form for efficient multi-field updates:
- [ ] Open form: `node scripts/new_page.js --url https://example.com/profile`
- [ ] Identify UIDs: `node scripts/take_snapshot.js`
- [ ] Fill all fields at once:
```bash
node scripts/fill_form.js --elements '[
{"uid":"input_name","value":"John Doe"},
{"uid":"input_email","value":"john@example.com"},
{"uid":"input_phone","value":"555-1234"},
{"uid":"select_timezone","value":"America/Los_Angeles"}
]'
```
- [ ] Review changes: `node scripts/take_snapshot.js`
- [ ] Save: `node scripts/click.js --uid button_save`
- [ ] Verify: `node scripts/wait_for.js --text "Profile updated" --timeout 5000`
**Expected Output:**
All fields updated in single operation, profile saved successfully.
### Workflow: File Upload with Validation
Upload a file and verify success:
- [ ] Navigate to upload page: `node scripts/new_page.js --url https://example.com/upload`
- [ ] Get file input UID: `node scripts/take_snapshot.js`
- [ ] Select file: `node scripts/upload_file.js --uid input_file_abc123 --filePath /Users/username/documents/report.pdf`
- [ ] Wait for preview: `node scripts/wait_for.js --text "report.pdf" --timeout 5000`
- [ ] Verify file name appears: `node scripts/take_snapshot.js`
- [ ] Click upload button: `node scripts/click.js --uid button_upload_xyz`
- [ ] Wait for completion: `node scripts/wait_for.js --text "Upload successful" --timeout 30000`
- [ ] Capture confirmation: `node scripts/take_screenshot.js --filePath upload_complete.png`
**Input Example:**
File path: `/Users/username/documents/report.pdf`
File input UID: `input_file_abc123`
**Expected Output:**
File uploaded successfully, confirmation message displayed.
### Workflow: Drag and Drop Interface
Interact with drag-and-drop components:
- [ ] Open drag interface: `node scripts/new_page.js --url https://example.com/kanban`
- [ ] Get board structure: `node scripts/take_snapshot.js`
- [ ] Drag task 1: `node scripts/drag.js --from-uid task_item_1 --to-uid column_in_progress`
- [ ] Wait for update: `node scripts/wait_for.js --text "Task moved" --timeout 3000`
- [ ] Drag task 2: `node scripts/drag.js --from-uid task_item_2 --to-uid column_done`
- [ ] Verify final state: `node scripts/take_snapshot.js`
- [ ] Save changes: `node scripts/click.js --uid button_save_board`
**Expected Output:**
Tasks moved between columns, board state updated and saved.
### Workflow: Keyboard Navigation
Use keyboard shortcuts and navigation keys:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/editor`
- [ ] Focus text area: `node scripts/click.js --uid textarea_editor_abc`
- [ ] Type content: `node scripts/fill.js --uid textarea_editor_abc --value "Hello world"`
- [ ] Select all: `node scripts/press_key.js --key "Control+A"`
- [ ] Copy: `node scripts/press_key.js --key "Control+C"`
- [ ] Navigate down: `node scripts/press_key.js --key ArrowDown`
- [ ] Paste: `node scripts/press_key.js --key "Control+V"`
- [ ] Save: `node scripts/press_key.js --key "Control+S"`
- [ ] Verify save: `node scripts/wait_for.js --text "Saved" --timeout 5000`
**Expected Output:**
Keyboard shortcuts execute correctly, content manipulated and saved.
### Workflow: Hover Tooltips and Menus
Interact with hover-triggered UI elements:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/dashboard`
- [ ] Get elements: `node scripts/take_snapshot.js`
- [ ] Hover over help icon: `node scripts/hover.js --uid icon_help_abc`
- [ ] Wait for tooltip: `node scripts/wait_for.js --text "Click for help" --timeout 2000`
- [ ] Capture tooltip: `node scripts/take_screenshot.js --filePath tooltip.png`
- [ ] Hover over menu: `node scripts/hover.js --uid menu_trigger_xyz`
- [ ] Wait for dropdown: `node scripts/wait_for.js --text "Settings" --timeout 2000`
- [ ] Click menu item: `node scripts/click.js --uid menu_item_settings`
**Expected Output:**
Tooltips and dropdowns appear on hover, menu items clickable.
## Common Patterns
### Pattern: Always Snapshot Before Interaction
Get fresh UIDs for every interaction:
```bash
# 1. Navigate to page
node scripts/new_page.js --url https://example.com/form
# 2. Wait for page load
node scripts/wait_for.js --text "Submit" --timeout 5000
# 3. Get current element UIDs
node scripts/take_snapshot.js
# 4. Use UIDs from snapshot output
node scripts/fill.js --uid <uid-from-snapshot> --value "data"
```
### Pattern: Form Validation Handling
Handle form validation errors:
```bash
# 1. Fill form
node scripts/fill.js --uid input_email --value "invalid-email"
# 2. Submit
node scripts/click.js --uid button_submit
# 3. Check for error message
node scripts/wait_for.js --text "Invalid email" --timeout 3000
# 4. Correct the input
node scripts/fill.js --uid input_email --value "valid@example.com"
# 5. Resubmit
node scripts/click.js --uid button_submit
```
### Pattern: Wait After Each Interaction
Ensure UI updates before next action:
```bash
# 1. Click button
node scripts/click.js --uid button_load_more
# 2. Wait for new content
node scripts/wait_for.js --text "Showing 20 items" --timeout 5000
# 3. Now interact with new elements
node scripts/take_snapshot.js
```
## Troubleshooting
**Problem:** Element UID not found
**Solution:** UIDs are dynamic. Always take a fresh snapshot before interaction. Don't reuse old UIDs.
**Problem:** Click doesn't trigger action
**Solution:**
- Ensure element is visible and clickable (not hidden)
- Try waiting for page to fully load first with `wait_for.js`
- Check if element requires hover first: use `hover.js` then `click.js`
**Problem:** Fill doesn't work on input
**Solution:**
- Verify the element is an input/textarea/select
- For some custom components, use `click.js` to focus, then `press_key.js` to type
- Check if page has JavaScript that prevents fill
**Problem:** File upload fails
**Solution:**
- Use absolute file paths (not relative)
- Verify file exists at the specified path
- Use forward slashes in paths: `/Users/username/file.pdf`
**Problem:** Drag and drop doesn't work
**Solution:**
- Ensure both UIDs are valid and current
- Some drag implementations require specific timing - add `wait_for.js` between actions
- Verify dropzone accepts the dragged element type

View File

@@ -0,0 +1,326 @@
# Inspection & Debugging Workflows
Monitor and debug web applications using snapshots, screenshots, console logs, and network requests.
## Tools in This Group
### take_snapshot
Captures text-based page structure from the accessibility tree with element UIDs.
**Optional:** `--verbose [true|false]`, `--filePath FILEPATH`
```bash
# Console output
node scripts/take_snapshot.js
# Verbose mode (more details)
node scripts/take_snapshot.js --verbose true
# Save to file
node scripts/take_snapshot.js --filePath snapshot.txt
```
**Output Example:**
```
Page: https://example.com
Title: Example Domain
button "Submit" [uid: button_submit_abc123]
input "Email" [uid: input_email_def456]
link "About" [uid: link_about_ghi789]
```
### take_screenshot
Captures visual screenshot of the page or specific element.
**Optional:** `--format [png|jpeg]`, `--quality 0-100`, `--uid UID`, `--fullPage [true|false]`, `--filePath FILEPATH`
```bash
# Full page screenshot
node scripts/take_screenshot.js --format png --fullPage true --filePath page.png
# Element screenshot
node scripts/take_screenshot.js --uid element_abc123 --filePath element.png
# Compressed JPEG
node scripts/take_screenshot.js --format jpeg --quality 80 --filePath page.jpg
```
### list_console_messages
Lists console logs, warnings, and errors from the current page.
**Optional:** `--pageSize SIZE`, `--pageIdx INDEX`, `--types [log,warn,error,info]`, `--includePreservedMessages [true|false]`
```bash
# All messages
node scripts/list_console_messages.js
# Only errors
node scripts/list_console_messages.js --types error
# Paginated results
node scripts/list_console_messages.js --pageSize 10 --pageIdx 0
```
### get_console_message
Retrieves a specific console message by ID.
**Required:** `--msgid MESSAGE_ID`
```bash
node scripts/get_console_message.js --msgid msg_abc123
```
### list_network_requests
Lists network requests made by the current page.
**Optional:** `--pageSize SIZE`, `--pageIdx INDEX`, `--resourceTypes [fetch,xhr,document,script,stylesheet]`, `--includePreservedRequests [true|false]`
```bash
# All requests
node scripts/list_network_requests.js
# Only API calls
node scripts/list_network_requests.js --resourceTypes fetch,xhr
# Paginated results
node scripts/list_network_requests.js --pageSize 20 --pageIdx 0
```
### get_network_request
Retrieves details of a specific network request.
**Optional:** `--reqid REQUEST_ID`
```bash
# Get specific request
node scripts/get_network_request.js --reqid req_abc123
# Get currently selected request in DevTools
node scripts/get_network_request.js
```
## Workflows
### Workflow: Debug JavaScript Errors
Identify and analyze console errors:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/app`
- [ ] Wait for page load: `node scripts/wait_for.js --text "Welcome" --timeout 10000`
- [ ] List all console messages: `node scripts/list_console_messages.js`
- [ ] Filter errors only: `node scripts/list_console_messages.js --types error`
- [ ] Get specific error details: `node scripts/get_console_message.js --msgid <error-id-from-list>`
- [ ] Take screenshot of error state: `node scripts/take_screenshot.js --filePath error_state.png`
- [ ] Take snapshot for context: `node scripts/take_snapshot.js --filePath error_snapshot.txt`
**Expected Output:**
Console errors identified, stack traces captured, visual state documented.
### Workflow: Monitor API Calls
Track network requests and responses:
- [ ] Open application: `node scripts/new_page.js --url https://example.com/dashboard`
- [ ] Trigger data load: `node scripts/click.js --uid button_load_data`
- [ ] Wait for request: `node scripts/wait_for.js --text "Data loaded" --timeout 10000`
- [ ] List API calls: `node scripts/list_network_requests.js --resourceTypes fetch,xhr`
- [ ] Get specific request: `node scripts/get_network_request.js --reqid <request-id>`
- [ ] Verify response data in output
- [ ] Save network log: `node scripts/list_network_requests.js > network_log.txt`
**Expected Output:**
All API calls logged, request/response details captured, timing information available.
### Workflow: Visual Regression Testing
Capture screenshots for comparison:
- [ ] Open baseline page: `node scripts/new_page.js --url https://example.com/page`
- [ ] Wait for load: `node scripts/wait_for.js --text "Content loaded" --timeout 5000`
- [ ] Capture full page: `node scripts/take_screenshot.js --fullPage true --filePath baseline.png`
- [ ] Capture header: `node scripts/take_screenshot.js --uid header_main --filePath header.png`
- [ ] Capture footer: `node scripts/take_screenshot.js --uid footer_main --filePath footer.png`
- [ ] Navigate to variant: `node scripts/navigate_page.js --url https://example.com/page?variant=b`
- [ ] Wait for load: `node scripts/wait_for.js --text "Content loaded" --timeout 5000`
- [ ] Capture variant: `node scripts/take_screenshot.js --fullPage true --filePath variant.png`
**Expected Output:**
Screenshots captured for visual comparison, specific components isolated.
### Workflow: Form Submission Debugging
Debug form submission issues:
- [ ] Open form: `node scripts/new_page.js --url https://example.com/contact`
- [ ] Initial snapshot: `node scripts/take_snapshot.js`
- [ ] Fill form fields: `node scripts/fill.js --uid input_name --value "Test User"`
- [ ] Continue filling: `node scripts/fill.js --uid input_email --value "test@example.com"`
- [ ] Submit form: `node scripts/click.js --uid button_submit`
- [ ] Monitor console: `node scripts/list_console_messages.js --types error,warn`
- [ ] Monitor network: `node scripts/list_network_requests.js --resourceTypes fetch,xhr`
- [ ] Get POST request: `node scripts/get_network_request.js --reqid <post-request-id>`
- [ ] Check response: Verify status code and response body in output
- [ ] Take error screenshot: `node scripts/take_screenshot.js --filePath form_error.png`
**Expected Output:**
Form submission tracked, network call details captured, errors identified.
### Workflow: Content Extraction
Extract page content and structure:
- [ ] Navigate to page: `node scripts/new_page.js --url https://example.com/article`
- [ ] Wait for content: `node scripts/wait_for.js --text "Published" --timeout 5000`
- [ ] Take detailed snapshot: `node scripts/take_snapshot.js --verbose true --filePath article_structure.txt`
- [ ] Extract main content: `node scripts/evaluate_script.js --function "() => document.querySelector('article').textContent"`
- [ ] Extract metadata: `node scripts/evaluate_script.js --function "() => ({title: document.title, author: document.querySelector('.author').textContent})"`
- [ ] Screenshot article: `node scripts/take_screenshot.js --uid article_main --filePath article.png`
- [ ] List external resources: `node scripts/list_network_requests.js --resourceTypes script,stylesheet,image`
**Expected Output:**
Page structure documented, content extracted, external dependencies identified.
### Workflow: Performance Monitoring
Monitor page performance and resource loading:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/heavy-page`
- [ ] Wait for interactive: `node scripts/wait_for.js --text "Loaded" --timeout 30000`
- [ ] List all requests: `node scripts/list_network_requests.js`
- [ ] Identify slow requests: Review timing in network list output
- [ ] Get slow request details: `node scripts/get_network_request.js --reqid <slow-request-id>`
- [ ] Check console warnings: `node scripts/list_console_messages.js --types warn`
- [ ] Take final screenshot: `node scripts/take_screenshot.js --filePath loaded_state.png`
**Expected Output:**
Resource loading times captured, slow requests identified, console warnings logged.
### Workflow: Multi-Step User Flow Debugging
Debug complex user interactions:
- [ ] Start flow: `node scripts/new_page.js --url https://example.com/checkout`
- [ ] **Step 1: Cart**
- [ ] Snapshot: `node scripts/take_snapshot.js --filePath step1_snapshot.txt`
- [ ] Screenshot: `node scripts/take_screenshot.js --filePath step1_cart.png`
- [ ] Console: `node scripts/list_console_messages.js > step1_console.txt`
- [ ] Network: `node scripts/list_network_requests.js > step1_network.txt`
- [ ] Next: `node scripts/click.js --uid button_checkout`
- [ ] **Step 2: Shipping**
- [ ] Wait: `node scripts/wait_for.js --text "Shipping Information" --timeout 5000`
- [ ] Snapshot: `node scripts/take_snapshot.js --filePath step2_snapshot.txt`
- [ ] Screenshot: `node scripts/take_screenshot.js --filePath step2_shipping.png`
- [ ] Fill: `node scripts/fill_form.js --elements '[{"uid":"input_address","value":"123 Main St"}]'`
- [ ] Next: `node scripts/click.js --uid button_continue`
- [ ] **Step 3: Payment**
- [ ] Wait: `node scripts/wait_for.js --text "Payment Method" --timeout 5000`
- [ ] Snapshot: `node scripts/take_snapshot.js --filePath step3_snapshot.txt`
- [ ] Console errors: `node scripts/list_console_messages.js --types error`
- [ ] Network calls: `node scripts/list_network_requests.js --resourceTypes fetch,xhr`
**Expected Output:**
Full debugging trace of multi-step flow, each step documented with snapshot/screenshot/logs.
## Common Patterns
### Pattern: Snapshot First, Then Screenshot
Use snapshot for UIDs and structure, screenshot for visual verification:
```bash
# 1. Get structure and UIDs
node scripts/take_snapshot.js --filePath structure.txt
# 2. Get visual representation
node scripts/take_screenshot.js --filePath visual.png
# 3. Use UIDs from snapshot for interaction
node scripts/click.js --uid <uid-from-snapshot>
```
### Pattern: Filter Console by Type
Focus on specific message types:
```bash
# Errors only (most critical)
node scripts/list_console_messages.js --types error
# Errors and warnings
node scripts/list_console_messages.js --types error,warn
# Everything
node scripts/list_console_messages.js
```
### Pattern: Track API Call Sequence
Monitor API calls in order:
```bash
# 1. Before action
node scripts/list_network_requests.js > before.txt
# 2. Trigger action
node scripts/click.js --uid button_submit
# 3. After action
node scripts/list_network_requests.js > after.txt
# 4. Compare to see new requests
# (manually diff before.txt and after.txt)
```
### Pattern: Element-Specific Screenshot
Capture specific UI components:
```bash
# 1. Get element UID
node scripts/take_snapshot.js
# 2. Screenshot just that element
node scripts/take_screenshot.js --uid <element-uid> --filePath component.png
```
## Troubleshooting
**Problem:** Snapshot shows different UIDs each time
**Solution:** This is expected. UIDs are regenerated on each snapshot. Always use the most recent snapshot before interaction.
**Problem:** Screenshot is blank or black
**Solution:**
- Wait for page to fully load with `wait_for.js`
- Check if element is visible (not hidden or off-screen)
- Try full page screenshot first: `--fullPage true`
**Problem:** Console messages not showing up
**Solution:**
- Messages accumulate since last navigation
- Reload page if you need to clear: `navigate_page.js --type reload`
- Use `--includePreservedMessages true` to see older messages
**Problem:** Network requests list is empty
**Solution:**
- Requests are captured from current navigation onwards
- Navigate to page after opening it to capture requests
- Use `--includePreservedRequests true` to see older requests
**Problem:** Cannot find specific console message ID
**Solution:**
- Run `list_console_messages.js` first to get message IDs
- Message IDs are shown in the list output
- Use the exact ID from the list in `get_console_message.js`
**Problem:** Screenshot file path error
**Solution:**
- Use absolute paths: `/Users/username/screenshots/image.png`
- Use forward slashes (not backslashes)
- Ensure directory exists before saving

View File

@@ -0,0 +1,218 @@
# Page Management Workflows
Browser window and tab operations for managing multiple pages and navigation.
## Tools in This Group
### new_page
Creates a new browser page (tab).
**Required:** `--url URL`
**Optional:** `--timeout MILLISECONDS`
```bash
node scripts/new_page.js --url https://example.com --timeout 30000
```
### list_pages
Lists all open pages with their indices and URLs.
```bash
node scripts/list_pages.js
```
**Output Example:**
```
Page 0: https://example.com (selected)
Page 1: https://google.com
Page 2: https://github.com
```
### select_page
Switches the active context to a specific page by index.
**Required:** `--pageIdx INDEX`
```bash
node scripts/select_page.js --pageIdx 1
```
### navigate_page
Navigates the currently selected page to a new URL.
**Optional:** `--url URL`, `--type [navigate|reload|back|forward]`, `--ignoreCache [true|false]`, `--timeout MILLISECONDS`
```bash
# Navigate to URL
node scripts/navigate_page.js --url https://example.com/page2
# Reload page
node scripts/navigate_page.js --type reload --ignoreCache true
# Go back
node scripts/navigate_page.js --type back
```
### resize_page
Resizes the browser window to specific dimensions.
**Required:** `--width WIDTH --height HEIGHT`
```bash
node scripts/resize_page.js --width 1920 --height 1080
```
### close_page
Closes a page by its index. Cannot close the last remaining page.
**Required:** `--pageIdx INDEX`
```bash
node scripts/close_page.js --pageIdx 2
```
## Workflows
### Workflow: Open Multiple Research Tabs
Open several pages for research or comparison:
- [ ] List current pages: `node scripts/list_pages.js`
- [ ] Open first article: `node scripts/new_page.js --url https://example.com/article1`
- [ ] Open second article: `node scripts/new_page.js --url https://example.com/article2`
- [ ] Open third article: `node scripts/new_page.js --url https://example.com/article3`
- [ ] Verify all open: `node scripts/list_pages.js`
**Expected Output:**
Multiple tabs open, each with different content, ready for analysis.
### Workflow: Navigate Through Site Pages
Walk through a multi-page flow:
- [ ] Start at homepage: `node scripts/new_page.js --url https://example.com`
- [ ] Take initial snapshot: `node scripts/take_snapshot.js`
- [ ] Click "About" link: `node scripts/click.js --uid link_about_xyz`
- [ ] Wait for page load: `node scripts/wait_for.js --text "About Us" --timeout 5000`
- [ ] Go back: `node scripts/navigate_page.js --type back`
- [ ] Verify homepage: `node scripts/wait_for.js --text "Welcome" --timeout 5000`
- [ ] Go forward: `node scripts/navigate_page.js --type forward`
**Expected Output:**
Browser navigates through pages, back/forward works correctly.
### Workflow: Multi-Tab Data Extraction
Extract data from multiple pages simultaneously:
- [ ] Open page 1: `node scripts/new_page.js --url https://example.com/data/item1`
- [ ] Take snapshot 1: `node scripts/take_snapshot.js --filePath item1.txt`
- [ ] Open page 2: `node scripts/new_page.js --url https://example.com/data/item2`
- [ ] Take snapshot 2: `node scripts/take_snapshot.js --filePath item2.txt`
- [ ] Open page 3: `node scripts/new_page.js --url https://example.com/data/item3`
- [ ] Take snapshot 3: `node scripts/take_snapshot.js --filePath item3.txt`
- [ ] Switch to page 0: `node scripts/select_page.js --pageIdx 0`
- [ ] Extract from page 0: `node scripts/evaluate_script.js --function "() => document.querySelector('.price').textContent"`
- [ ] Switch to page 1: `node scripts/select_page.js --pageIdx 1`
- [ ] Extract from page 1: `node scripts/evaluate_script.js --function "() => document.querySelector('.price').textContent"`
**Expected Output:**
Data extracted from multiple pages, context switching successful.
### Workflow: Responsive Design Testing
Test page at different viewport sizes:
- [ ] Open test page: `node scripts/new_page.js --url https://example.com`
- [ ] Desktop view: `node scripts/resize_page.js --width 1920 --height 1080`
- [ ] Take desktop screenshot: `node scripts/take_screenshot.js --fullPage true --filePath desktop.png`
- [ ] Tablet view: `node scripts/resize_page.js --width 768 --height 1024`
- [ ] Take tablet screenshot: `node scripts/take_screenshot.js --fullPage true --filePath tablet.png`
- [ ] Mobile view: `node scripts/resize_page.js --width 375 --height 667`
- [ ] Take mobile screenshot: `node scripts/take_screenshot.js --fullPage true --filePath mobile.png`
**Expected Output:**
Screenshots captured at different viewport sizes for comparison.
### Workflow: Clean Up Tabs
Close unnecessary tabs while keeping important ones:
- [ ] List all pages: `node scripts/list_pages.js`
- [ ] Identify indices to close (e.g., pages 2, 3, 4)
- [ ] Close page 4: `node scripts/close_page.js --pageIdx 4`
- [ ] Close page 3: `node scripts/close_page.js --pageIdx 3`
- [ ] Close page 2: `node scripts/close_page.js --pageIdx 2`
- [ ] Verify remaining: `node scripts/list_pages.js`
- [ ] Switch to desired page: `node scripts/select_page.js --pageIdx 0`
**Note:** Close tabs in reverse order (highest index first) to avoid index shifting issues.
**Expected Output:**
Unwanted tabs closed, important tabs remain active.
## Common Patterns
### Pattern: Safe Page Closing
Always list pages before closing to avoid errors:
```bash
# 1. Check what's open
node scripts/list_pages.js
# 2. Close specific page (use actual index from list)
node scripts/close_page.js --pageIdx 2
# 3. Verify closure
node scripts/list_pages.js
```
### Pattern: Page Context Switching
When working with multiple pages, always select before interacting:
```bash
# 1. List to see indices
node scripts/list_pages.js
# 2. Select target page
node scripts/select_page.js --pageIdx 1
# 3. Now interact with that page
node scripts/take_snapshot.js
node scripts/click.js --uid button_xyz
```
### Pattern: Reliable Navigation
Use wait_for to ensure page loads before interaction:
```bash
# 1. Navigate
node scripts/navigate_page.js --url https://example.com/login
# 2. Wait for key element
node scripts/wait_for.js --text "Sign In" --timeout 10000
# 3. Now safe to interact
node scripts/take_snapshot.js
```
## Troubleshooting
**Problem:** "Cannot close last page" error
**Solution:** You must keep at least one page open. Open a new page before closing the last one.
**Problem:** Page index out of range
**Solution:** Always run `list_pages.js` first to see current indices. Indices shift when pages are closed.
**Problem:** Navigation timeout
**Solution:** Increase timeout value: `--timeout 60000` (60 seconds) for slow-loading pages.
**Problem:** Wrong page context
**Solution:** Use `list_pages.js` to check which page is selected (marked with "selected"). Use `select_page.js` to switch.

View File

@@ -0,0 +1,383 @@
# Performance Analysis Workflows
Advanced tools for JavaScript execution, performance tracing, device emulation, and automation utilities.
## Tools in This Group
### evaluate_script
Executes JavaScript code in the page context and returns JSON-serializable results.
**Required:** `--function FUNCTION_STRING`
**Optional:** `--args JSON_ARRAY`
```bash
# Simple extraction
node scripts/evaluate_script.js --function "() => document.title"
# With parameters
node scripts/evaluate_script.js --function "(x, y) => x + y" --args '[5, 3]'
# Complex extraction
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('h2')).map(h => h.textContent)"
```
### wait_for
Waits for specific text to appear on the page (for dynamic content loading).
**Required:** `--text TEXT`
**Optional:** `--timeout MILLISECONDS`
```bash
# Wait up to 10 seconds
node scripts/wait_for.js --text "Loading complete" --timeout 10000
# Wait for error message
node scripts/wait_for.js --text "Error" --timeout 5000
```
### handle_dialog
Handles browser dialogs (alert, confirm, prompt).
**Required:** `--action [accept|dismiss]`
**Optional:** `--promptText TEXT`
```bash
# Accept alert
node scripts/handle_dialog.js --action accept
# Dismiss confirm
node scripts/handle_dialog.js --action dismiss
# Accept prompt with text
node scripts/handle_dialog.js --action accept --promptText "User input"
```
### emulate
Emulates network conditions and CPU throttling.
**Optional:** `--networkConditions JSON`, `--cpuThrottlingRate NUMBER`
```bash
# Slow 3G network
node scripts/emulate.js --networkConditions '{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'
# 4x CPU throttling
node scripts/emulate.js --cpuThrottlingRate 4
# Both
node scripts/emulate.js --networkConditions '{"downloadThroughput":100000,"uploadThroughput":50000,"latency":100}' --cpuThrottlingRate 2
```
### performance_start_trace
Starts recording performance trace for Core Web Vitals and performance insights.
**Required:** `--reload [true|false]`, `--autoStop [true|false]`
```bash
# Start tracing with page reload
node scripts/performance_start_trace.js --reload true --autoStop false
# Start tracing without reload
node scripts/performance_start_trace.js --reload false --autoStop true
```
### performance_stop_trace
Stops the active performance trace and returns results.
```bash
node scripts/performance_stop_trace.js
```
**Output includes:**
- Core Web Vitals: LCP, FID, CLS scores
- Performance insights and recommendations
- Insight set IDs for detailed analysis
### performance_analyze_insight
Gets detailed information about a specific performance insight.
**Required:** `--insightSetId SET_ID`, `--insightName INSIGHT_NAME`
```bash
node scripts/performance_analyze_insight.js --insightSetId set_abc123 --insightName LargestContentfulPaint
```
## Workflows
### Workflow: Extract Structured Data
Scrape data from pages using JavaScript:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/products`
- [ ] Wait for load: `node scripts/wait_for.js --text "Products" --timeout 10000`
- [ ] Extract product titles:
```bash
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.product-title')).map(el => el.textContent)"
```
- [ ] Extract product prices:
```bash
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.product-price')).map(el => el.textContent)"
```
- [ ] Extract complete product data:
```bash
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.product')).map(p => ({title: p.querySelector('.title').textContent, price: p.querySelector('.price').textContent, id: p.dataset.id}))"
```
**Expected Output:**
Structured JSON data extracted from page, ready for processing.
### Workflow: Comprehensive Performance Analysis
Measure page performance and Core Web Vitals:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/landing`
- [ ] Start trace with reload: `node scripts/performance_start_trace.js --reload true --autoStop false`
- [ ] Wait for page load: `node scripts/wait_for.js --text "Get Started" --timeout 20000`
- [ ] Interact with page: `node scripts/click.js --uid button_cta`
- [ ] Wait for interaction: `node scripts/wait_for.js --text "Form" --timeout 5000`
- [ ] Stop trace: `node scripts/performance_stop_trace.js`
- [ ] Review output for:
- LCP (Largest Contentful Paint) - should be < 2.5s
- FID (First Input Delay) - should be < 100ms
- CLS (Cumulative Layout Shift) - should be < 0.1
- Performance insights list
- [ ] Analyze specific insight: `node scripts/performance_analyze_insight.js --insightSetId <set-id> --insightName LargestContentfulPaint`
**Expected Output:**
Full performance profile, CWV scores, actionable insights for optimization.
### Workflow: Test Under Network Constraints
Simulate slow connections:
- [ ] Set up slow 3G: `node scripts/emulate.js --networkConditions '{"downloadThroughput":50000,"uploadThroughput":50000,"latency":2000}'`
- [ ] Open page: `node scripts/new_page.js --url https://example.com --timeout 60000`
- [ ] Start performance trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
- [ ] Wait for load: `node scripts/wait_for.js --text "Content" --timeout 60000`
- [ ] Stop trace: `node scripts/performance_stop_trace.js`
- [ ] Review load times: Check trace output for timing metrics
- [ ] Screenshot loaded state: `node scripts/take_screenshot.js --filePath slow_3g_loaded.png`
- [ ] Reset to fast network: `node scripts/emulate.js --networkConditions '{"downloadThroughput":10000000,"uploadThroughput":10000000,"latency":10}'`
**Expected Output:**
Page behavior under slow network documented, performance impact measured.
### Workflow: CPU Throttling Test
Test performance on low-powered devices:
- [ ] Apply 4x throttling: `node scripts/emulate.js --cpuThrottlingRate 4`
- [ ] Open app: `node scripts/new_page.js --url https://example.com/app`
- [ ] Start trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
- [ ] Interact with heavy UI: `node scripts/click.js --uid button_render_chart`
- [ ] Wait for render: `node scripts/wait_for.js --text "Chart loaded" --timeout 30000`
- [ ] Stop trace: `node scripts/performance_stop_trace.js`
- [ ] Check JavaScript execution time in trace output
- [ ] Remove throttling: `node scripts/emulate.js --cpuThrottlingRate 1`
- [ ] Repeat test for comparison
**Expected Output:**
Performance comparison between throttled and normal CPU, bottlenecks identified.
### Workflow: Handle Dynamic Content Loading
Work with lazy-loaded content:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/infinite-scroll`
- [ ] Wait for initial load: `node scripts/wait_for.js --text "Item 1" --timeout 5000`
- [ ] Scroll to bottom: `node scripts/evaluate_script.js --function "() => window.scrollTo(0, document.body.scrollHeight)"`
- [ ] Wait for more items: `node scripts/wait_for.js --text "Item 20" --timeout 10000`
- [ ] Take snapshot: `node scripts/take_snapshot.js`
- [ ] Scroll again: `node scripts/evaluate_script.js --function "() => window.scrollTo(0, document.body.scrollHeight)"`
- [ ] Wait for more: `node scripts/wait_for.js --text "Item 40" --timeout 10000`
- [ ] Extract all items:
```bash
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('.item')).length"
```
**Expected Output:**
All lazy-loaded content triggered and captured, full list extracted.
### Workflow: Automated Dialog Handling
Automate flows with browser dialogs:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/confirm-action`
- [ ] Click delete button: `node scripts/click.js --uid button_delete`
- [ ] Handle confirm dialog: `node scripts/handle_dialog.js --action accept`
- [ ] Wait for deletion: `node scripts/wait_for.js --text "Deleted successfully" --timeout 5000`
- [ ] Verify: `node scripts/take_snapshot.js`
**For prompt dialog:**
```bash
# Click button that opens prompt
node scripts/click.js --uid button_rename
# Enter new name and accept
node scripts/handle_dialog.js --action accept --promptText "New Name"
# Verify change
node scripts/wait_for.js --text "New Name" --timeout 3000
```
**Expected Output:**
Browser dialogs handled automatically, flow completes without manual intervention.
### Workflow: Custom Metrics Collection
Collect custom performance metrics:
- [ ] Open page: `node scripts/new_page.js --url https://example.com/dashboard`
- [ ] Wait for load: `node scripts/wait_for.js --text "Dashboard" --timeout 10000`
- [ ] Get page load time:
```bash
node scripts/evaluate_script.js --function "() => performance.timing.loadEventEnd - performance.timing.navigationStart"
```
- [ ] Get resource count:
```bash
node scripts/evaluate_script.js --function "() => performance.getEntriesByType('resource').length"
```
- [ ] Get memory usage (if available):
```bash
node scripts/evaluate_script.js --function "() => performance.memory ? performance.memory.usedJSHeapSize : null"
```
- [ ] Get paint timings:
```bash
node scripts/evaluate_script.js --function "() => performance.getEntriesByType('paint').map(p => ({name: p.name, time: p.startTime}))"
```
**Expected Output:**
Custom performance metrics collected via Performance API, specific to your needs.
### Workflow: A/B Test Performance Comparison
Compare performance across variants:
- [ ] **Variant A:**
- [ ] Open: `node scripts/new_page.js --url https://example.com?variant=a`
- [ ] Trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
- [ ] Wait: `node scripts/wait_for.js --text "Content" --timeout 15000`
- [ ] Stop: `node scripts/performance_stop_trace.js > variant_a_trace.txt`
- [ ] Screenshot: `node scripts/take_screenshot.js --filePath variant_a.png`
- [ ] **Variant B:**
- [ ] Navigate: `node scripts/navigate_page.js --url https://example.com?variant=b`
- [ ] Trace: `node scripts/performance_start_trace.js --reload true --autoStop false`
- [ ] Wait: `node scripts/wait_for.js --text "Content" --timeout 15000`
- [ ] Stop: `node scripts/performance_stop_trace.js > variant_b_trace.txt`
- [ ] Screenshot: `node scripts/take_screenshot.js --filePath variant_b.png`
- [ ] Compare CWV scores from both trace files
**Expected Output:**
Performance metrics for both variants, data-driven comparison for optimization.
## Common Patterns
### Pattern: Safe Script Evaluation
Always return JSON-serializable data:
```bash
# Good: Returns string
node scripts/evaluate_script.js --function "() => document.title"
# Good: Returns array of strings
node scripts/evaluate_script.js --function "() => Array.from(document.querySelectorAll('a')).map(a => a.href)"
# Bad: Returns DOM nodes (not serializable)
# node scripts/evaluate_script.js --function "() => document.querySelectorAll('a')"
```
### Pattern: Wait Before Interaction
Always wait for dynamic content:
```bash
# 1. Trigger action
node scripts/click.js --uid button_load
# 2. Wait for content
node scripts/wait_for.js --text "Loaded" --timeout 10000
# 3. Now safe to interact
node scripts/take_snapshot.js
```
### Pattern: Complete Performance Workflow
Standard performance analysis sequence:
```bash
# 1. Start tracing
node scripts/performance_start_trace.js --reload true --autoStop false
# 2. Let page load completely
node scripts/wait_for.js --text "Ready" --timeout 20000
# 3. Stop tracing
node scripts/performance_stop_trace.js
# 4. Analyze specific insights
node scripts/performance_analyze_insight.js --insightSetId <id> --insightName <name>
```
### Pattern: Emulation Reset
Reset emulation to normal after testing:
```bash
# 1. Test under constraints
node scripts/emulate.js --cpuThrottlingRate 4
# ... run tests ...
# 2. Reset to normal
node scripts/emulate.js --cpuThrottlingRate 1
```
## Troubleshooting
**Problem:** evaluate_script returns null or error
**Solution:**
- Ensure function returns JSON-serializable values (no DOM nodes, functions, or circular references)
- Use .map() to extract primitive values from DOM elements
- Check browser console for JavaScript errors: `list_console_messages.js --types error`
**Problem:** wait_for times out
**Solution:**
- Increase timeout: `--timeout 30000` (30 seconds)
- Verify text actually appears on page (check with `take_snapshot.js`)
- Text match is exact - check spelling and case
- Wait for network to finish if text appears after API call
**Problem:** Dialog not handled
**Solution:**
- Dialog must be already open when you call `handle_dialog.js`
- Trigger dialog first (e.g., click button), then immediately call `handle_dialog.js`
- Some "dialogs" are custom HTML, not browser dialogs - use `click.js` instead
**Problem:** Performance trace shows unexpected results
**Solution:**
- Ensure page fully loads before stopping trace
- Use `--reload true` for consistent initial page load measurement
- Clear browser cache if testing first-time load performance
- Disable browser extensions that might affect performance
**Problem:** Emulation not working
**Solution:**
- Emulation settings persist for the session
- To remove emulation, set back to normal values
- Network conditions JSON must be valid with all three properties
- CPU throttling rate of 1 = normal, higher = slower
**Problem:** Script evaluation with args fails
**Solution:**
- Args must be valid JSON array: `--args '[1, 2, 3]'`
- Function must accept the correct number of parameters
- Use single quotes around JSON, double quotes inside
- Example: `--function "(a, b) => a + b" --args '[5, 10]'`