Skip to content

Chrome DevTools MCP Performance Analysis

This guide introduces how to use Chrome DevTools MCP to analyze and optimize web application performance.

Overview

Chrome DevTools MCP provides programmatic access to browser performance analysis tools, enabling the AI assistant to:

  • Automate performance testing
  • Analyze page load performance
  • Identify performance bottlenecks
  • Generate optimization suggestions

Configuration

1. Install Chrome DevTools MCP

bash
npm install -g chrome-devtools-mcp-server

2. Configure ByteBuddy

json
{
  "mcpServers": {
    "chrome-devtools": {
      "command": "node",
      "args": ["chrome-devtools-mcp-server"],
      "env": {
        "CHROME_REMOTE_DEBUGGING_PORT": "9222",
        "TARGET_URL": "http://localhost:3000"
      }
    }
  }
}

3. Start Chrome Remote Debugging

bash
# Start Chrome with remote debugging enabled
google-chrome --remote-debugging-port=9222 --disable-web-security

# Or use headless mode
google-chrome --headless --remote-debugging-port=9222

Use Cases

Scenario 1: Performance Auditing

typescript
// Perform performance audit
const audit = await mcp.call("chrome.runLighthouse", {
  url: "http://localhost:3000",
  categories: ["performance", "accessibility", "best-practices"],
  settings: {
    throttling: {
      rttMs: 100,
      throughputKbps: 10000,
      cpuSlowdownMultiplier: 2,
    },
  },
});

console.log(
  `Performance Score: ${audit.lhr.categories.performance.score * 100}`,
);

Scenario 2: Network Analysis

typescript
// Analyze network requests
const networkLogs = await mcp.call("chrome.getNetworkLogs", {
  timeRange: {
    start: Date.now() - 60000,
    end: Date.now(),
  },
});

// Identify slow requests
const slowRequests = networkLogs.filter((request) => request.duration > 1000);

console.log("Slow requests:", slowRequests);

Scenario 3: Memory Analysis

typescript
// Check for memory leaks
const memorySnapshot = await mcp.call("chrome.takeHeapSnapshot", {
  includeNodeId: true,
  includeRetainedPaths: true,
});

// Analyze memory usage
const memoryAnalysis = await mcp.call("chrome.analyzeMemory", {
  snapshot: memorySnapshot,
  focusOnLeakedObjects: true,
});

Performance Optimization Strategies

1. Automated Performance Monitoring

typescript
class PerformanceMonitor {
  async auditPage(url: string) {
    const audit = await mcp.call("chrome.runLighthouse", { url });

    return {
      performance: audit.lhr.categories.performance.score,
      firstContentfulPaint:
        audit.lhr.audits["first-contentful-paint"].numericValue,
      largestContentfulPaint:
        audit.lhr.audits["largest-contentful-paint"].numericValue,
      cumulativeLayoutShift:
        audit.lhr.audits["cumulative-layout-shift"].numericValue,
    };
  }

  async generateReport(baseUrl: string, paths: string[]) {
    const results = [];

    for (const path of paths) {
      const url = `${baseUrl}${path}`;
      const metrics = await this.auditPage(url);
      results.push({ url, ...metrics });
    }

    return this.generateOptimizationSuggestions(results);
  }
}

2. Continuous Performance Monitoring

yaml
# .github/workflows/performance.yml
name: Performance Audit
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  performance-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: "18"

      - name: Install dependencies
        run: npm ci

      - name: Build application
        run: npm run build

      - name: Start application
        run: npm run start &

      - name: Wait for app to be ready
        run: sleep 30

      - name: Run performance audit
        run: |
          bytebuddy --mcp chrome-devtools --audit-performance \
            --url http://localhost:3000 \
            --output performance-report.json

      - name: Check performance threshold
        run: |
          node scripts/check-performance-threshold.js

3. Performance Regression Detection

typescript
// Performance threshold checking
const performanceThresholds = {
  performanceScore: 0.9,
  firstContentfulPaint: 1500,
  largestContentfulPaint: 2500,
  cumulativeLayoutShift: 0.1,
};

async function checkPerformanceRegression() {
  const currentMetrics = await getCurrentPerformanceMetrics();
  const baselineMetrics = await getBaselineMetrics();

  const regressions = [];

  for (const [metric, threshold] of Object.entries(performanceThresholds)) {
    const currentValue = currentMetrics[metric];
    const baselineValue = baselineMetrics[metric];

    if (currentValue < baselineValue * 0.95) {
      regressions.push({
        metric,
        current: currentValue,
        baseline: baselineValue,
        regression: baselineValue - currentValue,
      });
    }
  }

  return regressions;
}

