ai-debug-local-mcp
Version:
🎯 ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
192 lines • 8.2 kB
JavaScript
import { BaseToolHandler } from '../base-handler.js';
/**
* Handler for Next.js analysis tools (image audit, issue detection)
*/
export class NextJSAnalysisHandler extends BaseToolHandler {
nextjsEngine;
constructor(nextjsEngine) {
super();
this.nextjsEngine = nextjsEngine;
}
tools = [
{
name: 'nextjs_image_audit',
description: 'Audit Next.js image optimization. Detects unoptimized images, suggests next/image usage, and identifies oversized images.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'nextjs_detect_issues',
description: 'Detect Next.js specific problems: hydration errors, large RSC payloads, slow transitions, unnecessary SSR.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
}
];
async handle(toolName, args, sessions) {
const session = sessions.get(args.sessionId);
if (!session) {
throw new Error(`Debug session ${args.sessionId} not found`);
}
// Validate this is a Next.js app
if (session.framework !== 'nextjs' && session.framework !== 'next' && !(session.framework === 'react' && session.isNextJS)) {
throw new Error('This tool only works with Next.js applications');
}
switch (toolName) {
case 'nextjs_image_audit':
return this.auditImages(args, session);
case 'nextjs_detect_issues':
return this.detectIssues(args, session);
default:
throw new Error(`Unknown Next.js analysis tool: ${toolName}`);
}
}
async auditImages(args, session) {
try {
const audit = await this.nextjsEngine.auditImages(session);
let content = '🖼️ **Next.js Image Optimization Audit**\n\n';
// Summary stats
content += `**Total Images:** ${audit.totalImages}\n`;
const usingNextImage = Math.round(audit.totalImages * (audit.nextImageUsage / 100));
content += `**Using next/image:** ${usingNextImage} (${audit.nextImageUsage.toFixed(1)}%)\n\n`;
// Unoptimized images
if (audit.unoptimizedImages.length > 0) {
content += '**⚠️ Unoptimized Images:**\n';
audit.unoptimizedImages.forEach((img) => {
content += `- **${img.src}**\n`;
content += ` - Format: ${img.format}\n`;
content += ` - Displayed: ${img.displayed.width}x${img.displayed.height}\n`;
content += ` - Actual: ${img.actual.width}x${img.actual.height}\n`;
content += ` - ${img.improvement}\n`;
});
content += '\n';
}
else if (audit.totalImages > 0) {
content += '✅ All images are properly optimized!\n\n';
}
// Lazy load failures
if (audit.lazyLoadFailures && audit.lazyLoadFailures.length > 0) {
content += '**⚠️ Images with Lazy Load Issues:**\n';
audit.lazyLoadFailures.forEach((img) => {
content += `- ${img}\n`;
});
content += '\n';
}
// Recommendations
if (audit.recommendations && audit.recommendations.length > 0) {
content += '**💡 Recommendations:**\n';
audit.recommendations.forEach((rec) => {
content += `- ${rec}\n`;
});
}
return {
content: [{
type: 'text',
text: content.trim()
}]
};
}
catch (error) {
throw new Error(`Failed to audit Next.js images: ${error instanceof Error ? error.message : String(error)}`);
}
}
async detectIssues(args, session) {
try {
const issues = await this.nextjsEngine.detectIssues(session);
let content = '🔍 **Next.js Issues Detected**\n\n';
let hasIssues = false;
// Hydration errors
if (issues.hydrationErrors && issues.hydrationErrors.length > 0) {
hasIssues = true;
content += '**❌ Hydration Errors:**\n';
issues.hydrationErrors.forEach((error) => {
content += `- **Component:** ${error.component}\n`;
content += ` - Type: ${error.type}\n`;
if (error.serverText && error.clientText) {
content += ` - Server: "${error.serverText}"\n`;
content += ` - Client: "${error.clientText}"\n`;
}
if (error.stackTrace) {
content += ` - Stack: ${error.stackTrace}\n`;
}
});
content += '\n';
}
// Large RSC payloads
if (issues.largeRSCPayloads && issues.largeRSCPayloads.length > 0) {
hasIssues = true;
content += '**⚠️ Large RSC Payloads:**\n';
issues.largeRSCPayloads.forEach((payload) => {
content += `- **${payload.component}**: ${payload.size}\n`;
if (payload.recommendation) {
content += ` - ${payload.recommendation}\n`;
}
});
content += '\n';
}
// Slow transitions
if (issues.slowTransitions && issues.slowTransitions.length > 0) {
hasIssues = true;
content += '**🐌 Slow Route Transitions:**\n';
issues.slowTransitions.forEach((transition) => {
content += `- **${transition.from}** → **${transition.to}**: ${transition.duration}\n`;
if (transition.bottleneck) {
content += ` - Bottleneck: ${transition.bottleneck}\n`;
}
});
content += '\n';
}
// Unnecessary SSR
if (issues.unnecessarySSR && issues.unnecessarySSR.length > 0) {
hasIssues = true;
content += '**💡 Unnecessary SSR:**\n';
issues.unnecessarySSR.forEach((page) => {
content += `- **${page.path}**\n`;
content += ` - ${page.reason}\n`;
if (page.suggestion) {
content += ` - Suggestion: ${page.suggestion}\n`;
}
});
content += '\n';
}
if (!hasIssues) {
content += '✅ No issues detected!\n\n';
content += 'Your Next.js app appears to be running smoothly.\n';
}
else {
// Overall recommendations
if (issues.recommendations && issues.recommendations.length > 0) {
content += '**📋 Recommendations:**\n';
issues.recommendations.forEach((rec) => {
content += `- ${rec}\n`;
});
}
}
return {
content: [{
type: 'text',
text: content.trim()
}]
};
}
catch (error) {
throw new Error(`Failed to detect Next.js issues: ${error instanceof Error ? error.message : String(error)}`);
}
}
}
//# sourceMappingURL=nextjs-analysis-handler.js.map