@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
JavaScript
;
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,
};
}