Advanced Analysis

1. Custom Performance Metrics

typescript
// Define custom metrics
const customMetrics = {
  timeToInteractive: {
    measurement: () => {
      return new Promise((resolve) => {
        const observer = new PerformanceObserver((list) => {
          const entries = list.getEntries();
          const tti = entries.find(
            (entry) => entry.name === "time-to-interactive",
          );
          if (tti) {
            resolve(tti.startTime);
          }
        });
        observer.observe({ entryTypes: ["measure"] });
      });
    },
  },

  renderBlockingTime: {
    measurement: async () => {
      const navigation = performance.getEntriesByType("navigation")[0];
      const domContentLoaded = navigation.domContentLoadedEventStart;
      const firstPaint = performance.getEntriesByType("paint")[0].startTime;
      return domContentLoaded - firstPaint;
    },
  },
};

2. Core Web Vitals Monitoring

typescript
// Core Web Vitals monitoring
class CoreWebVitalsMonitor {
  constructor() {
    this.metrics = {};
  }

  startMonitoring() {
    // LCP
    new PerformanceObserver((list) => {
      const entries = list.getEntries();
      const lastEntry = entries[entries.length - 1];
      this.metrics.largestContentfulPaint = lastEntry.startTime;
    }).observe({ entryTypes: ["largest-contentful-paint"] });

    // CLS
    let clsValue = 0;
    new PerformanceObserver((list) => {
      for (const entry of list.getEntries()) {
        if (!entry.hadRecentInput) {
          clsValue += entry.value;
        }
      }
      this.metrics.cumulativeLayoutShift = clsValue;
    }).observe({ entryTypes: ["layout-shift"] });

    // FID (requires user interaction)
    new PerformanceObserver((list) => {
      for (const entry of list.getEntries()) {
        this.metrics.firstInputDelay = entry.processingStart - entry.startTime;
      }
    }).observe({ entryTypes: ["first-input"] });
  }

  getMetrics() {
    return this.metrics;
  }
}

Optimization Suggestion Generation

typescript
// Auto-generate optimization suggestions
class PerformanceOptimizer {
  generateOptimizationSuggestions(auditResults) {
    const suggestions = [];

    // Suggestions based on performance score
    if (auditResults.performance < 0.9) {
      suggestions.push({
        category: "Performance",
        issue: "Performance score is below 90%",
        suggestions: [
          "Optimize image resources",
          "Reduce JavaScript bundle size",
          "Enable resource compression",
        ],
      });
    }

    // Suggestions based on specific metrics
    if (auditResults.firstContentfulPaint > 1500) {
      suggestions.push({
        category: "First Contentful Paint",
        issue: `FCP is ${auditResults.firstContentfulPaint}ms (threshold: 1500ms)`,
        suggestions: [
          "Inline critical CSS",
          "Preload critical resources",
          "Optimize server response time",
        ],
      });
    }

    // Suggestions based on network requests
    if (auditResults.slowRequests.length > 0) {
      suggestions.push({
        category: "Network",
        issue: `${auditResults.slowRequests.length} slow requests detected`,
        suggestions: [
          "Implement request caching",
          "Use CDN",
          "Optimize API response time",
        ],
      });
    }

    return suggestions;
  }
}

Troubleshooting

Common Issues

Chrome Remote Debugging Cannot Connect

bash
# Check if port is open
netstat -tlnp | grep 9222

# Restart Chrome
pkill chrome
google-chrome --remote-debugging-port=9222

Performance Audit Fails

typescript
// Add retry mechanism
async function runAuditWithRetry(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await mcp.call("chrome.runLighthouse", { url });
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await new Promise((resolve) => setTimeout(resolve, 2000));
    }
  }
}

Memory Snapshot Too Large

json
{
  "chrome-devtools": {
    "env": {
      "HEAP_SNAPSHOT_COMPRESSION": "gzip",
      "MAX_SNAPSHOT_SIZE": "50MB"
    }
  }
}

With Chrome DevTools MCP, ByteBuddy can provide in-depth performance analysis and optimization suggestions, helping developers build faster web applications.