UNPKG

@danielsogl/lighthouse-mcp

Version:

A comprehensive Model Context Protocol (MCP) server that provides web performance auditing, accessibility testing, SEO analysis, security assessment, and Core Web Vitals monitoring using Google Lighthouse. Enables LLMs and AI agents to perform detailed we

147 lines (146 loc) 5.83 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getPerformanceScore = getPerformanceScore; exports.getCoreWebVitals = getCoreWebVitals; exports.compareMobileDesktop = compareMobileDesktop; exports.checkPerformanceBudget = checkPerformanceBudget; exports.getLcpOpportunities = getLcpOpportunities; const lighthouse_core_1 = require("./lighthouse-core"); const lighthouse_constants_1 = require("./lighthouse-constants"); // Helper function to get performance score only async function getPerformanceScore(url, device = "desktop") { const result = await (0, lighthouse_core_1.runLighthouseAudit)(url, ["performance"], device); return { url: result.url, device: result.device, performanceScore: result.categories.performance?.score || 0, metrics: result.metrics, fetchTime: result.fetchTime, }; } // Helper function to get Core Web Vitals async function getCoreWebVitals(url, device = "desktop", threshold) { const result = await (0, lighthouse_core_1.runLighthouseAudit)(url, ["performance"], device); const coreWebVitals = { lcp: result.metrics["largest-contentful-paint"], fcp: result.metrics["first-contentful-paint"], cls: result.metrics["cumulative-layout-shift"], tbt: result.metrics["total-blocking-time"], // TBT is used as FID proxy in lab tests }; // Check against thresholds if provided const thresholdResults = threshold ? { lcp: threshold.lcp ? (coreWebVitals.lcp?.value || 0) / 1000 <= threshold.lcp : null, fid: threshold.fid ? (coreWebVitals.tbt?.value || 0) <= threshold.fid : null, cls: threshold.cls ? (coreWebVitals.cls?.value || 0) <= threshold.cls : null, } : null; return { url: result.url, device: result.device, coreWebVitals, thresholdResults, fetchTime: result.fetchTime, }; } // Helper function to compare mobile vs desktop async function compareMobileDesktop(url, categories, throttling = false) { // Run audits sequentially to avoid Chrome port conflicts const mobileResult = await (0, lighthouse_core_1.runLighthouseAudit)(url, categories, "mobile", throttling); const desktopResult = await (0, lighthouse_core_1.runLighthouseAudit)(url, categories, "desktop", throttling); const comparison = { url: mobileResult.url, mobile: { categories: mobileResult.categories, metrics: mobileResult.metrics, }, desktop: { categories: desktopResult.categories, metrics: desktopResult.metrics, }, differences: {}, }; // Calculate differences for categories for (const [key, mobileCategory] of Object.entries(mobileResult.categories)) { const desktopCategory = desktopResult.categories[key]; if (desktopCategory) { comparison.differences[key] = { mobile: mobileCategory.score, desktop: desktopCategory.score, difference: desktopCategory.score - mobileCategory.score, }; } } return comparison; } // Helper function to check performance budget async function checkPerformanceBudget(url, device = "desktop", budget) { const result = await (0, lighthouse_core_1.runLighthouseAudit)(url, ["performance"], device); const budgetResults = { url: result.url, device: result.device, fetchTime: result.fetchTime, results: {}, overallPassed: true, }; // Check performance score if (budget.performanceScore !== undefined) { const actual = result.categories.performance?.score || 0; const passed = actual >= budget.performanceScore; budgetResults.results.performanceScore = { actual, budget: budget.performanceScore, passed, unit: "score", }; if (!passed) budgetResults.overallPassed = false; } // Check metrics using constants for (const { key, metric, unit } of lighthouse_constants_1.BUDGET_METRIC_MAPPINGS) { const budgetValue = budget[key]; if (budgetValue !== undefined) { const actual = result.metrics[metric]?.value || 0; const passed = actual <= budgetValue; budgetResults.results[key] = { actual, budget: budgetValue, passed, unit, }; if (!passed) budgetResults.overallPassed = false; } } return budgetResults; } // Helper function to get LCP optimization opportunities async function getLcpOpportunities(url, device = "desktop", threshold = lighthouse_constants_1.DEFAULTS.LCP_THRESHOLD) { const runnerResult = await (0, lighthouse_core_1.runRawLighthouseAudit)(url, ["performance"], device); const { lhr } = runnerResult; const lcpValue = (lhr.audits["largest-contentful-paint"]?.numericValue || 0) / 1000; const needsImprovement = lcpValue > threshold; const opportunities = lighthouse_constants_1.LCP_OPPORTUNITIES.map((auditId) => { const audit = lhr.audits[auditId]; if (audit && audit.score !== null && audit.score < 1) { return { id: auditId, title: audit.title, description: audit.description, score: audit.score, displayValue: audit.displayValue, numericValue: audit.numericValue, }; } return null; }).filter(Boolean); return { url: lhr.finalDisplayedUrl, device, lcpValue, threshold, needsImprovement, opportunities, fetchTime: lhr.fetchTime, }; }