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
1,478 lines (1,323 loc) โข 111 kB
text/typescript
#!/usr/bin/env node
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
CallToolRequestSchema,
ListToolsRequestSchema,
Tool,
} from '@modelcontextprotocol/sdk/types.js';
import { chromium, Browser, Page } from 'playwright';
import { nanoid } from 'nanoid';
import { APIKeyManager, APIKeyInfo } from './utils/api-key-manager.js';
import { CloudAIService } from './utils/cloud-ai-service.js';
import { LocalDebugEngine } from './engines/local-debug-engine.js';
import { DebugSession as BaseDebugSession } from './types.js';
import { tidewave } from './utils/tidewave-integration.js';
import { AuditEngine } from './engines/audit-engine.js';
import { VersionChecker } from './utils/version-checker.js';
import { CICDIntegration } from './utils/ci-cd-integration.js';
interface DebugSession {
id: string;
sessionId: string;
browser: Browser;
page: Page;
url: string;
framework: string;
startTime: Date;
state: any;
events: any[];
}
/**
* AI Debug Local MCP Server
*
* Revolutionary local debugging with freemium cloud AI features.
*
* Architecture:
* - Runs locally (works with localhost apps)
* - Basic debugging (free tier)
* - Advanced AI analysis (paid tier with API key)
* - Compiled binary distribution (IP protection)
*/
export class AIDebugLocalMCPServer {
private server: Server;
private sessions: Map<string, DebugSession> = new Map();
private apiKeyManager: APIKeyManager;
private cloudAI: CloudAIService;
private localEngine: LocalDebugEngine;
private auditEngine: AuditEngine;
private versionChecker: VersionChecker;
private cicdIntegration: CICDIntegration;
constructor() {
this.versionChecker = new VersionChecker();
this.server = new Server(
{
name: 'ai-debug-local',
version: '1.0.0',
},
{
capabilities: {
tools: {},
},
}
);
this.apiKeyManager = new APIKeyManager();
this.cloudAI = new CloudAIService();
this.localEngine = new LocalDebugEngine();
this.auditEngine = new AuditEngine();
this.cicdIntegration = new CICDIntegration();
this.setupToolHandlers();
this.initializeServices();
}
private async initializeServices() {
// Initialize API key manager
await this.apiKeyManager.initialize();
// Set API key for cloud service if available
const apiKey = process.env.AI_DEBUG_API_KEY;
if (apiKey) {
this.cloudAI.setApiKey(apiKey);
}
}
private setupToolHandlers() {
this.server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'inject_debugging',
description: 'Inject AI debugging capabilities into a local web application. Launches a browser, navigates to your app, and injects revolutionary debugging code. Works with localhost and private applications.',
inputSchema: {
type: 'object',
properties: {
url: {
type: 'string',
description: 'URL of the web application to debug (e.g., http://localhost:3000)'
},
framework: {
type: 'string',
enum: ['auto', 'nextjs', 'remix', 'astro', 'nuxt', 'qwik', 'solidjs', 'sveltekit', 'rails', 'django', 'phoenix', 'react', 'vue', 'angular', 'svelte', 'flutter-web'],
description: 'Web framework to optimize for (auto-detect if not specified)',
default: 'auto'
},
headless: {
type: 'boolean',
description: 'Run browser in headless mode (default: false)',
default: false
}
},
required: ['url']
}
},
{
name: 'monitor_realtime',
description: 'Monitor real-time application events. FREE: Basic event collection. PREMIUM: AI-powered pattern analysis and insights.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
duration: {
type: 'number',
description: 'Monitoring duration in seconds (default: 30)',
default: 30
},
aiAnalysis: {
type: 'boolean',
description: 'Enable AI-powered analysis (requires API key)',
default: false
}
},
required: ['sessionId']
}
},
{
name: 'simulate_user_action',
description: 'Simulate user interactions in the local browser. FREE: Basic actions. PREMIUM: AI-optimized interaction patterns.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
action: {
type: 'string',
enum: ['click', 'type', 'submit', 'scroll', 'hover'],
description: 'Type of user action'
},
selector: {
type: 'string',
description: 'CSS selector for target element'
},
value: {
type: 'string',
description: 'Value for type actions'
}
},
required: ['sessionId', 'action', 'selector']
}
},
{
name: 'take_screenshot',
description: 'Capture screenshots of your local application for visual debugging.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
fullPage: {
type: 'boolean',
description: 'Capture full page (default: true)',
default: true
}
},
required: ['sessionId']
}
},
{
name: 'analyze_with_ai',
description: 'PREMIUM: Get revolutionary AI insights about your application. Requires API key.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
analysisType: {
type: 'string',
enum: ['performance', 'ux', 'accessibility', 'security', 'comprehensive'],
description: 'Type of AI analysis',
default: 'comprehensive'
}
},
required: ['sessionId']
}
},
{
name: 'get_debug_report',
description: 'Generate debugging report. FREE: Basic report. PREMIUM: AI-enhanced with insights and recommendations.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
includeAI: {
type: 'boolean',
description: 'Include AI analysis (requires API key)',
default: false
}
},
required: ['sessionId']
}
},
{
name: 'close_session',
description: 'Close debugging session and clean up browser resources.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'get_subscription_info',
description: 'Get information about AI Debug subscription and API key status.',
inputSchema: {
type: 'object',
properties: {},
additionalProperties: false
}
},
{
name: 'run_audit',
description: 'Run comprehensive audits on the web page for accessibility, performance, SEO, security, and best practices. Returns detailed scores and actionable recommendations.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
categories: {
type: 'array',
items: {
type: 'string',
enum: ['all', 'accessibility', 'performance', 'seo', 'security', 'bestPractices']
},
description: 'Audit categories to run (default: all)',
default: ['all']
}
},
required: ['sessionId']
}
},
{
name: 'mock_network',
description: 'Mock network responses to test different scenarios. Useful for testing error handling, slow responses, or specific data conditions.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
action: {
type: 'string',
enum: ['add', 'remove', 'clear', 'list'],
description: 'Mock action to perform'
},
urlPattern: {
type: 'string',
description: 'URL pattern to mock (supports * wildcards)'
},
response: {
type: 'object',
properties: {
status: {
type: 'number',
description: 'HTTP status code (default: 200)'
},
body: {
description: 'Response body (string or JSON)'
},
headers: {
type: 'object',
description: 'Response headers'
},
delay: {
type: 'number',
description: 'Delay in milliseconds before responding'
}
}
}
},
required: ['sessionId', 'action']
}
},
{
name: 'flutter_widget_tree',
description: 'Get the Flutter widget tree for debugging Flutter Web applications. Shows widget hierarchy, properties, and render objects.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'flutter_performance',
description: 'Get Flutter performance metrics including FPS, frame times, and widget build performance.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'flutter_inspect_widget',
description: 'Inspect a specific Flutter widget by ID to see its properties and state.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
widgetId: {
type: 'string',
description: 'Widget ID to inspect'
},
highlight: {
type: 'boolean',
description: 'Highlight the widget in the UI',
default: false
}
},
required: ['sessionId', 'widgetId']
}
},
{
name: 'tidewave_query',
description: 'Execute Tidewave AI-powered queries against Phoenix/Rails applications for enhanced debugging and testing. Access logs, execute SQL, trace processes, and more.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
tool: {
type: 'string',
enum: ['logs', 'eval', 'sql', 'processes', 'documentation', 'dependencies'],
description: 'Tidewave tool to execute'
},
params: {
type: 'object',
description: 'Parameters for the Tidewave tool',
additionalProperties: true
}
},
required: ['sessionId', 'tool']
}
},
{
name: 'debug_hydration',
description: 'Detect SSR/CSR hydration mismatches that cause React, Next.js, Remix, and other framework errors. Shows server vs client HTML differences.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'analyze_bundles',
description: 'Analyze JavaScript bundle sizes, loading patterns, and code coverage. Helps identify performance bottlenecks and unused code.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'track_route_changes',
description: 'Monitor SPA route changes, navigation performance, and history state. Works with any client-side router.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'detect_problems',
description: 'Automatically detect common web app problems: hydration errors, large bundles, slow routes, poor caching, and more.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'nextjs_page_info',
description: 'Get Next.js page information including rendering type (SSR/SSG/ISR), data fetching methods, and app directory usage.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
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']
}
},
{
name: 'rails_turbo_analysis',
description: 'Analyze Rails Turbo/Hotwire performance: cache hit rates, frame loading, navigation timing.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'csrf_security_check',
description: 'Check CSRF token configuration for Rails/Django apps. Detects missing tokens in forms and AJAX requests.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'stimulus_controllers',
description: 'List and analyze Stimulus controllers in Rails applications. Shows actions, targets, and potential issues.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'meta_framework_info',
description: 'Get information about detected meta-framework (Remix, Astro, Nuxt, Qwik, SolidJS, SvelteKit) including version, features, and build tool.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'remix_loader_analysis',
description: 'Analyze Remix loader performance including execution times, data sizes, and caching behavior.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'astro_islands_audit',
description: 'Audit Astro islands for hydration strategies, component usage, and performance optimization opportunities.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'nuxt_payload_analysis',
description: 'Analyze Nuxt payload size, hydration state, and server-side data to identify optimization opportunities.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'qwik_resumability_check',
description: 'Check Qwik resumability performance including serialized state size, QRL loading, and lazy execution metrics.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'vite_hmr_monitor',
description: 'Monitor Vite HMR (Hot Module Replacement) events, update times, and errors during development.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'detect_meta_framework_issues',
description: 'Detect framework-specific issues in Remix, Astro, Nuxt, Qwik, SolidJS, or SvelteKit applications.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'init_ci_cd',
description: 'Initialize CI/CD pipeline templates with AI debugging integration. Generates GitHub Actions, GitLab CI, or other CI/CD configurations with automated testing and debugging capabilities.',
inputSchema: {
type: 'object',
properties: {
projectDir: {
type: 'string',
description: 'Project directory path'
},
provider: {
type: 'string',
enum: ['github', 'gitlab', 'circleci', 'jenkins'],
description: 'CI/CD provider',
default: 'github'
},
appUrl: {
type: 'string',
description: 'Application URL for testing',
default: 'http://localhost:3000'
},
framework: {
type: 'string',
enum: ['auto', 'react', 'vue', 'angular', 'nextjs', 'phoenix', 'rails', 'node'],
description: 'Project framework (auto-detect if not specified)',
default: 'auto'
},
tools: {
type: 'array',
items: {
type: 'string',
enum: ['debug_page', 'performance_audit', 'run_accessibility_check', 'tidewave_query']
},
description: 'AI debugging tools to include in CI/CD',
default: ['debug_page', 'performance_audit']
}
},
required: ['projectDir']
}
}
] as Tool[]
};
});
this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
try {
switch (request.params.name) {
case 'inject_debugging':
return await this.injectDebugging(request.params.arguments);
case 'monitor_realtime':
return await this.monitorRealtime(request.params.arguments);
case 'simulate_user_action':
return await this.simulateUserAction(request.params.arguments);
case 'take_screenshot':
return await this.takeScreenshot(request.params.arguments);
case 'analyze_with_ai':
return await this.analyzeWithAI(request.params.arguments);
case 'get_debug_report':
return await this.getDebugReport(request.params.arguments);
case 'close_session':
return await this.closeSession(request.params.arguments);
case 'get_subscription_info':
return await this.getSubscriptionInfo();
case 'run_audit':
return await this.runAudit(request.params.arguments);
case 'mock_network':
return await this.mockNetwork(request.params.arguments);
case 'flutter_widget_tree':
return await this.getFlutterWidgetTree(request.params.arguments);
case 'flutter_performance':
return await this.getFlutterPerformance(request.params.arguments);
case 'flutter_inspect_widget':
return await this.inspectFlutterWidget(request.params.arguments);
case 'tidewave_query':
return await this.executeTidewaveQuery(request.params.arguments);
case 'debug_hydration':
return await this.debugHydration(request.params.arguments);
case 'analyze_bundles':
return await this.analyzeBundles(request.params.arguments);
case 'track_route_changes':
return await this.trackRouteChanges(request.params.arguments);
case 'detect_problems':
return await this.detectProblems(request.params.arguments);
case 'nextjs_page_info':
return await this.getNextJSPageInfo(request.params.arguments);
case 'nextjs_image_audit':
return await this.getNextJSImageAudit(request.params.arguments);
case 'nextjs_detect_issues':
return await this.detectNextJSIssues(request.params.arguments);
case 'rails_turbo_analysis':
return await this.analyzeTurbo(request.params.arguments);
case 'csrf_security_check':
return await this.checkCSRFSecurity(request.params.arguments);
case 'stimulus_controllers':
return await this.getStimulusControllers(request.params.arguments);
case 'meta_framework_info':
return await this.getMetaFrameworkInfo(request.params.arguments);
case 'remix_loader_analysis':
return await this.analyzeRemixLoaders(request.params.arguments);
case 'astro_islands_audit':
return await this.auditAstroIslands(request.params.arguments);
case 'nuxt_payload_analysis':
return await this.analyzeNuxtPayload(request.params.arguments);
case 'qwik_resumability_check':
return await this.checkQwikResumability(request.params.arguments);
case 'vite_hmr_monitor':
return await this.monitorViteHMR(request.params.arguments);
case 'detect_meta_framework_issues':
return await this.detectMetaFrameworkIssues(request.params.arguments);
case 'init_ci_cd':
return await this.initCICD(request.params.arguments);
default:
throw new Error(`Unknown tool: ${request.params.name}`);
}
} catch (error) {
return this.createErrorResponse(error);
}
});
}
private async injectDebugging(args: any) {
const { url, framework = 'auto', headless = false } = args;
const sessionId = nanoid();
try {
// Launch local browser
const browser = await chromium.launch({
headless,
devtools: !headless
});
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle' });
// Attach local engine to page
await this.localEngine.attachToPage(page);
// Detect Tidewave capabilities
const tidewaveCapabilities = await tidewave.detectTidewave(url);
// Detect framework
let detectedFramework = framework;
if (framework === 'auto') {
detectedFramework = await this.localEngine.detectFramework(page);
// If Tidewave detected, use its framework info
if (tidewaveCapabilities) {
detectedFramework = tidewaveCapabilities.framework === 'unknown' ? detectedFramework : tidewaveCapabilities.framework;
}
}
// Inject our revolutionary debugging code (local version)
await this.localEngine.injectDebugging(page, detectedFramework);
// Capture initial state with Tidewave enhancement
let state = await this.localEngine.captureState();
if (tidewaveCapabilities) {
state = await tidewave.enhanceDebugState(url, state);
}
// Store session
const session: DebugSession = {
id: sessionId,
sessionId,
browser,
page,
url,
framework: detectedFramework,
startTime: new Date(),
state,
events: []
};
this.sessions.set(sessionId, session);
// Wait for initialization
await page.waitForTimeout(1000);
return {
content: [{
type: 'text',
text: `๐ฌ **AI Debug Session Started**
**Session ID:** \`${sessionId}\`
**URL:** ${url}
**Framework:** ${detectedFramework}
**Browser:** Local browser launched
**๐ Debugging Capabilities Injected:**
- โ
Real-time event monitoring
- โ
User interaction simulation
- โ
Visual debugging with screenshots
- โ
Framework-specific hooks (${detectedFramework})
- โ
Local performance analysis
${detectedFramework === 'flutter-web' ? `- โ
Flutter widget tree inspection
- โ
Flutter performance metrics (FPS, frame times)
- โ
Flutter widget property inspection
- โ
Flutter DevTools integration${this.localEngine.isFlutterConnected() ? ' (Connected!)' : ' (Attempting connection...)'}` : ''}
**๐ก Available Features:**
- **FREE:** Basic debugging, screenshots, event monitoring
- **PREMIUM:** AI insights, advanced analysis, recommendations
**Next Steps:**
1. Use \`monitor_realtime\` to observe behavior
2. Use \`simulate_user_action\` to test interactions
3. Use \`analyze_with_ai\` for revolutionary AI insights (Premium)
${this.apiKeyManager.hasValidKey() ?
'๐ **Premium features available** with your API key!' :
'๐ก **Upgrade:** Get API key at https://ai-debug.com/pricing for AI features'
}
**Local debugging is now active! ๐ฏ**`
}]
};
} catch (error) {
throw new Error(`Failed to inject debugging: ${error instanceof Error ? error.message : error}`);
}
}
private async monitorRealtime(args: any) {
const { sessionId, duration = 30, aiAnalysis = false } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
// Always do local monitoring
const events = await this.localEngine.monitorEvents(session.page, duration);
session.events.push(...events);
// Get console messages with smart truncation
const consoleMessages = this.localEngine.getConsoleMessages({
maxTokens: 2000 // Reserve tokens for console output
});
let analysis = this.localEngine.basicAnalysis(events);
// Premium AI analysis if requested and available
if (aiAnalysis) {
if (!this.apiKeyManager.hasValidKey()) {
return this.createPremiumFeatureResponse('AI Analysis');
}
try {
const aiInsights = await this.cloudAI.analyzeEvents(events);
analysis = { ...analysis, ...aiInsights };
} catch (error) {
// Fallback to local analysis if cloud fails
console.error('Cloud AI analysis failed, using local analysis');
}
}
return {
content: [{
type: 'text',
text: `๐ **Real-time Monitoring Complete** (${duration}s)
**Events Captured:** ${events.length}
**User Interactions:** ${events.filter(e => e.type === 'userInteraction').length}
**Network Requests:** ${events.filter(e => e.type === 'networkRequest').length}
**DOM Changes:** ${events.filter(e => e.type === 'domMutation').length}
**Errors:** ${events.filter(e => e.type === 'error').length}
**๐ Basic Analysis:**
- **Most Active Element:** ${analysis.mostActiveElement || 'N/A'}
- **Performance Score:** ${analysis.performanceScore || 'N/A'}/100
- **Error Rate:** ${analysis.errorRate || 0}%
${aiAnalysis && analysis.aiInsights ?
`**๐ง AI Insights:**\n${analysis.aiInsights.map((insight: string) => `๐ก ${insight}`).join('\n')}` :
'๐ก **Enable AI analysis** with `aiAnalysis: true` for revolutionary insights!'
}
${events.filter(e => e.type === 'error').length > 0 ?
`โ ๏ธ **Errors Detected:**\n${events.filter(e => e.type === 'error').map(e => `- ${e.data.message}`).slice(0, 3).join('\n')}` :
'โ
No errors detected'
}`
}]
};
}
private async simulateUserAction(args: any) {
const { sessionId, action, selector, value } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
const result = await this.localEngine.simulateAction(session.page, action, selector, value);
// Capture events triggered by the action
const postActionEvents = await this.localEngine.captureRecentEvents(session.page, 2000);
session.events.push(...postActionEvents);
return {
content: [{
type: 'text',
text: `๐ฏ **User Action Simulation**
**Action:** ${result.description}
**Success:** ${result.success ? 'โ
' : 'โ'}
**Duration:** ${result.duration}ms
**๐ Response Analysis:**
- **Events Triggered:** ${postActionEvents.length}
- **DOM Changes:** ${postActionEvents.filter(e => e.type === 'domMutation').length}
- **Network Activity:** ${postActionEvents.filter(e => e.type === 'networkRequest').length}
${result.success ?
'โ
Action completed successfully' :
`โ Action failed: ${result.error}`
}
${postActionEvents.length > 0 ?
`**Recent Events:**\n${postActionEvents.slice(0, 3).map(e => `- ${e.type}: ${e.data.target || e.data.url || 'N/A'}`).join('\n')}` :
'โ ๏ธ No response detected - action may have been ignored'
}`
}]
};
}
private async takeScreenshot(args: any) {
const { sessionId, fullPage = true } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
const screenshot = await session.page.screenshot({
type: 'png',
fullPage
});
return {
content: [
{
type: 'text',
text: `๐ธ **Screenshot Captured**
**Type:** ${fullPage ? 'Full page' : 'Viewport'}
**Timestamp:** ${new Date().toLocaleTimeString()}
**URL:** ${session.url}
*Visual debugging via local browser*`
},
{
type: 'image',
data: screenshot.toString('base64'),
mimeType: 'image/png'
}
]
};
}
private async analyzeWithAI(args: any) {
const { sessionId, analysisType = 'comprehensive' } = args;
if (!this.apiKeyManager.hasValidKey()) {
return this.createPremiumFeatureResponse('AI Analysis');
}
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
try {
// Get current page state
const pageState = await this.localEngine.extractPageState(session.page);
// Send to cloud AI for revolutionary analysis
const aiAnalysis = await this.cloudAI.comprehensiveAnalysis(
session.events,
pageState,
analysisType
);
await this.apiKeyManager.recordUsage('ai_analysis');
return {
content: [{
type: 'text',
text: `๐ง **Revolutionary AI Analysis** (${analysisType})
## ๐ฏ Overall Assessment
**Health Score:** ${aiAnalysis.healthScore}/100
**User Experience:** ${aiAnalysis.uxScore}/100
**Performance:** ${aiAnalysis.performanceScore}/100
## ๐ Key Findings
${aiAnalysis.findings.map((finding: any) =>
`**${finding.severity.toUpperCase()}:** ${finding.title}\n ${finding.description}`
).join('\n\n')}
## ๐ก AI Recommendations
${aiAnalysis.recommendations.map((rec: any) =>
`**${rec.priority}:** ${rec.title}\n ${rec.description}\n *Impact:* ${rec.impact}`
).join('\n\n')}
## โก Quick Fixes
${aiAnalysis.quickFixes.map((fix: string) => `- ${fix}`).join('\n')}
## ๐๏ธ Framework-Specific Insights
${aiAnalysis.frameworkInsights.map((insight: string) => `๐ก ${insight}`).join('\n')}
*Powered by revolutionary AI debugging engine*`
}]
};
} catch (error) {
throw new Error(`AI analysis failed: ${error instanceof Error ? error.message : error}`);
}
}
private async getDebugReport(args: any) {
const { sessionId, includeAI = false } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
// Always generate basic report
const basicReport = this.localEngine.generateBasicReport(session);
let aiEnhancements = null;
if (includeAI) {
if (!this.apiKeyManager.hasValidKey()) {
return this.createPremiumFeatureResponse('AI-Enhanced Reports');
}
try {
aiEnhancements = await this.cloudAI.enhanceReport(basicReport, session.events);
await this.apiKeyManager.recordUsage('ai_report');
} catch (error) {
console.error('AI enhancement failed, using basic report');
}
}
const duration = Math.round((Date.now() - session.startTime.getTime()) / 1000);
return {
content: [{
type: 'text',
text: `๐ **AI Debug Report** - Session ${sessionId}
## ๐ Session Information
**URL:** ${session.url}
**Framework:** ${session.framework}
**Duration:** ${duration}s
**Events Captured:** ${session.events.length}
## ๐ Activity Summary
**User Interactions:** ${session.events.filter(e => e.type === 'userInteraction').length}
**Network Requests:** ${session.events.filter(e => e.type === 'networkRequest').length}
**DOM Changes:** ${session.events.filter(e => e.type === 'domMutation').length}
**Console Messages:** ${session.events.filter(e => e.type === 'console').length}
**Errors:** ${session.events.filter(e => e.type === 'error').length}
## ๐ Basic Analysis
${basicReport.findings.map((finding: string) => `- ${finding}`).join('\n')}
${aiEnhancements ? `
## ๐ง AI-Enhanced Insights
**Performance Rating:** ${aiEnhancements.performanceRating}/10
**Code Quality:** ${aiEnhancements.codeQuality}/10
**User Experience:** ${aiEnhancements.uxRating}/10
**Key Recommendations:**
${aiEnhancements.recommendations.map((rec: string) => `๐ก ${rec}`).join('\n')}
**Optimization Opportunities:**
${aiEnhancements.optimizations.map((opt: string) => `โก ${opt}`).join('\n')}
` : `
๐ก **Upgrade for AI Insights:** Add \`includeAI: true\` and get revolutionary AI analysis!
๐ **Get API Key:** https://ai-debug.com/pricing
`}
## ๐ Recent Activity
${session.events.slice(-5).map(e =>
`**${new Date(e.data.timestamp).toLocaleTimeString()}** - ${e.type}`
).join('\n')}
---
*Generated by AI Debug Local MCP Server*`
}]
};
}
private async closeSession(args: any) {
const { sessionId } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
const duration = Math.round((Date.now() - session.startTime.getTime()) / 1000);
const eventCount = session.events.length;
await session.browser.close();
this.sessions.delete(sessionId);
return {
content: [{
type: 'text',
text: `๐ **Debug Session Closed**
**Session ID:** ${sessionId}
**Duration:** ${duration}s
**Events Captured:** ${eventCount}
**URL:** ${session.url}
Browser resources cleaned up successfully. โ
*Session managed locally for complete privacy*`
}]
};
}
private async getSubscriptionInfo() {
const keyStatus = this.apiKeyManager.getKeyStatus();
const usage = this.apiKeyManager.getUsageStats();
return {
content: [{
type: 'text',
text: `๐ณ **AI Debug Subscription Status**
## ๐ API Key Status
**Status:** ${keyStatus.valid ? 'โ
Valid' : 'โ Invalid/Missing'}
**Tier:** ${keyStatus.tier || 'Free'}
${keyStatus.valid ? `**Expires:** ${keyStatus.expiresAt || 'Never'}` : ''}
## ๐ Usage Statistics
**This Month:**
- **AI Analysis:** ${usage.aiAnalysis}/${usage.limits.aiAnalysis === -1 ? 'โ' : usage.limits.aiAnalysis}
- **AI Reports:** ${usage.aiReports}/${usage.limits.aiReports === -1 ? 'โ' : usage.limits.aiReports}
- **Premium Features:** ${usage.premiumFeatures}/${usage.limits.premiumFeatures === -1 ? 'โ' : usage.limits.premiumFeatures}
## ๐ Available Features
**FREE Tier:**
- โ
Local debugging and monitoring
- โ
User action simulation
- โ
Screenshots and basic reports
- โ
Framework detection
${keyStatus.valid ? `
**${keyStatus.tier?.toUpperCase()} Tier:**
- โ
Revolutionary AI analysis
- โ
AI-enhanced reports
- โ
Advanced insights and recommendations
- โ
Performance optimization suggestions
- โ
Priority support
` : `
**PREMIUM Features (Requires API Key):**
- ๐ Revolutionary AI analysis
- ๐ AI-enhanced reports
- ๐ Advanced insights and recommendations
- ๐ Performance optimization suggestions
**๐ Upgrade:** https://ai-debug.com/pricing
`}
## ๐ Quick Links
- **Dashboard:** https://ai-debug.com/dashboard
- **Documentation:** https://docs.ai-debug.com
- **Support:** https://ai-debug.com/support
*Revolutionary debugging technology for modern developers*`
}]
};
}
// Helper methods
private createPremiumFeatureResponse(featureName: string) {
return {
content: [{
type: 'text',
text: `๐ **Premium Feature: ${featureName}**
This feature requires an AI Debug API key.
**๐ Why Upgrade?**
- ๐ง Revolutionary AI analysis powered by advanced algorithms
- ๐ก Intelligent insights and recommendations
- โก Performance optimization suggestions
- ๐ง Framework-specific debugging intelligence
- ๐ Advanced reporting and analytics
**๐ณ Pricing:**
- **Pro:** $29/month - 100 AI analyses
- **Enterprise:** $299/month - Unlimited + priority support
**๐ Get API Key:** https://ai-debug.com/pricing
**โ๏ธ Setup:**
1. Purchase API key at https://ai-debug.com/dashboard
2. Set environment variable: \`export AI_DEBUG_API_KEY=your_key\`
3. Restart your MCP server
4. Enjoy revolutionary AI debugging!
*Local debugging remains completely free forever.*`
}]
};
}
private async runAudit(args: any) {
const { sessionId, categories = ['all'] } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
// Run the audit
const auditResults = await this.auditEngine.performAudit(session.page, categories);
// Calculate overall score
const scores = Object.values(auditResults).map(r => r.score);
const overallScore = Math.round(scores.reduce((a, b) => a + b, 0) / scores.length);
// Count issues by severity
const issueCounts = { error: 0, warning: 0, info: 0 };
Object.values(auditResults).forEach(result => {
result.issues.forEach(issue => {
issueCounts[issue.severity]++;
});
});
// Format the results
let reportText = `๐ **Comprehensive Audit Report**
**Overall Score:** ${overallScore}/100 ${getScoreEmoji(overallScore)}
**URL:** ${session.url}
**๐ Summary:**
- ๐ด Errors: ${issueCounts.error}
- ๐ก Warnings: ${issueCounts.warning}
- โน๏ธ Info: ${issueCounts.info}
`;
// Add results for each category
for (const [category, result] of Object.entries(auditResults)) {
reportText += `\n## ${getCategoryIcon(category)} ${formatCategoryName(category)} - ${result.score}/100\n\n`;
if (result.issues.length > 0) {
reportText += '**Issues:**\n';
result.issues.forEach(issue => {
const icon = issue.severity === 'error' ? 'โ' : issue.severity === 'warning' ? 'โ ๏ธ' : 'โน๏ธ';
reportText += `${icon} ${issue.message}\n`;
});
reportText += '\n';
}
if (result.suggestions.length > 0) {
reportText += '**Recommendations:**\n';
result.suggestions.forEach(suggestion => {
reportText += `๐ก ${suggestion}\n`;
});
}
}
// Add AI insights if premium
if (this.apiKeyManager.hasValidKey()) {
reportText += `\n## ๐ง AI Insights (Premium)
โจ Based on the audit results, consider focusing on ${getTopPriority(auditResults)}
๐ Fixing all errors could improve your score by up to ${calculatePotentialImprovement(issueCounts)}%
๐ฏ Quick wins: Start with accessibility and performance optimizations`;
} else {
reportText += `\n๐ก **Upgrade to Premium** for AI-powered insights and recommendations tailored to your specific issues.`;
}
return {
content: [{
type: 'text',
text: reportText
}]
};
function getScoreEmoji(score: number): string {
if (score >= 90) return '๐ข';
if (score >= 70) return '๐ก';
if (score >= 50) return '๐ ';
return '๐ด';
}
function getCategoryIcon(category: string): string {
const icons: Record<string, string> = {
accessibility: 'โฟ',
performance: 'โก',
seo: '๐',
security: '๐',
bestPractices: 'โ
'
};
return icons[category] || '๐';
}
function formatCategoryName(category: string): string {
const names: Record<string, string> = {
accessibility: 'Accessibility',
performance: 'Performance',
seo: 'SEO',
security: 'Security',
bestPractices: 'Best Practices'
};
return names[category] || category;
}
function getTopPriority(results: Record<string, any>): string {
let lowestScore = 100;
let priority = '';
for (const [category, result] of Object.entries(results)) {
if (result.score < lowestScore) {
lowestScore = result.score;
priority = formatCategoryName(category);
}
}
return priority || 'general improvements';
}
function calculatePotentialImprovement(counts: Record<string, number>): number {
return Math.min(counts.error * 10 + counts.warning * 5, 50);
}
}
private async mockNetwork(args: any) {
const { sessionId, action, urlPattern, response } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
switch (action) {
case 'add':
if (!urlPattern) {
throw new Error('URL pattern required for add action');
}
await this.localEngine.addNetworkMock(urlPattern, response || {});
return {
content: [{
type: 'text',
text: `๐ญ **Network Mock Added**
**Pattern:** \`${urlPattern}\`
**Status:** ${response?.status || 200}
**Delay:** ${response?.delay ? `${response.delay}ms` : 'None'}
The following URLs will be intercepted:
${this.getMatchingExamples(urlPattern)}
**Active Mocks:** ${this.localEngine.getMockedUrls().length}
๐ก **Usage Tips:**
- Test error scenarios with status codes like 404, 500
- Simulate slow networks with delay
- Mock specific JSON responses for edge cases`
}]
};
case 'remove':
if (!urlPattern) {
throw new Error('URL pattern required for remove action');
}
const removed = this.localEngine.removeNetworkMock(urlPattern);
return {
content: [{
type: 'text',
text: removed
? `โ
Removed mock for pattern: \`${urlPattern}\``
: `โ No mock found for pattern: \`${urlPattern}\``
}]
};
case 'clear':
this.localEngine.clearAllMocks();
return {
content: [{
type: 'text',
text: '๐งน All network mocks cleared'
}]
};
case 'list':
const mocks = this.localEngine.getMockedUrls();
return {
content: [{
type: 'text',
text: mocks.length > 0
? `๐ **Active Network Mocks:**\n${mocks.map(m => `- \`${m}\``).join('\n')}`
: '๐ No active network mocks'
}]
};
default:
throw new Error(`Unknown mock action: ${action}`);
}
}
private getMatchingExamples(pattern: string): string {
const examples = [];
if (pattern.includes('*')) {
if (pattern === '*') {
examples.push('- All requests');
} else if (pattern.startsWith('*/')) {
examples.push(`- Any domain with path ${pattern.substring(1)}`);
} else if (pattern.endsWith('/*')) {
examples.push(`- All paths under ${pattern.substring(0, pattern.length - 2)}`);
} else {
examples.push(`- URLs matching pattern ${pattern}`);
}
} else {
examples.push(`- Exact URL: ${pattern}`);
}
return examples.join('\n');
}
private async getFlutterWidgetTree(args: any) {
const { sessionId } = args;
const session = this.sessions.get(sessionId);
if (!session) {
throw new Error(`Debug session ${sessionId} not found`);
}
if (session.framework !== 'flutter-web') {
throw new Error('This tool only works with Flutter Web applications');
}
try {
const widgetTree = await this.localEngine.getFlutterWidgetTree();
if (!widgetTree) {