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

138 lines (137 loc) 5.11 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.findUnusedJavaScript = findUnusedJavaScript; exports.analyzeResources = analyzeResources; exports.getSecurityAudit = getSecurityAudit; const lighthouse_core_1 = require("./lighthouse-core"); const lighthouse_constants_1 = require("./lighthouse-constants"); // Helper function to find unused JavaScript async function findUnusedJavaScript(url, device = "desktop", minBytes = lighthouse_constants_1.DEFAULTS.MIN_UNUSED_JS_BYTES) { const runnerResult = await (0, lighthouse_core_1.runRawLighthouseAudit)(url, ["performance"], device); const { lhr } = runnerResult; const unusedJsAudit = lhr.audits["unused-javascript"]; if (!unusedJsAudit || !unusedJsAudit.details) { return { url: lhr.finalDisplayedUrl, device, totalUnusedBytes: 0, items: [], fetchTime: lhr.fetchTime, }; } // Filter items by minimum bytes const items = (unusedJsAudit.details.items || []) .filter((item) => item.wastedBytes >= minBytes) .map((item) => ({ url: item.url, totalBytes: item.totalBytes, wastedBytes: item.wastedBytes, wastedPercent: Math.round((item.wastedBytes / item.totalBytes) * 100), })); const totalUnusedBytes = items.reduce((sum, item) => sum + item.wastedBytes, 0); return { url: lhr.finalDisplayedUrl, device, totalUnusedBytes, items, fetchTime: lhr.fetchTime, }; } // Helper function to categorize resource type function categorizeResourceType(item) { if (item.resourceType) { return item.resourceType.toLowerCase(); } if (item.mimeType) { const mimeType = item.mimeType; if (mimeType.startsWith("image/")) return "images"; if (mimeType.includes("javascript")) return "javascript"; if (mimeType.includes("css")) return "css"; if (mimeType.includes("font")) return "fonts"; } return "other"; } // Helper function to analyze resources async function analyzeResources(url, device = "desktop", resourceTypes, minSize = lighthouse_constants_1.DEFAULTS.MIN_RESOURCE_SIZE_KB) { const runnerResult = await (0, lighthouse_core_1.runRawLighthouseAudit)(url, ["performance"], device); const { lhr } = runnerResult; // Get resource summary from network-requests audit const networkAudit = lhr.audits["network-requests"]; if (!networkAudit || !networkAudit.details) { return { url: lhr.finalDisplayedUrl, device, resources: [], summary: {}, fetchTime: lhr.fetchTime, }; } const resources = (networkAudit.details.items || []) .map((item) => { const sizeKB = (item.transferSize || 0) / 1024; const resourceType = categorizeResourceType(item); return { url: item.url, resourceType, transferSize: item.transferSize || 0, resourceSize: item.resourceSize || 0, sizeKB: Math.round(sizeKB * 100) / 100, mimeType: item.mimeType, }; }) .filter((resource) => { if (minSize && resource.sizeKB < minSize) return false; if (resourceTypes && !resourceTypes.includes(resource.resourceType)) return false; return true; }); // Create summary by resource type const summary = resources.reduce((acc, resource) => { if (!acc[resource.resourceType]) { acc[resource.resourceType] = { count: 0, totalSize: 0 }; } acc[resource.resourceType].count++; acc[resource.resourceType].totalSize += resource.transferSize; return acc; }, {}); return { url: lhr.finalDisplayedUrl, device, resources, summary, fetchTime: lhr.fetchTime, }; } // Helper function to get security audit async function getSecurityAudit(url, device = "desktop", checks) { const runnerResult = await (0, lighthouse_core_1.runRawLighthouseAudit)(url, ["best-practices"], device); const { lhr } = runnerResult; const auditResults = lighthouse_constants_1.SECURITY_AUDITS.map((auditId) => { const audit = lhr.audits[auditId]; if (audit && (!checks || checks.some((check) => auditId.includes(check)))) { return { id: auditId, title: audit.title, description: audit.description, score: audit.score, scoreDisplayMode: audit.scoreDisplayMode, displayValue: audit.displayValue, }; } return null; }).filter(Boolean); const overallScore = auditResults.reduce((sum, audit) => sum + (audit?.score || 0), 0) / auditResults.length; return { url: lhr.finalDisplayedUrl, device, overallScore: Math.round(overallScore * 100), audits: auditResults, fetchTime: lhr.fetchTime, }; }