UNPKG

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

326 lines 17.1 kB
import { BaseToolHandler } from '../base-handler.js'; import { SessionDebugFixes } from '../session-debug-fixes.js'; import * as fmt from './python-formatter-utils.js'; /** * Handler for Python backend debugging tools (test analysis, Pydantic validation, database debugging) */ export class PythonBackendHandler extends BaseToolHandler { pythonEngine; constructor(pythonEngine) { super(); this.pythonEngine = pythonEngine; } tools = [ { name: 'analyze_python_tests', description: 'Analyze Python test failures, validation errors, and test health status. Handles pytest output, unittest failures, and test structure analysis.', inputSchema: { type: 'object', properties: { testFilePath: { type: 'string', description: 'Path to Python test file or directory' }, testOutput: { type: 'string', description: 'Test execution output/logs to analyze' }, includeStackTrace: { type: 'boolean', description: 'Include detailed stack trace analysis', default: true } }, required: ['testFilePath'] } }, { name: 'validate_pydantic_models', description: 'Debug Pydantic model validation errors, field mismatches, and schema conflicts. Analyzes model definitions and validation failures.', inputSchema: { type: 'object', properties: { modelFilePath: { type: 'string', description: 'Path to Python file containing Pydantic models' }, validationError: { type: 'string', description: 'Pydantic validation error message to debug' }, testData: { type: 'string', description: 'Sample data that failed validation (JSON format)' } }, required: ['modelFilePath'] } }, { name: 'debug_database_schema', description: 'Analyze database schema issues, migration errors, and model-database mismatches. Supports SQLAlchemy, Django ORM, and raw SQL.', inputSchema: { type: 'object', properties: { schemaFilePath: { type: 'string', description: 'Path to database schema/model definitions' }, migrationError: { type: 'string', description: 'Database migration error message' }, databaseType: { type: 'string', description: 'Database type (postgresql, mysql, sqlite)', enum: ['postgresql', 'mysql', 'sqlite'] }, includeData: { type: 'boolean', description: 'Include sample data analysis', default: false } }, required: ['schemaFilePath'] } }, { name: 'analyze_backend_logic', description: 'Debug complex Python backend logic including API endpoints, data processing pipelines, and business logic errors.', inputSchema: { type: 'object', properties: { codeFilePath: { type: 'string', description: 'Path to Python backend code file' }, errorMessage: { type: 'string', description: 'Runtime error or exception message' }, logContext: { type: 'string', description: 'Application logs around the error' }, analysisType: { type: 'string', description: 'Type of analysis needed', enum: ['api_endpoints', 'data_processing', 'business_logic', 'general'], default: 'general' } }, required: ['codeFilePath'] } }, { name: 'debug_python_imports', description: 'Analyze Python import errors, module dependencies, and path resolution issues.', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to Python project root' }, importError: { type: 'string', description: 'Import error message to debug' }, includeVirtualEnv: { type: 'boolean', description: 'Include virtual environment analysis', default: true } }, required: ['projectPath'] } }, { name: 'analyze_api_integration', description: 'Debug API integration issues between frontend and Python backend, including request/response validation.', inputSchema: { type: 'object', properties: { apiEndpointPath: { type: 'string', description: 'Path to API endpoint code' }, requestData: { type: 'string', description: 'Sample request data (JSON format)' }, responseError: { type: 'string', description: 'API response error or validation failure' }, frameworkType: { type: 'string', description: 'API framework type', enum: ['fastapi', 'flask', 'django', 'starlette'], default: 'fastapi' } }, required: ['apiEndpointPath'] } } ]; async handle(toolName, args, sessions) { try { // Python backend debugging doesn't require browser sessions like web debugging // Instead, we work directly with file system and code analysis switch (toolName) { case 'analyze_python_tests': return this.analyzePythonTests(args); case 'validate_pydantic_models': return this.validatePydanticModels(args); case 'debug_database_schema': return this.debugDatabaseSchema(args); case 'analyze_backend_logic': return this.analyzeBackendLogic(args); case 'debug_python_imports': return this.debugPythonImports(args); case 'analyze_api_integration': return this.analyzeApiIntegration(args); default: throw new Error(`Unknown Python backend tool: ${toolName}`); } } catch (error) { return SessionDebugFixes.createDetailedErrorResponse(error, 'Python Backend Debug', 'backend-session'); } } async analyzePythonTests(args) { try { const analysis = await this.pythonEngine.analyzeTests(args.testFilePath, args.testOutput, args.includeStackTrace); const sections = [ '🐍 **Python Test Analysis**', '', fmt.formatKeyValue('Test File/Directory', args.testFilePath), '' ]; // Test Results Summary if (analysis.summary) { sections.push(...fmt.formatSection('**Test Results Summary:**', [ `Total Tests: ${analysis.summary.total || 'Unknown'}`, `Passed: ${analysis.summary.passed || 0}`, `Failed: ${analysis.summary.failed || 0}`, `Skipped: ${analysis.summary.skipped || 0}`, `Errors: ${analysis.summary.errors || 0}` ])); } // Failed Tests Details if (analysis.failures?.length > 0) { sections.push(...fmt.formatSection('**Failed Tests:**', analysis.failures.map((failure) => `❌ ${failure.test_name}: ${failure.error_message}`))); } // Error Analysis if (analysis.errorAnalysis?.length > 0) { sections.push(...fmt.formatSection('**Error Analysis:**', analysis.errorAnalysis.map((error) => `⚠️ ${error.type}: ${error.description}`))); } // Recommendations const recommendations = []; if (analysis.recommendations?.length > 0) { recommendations.push(...analysis.recommendations); } sections.push(...fmt.formatRecommendations(recommendations)); return this.createTextResponse(sections.join('\n').trim()); } catch (error) { throw new Error(`Failed to analyze Python tests: ${error instanceof Error ? error.message : String(error)}`); } } async validatePydanticModels(args) { try { const validation = await this.pythonEngine.validatePydanticModels(args.modelFilePath, args.validationError, args.testData); const sections = [ '📋 **Pydantic Model Validation**', '', fmt.formatKeyValue('Model File', args.modelFilePath), '' ]; // Model Analysis if (validation.models?.length > 0) { sections.push(...fmt.formatSection('**Models Found:**', validation.models.map((model) => `📄 ${model.name}: ${model.fields.length} fields`))); } // Validation Errors if (validation.errors?.length > 0) { sections.push(...fmt.formatSection('**Validation Errors:**', validation.errors.map((error) => `❌ ${error.field}: ${error.message}`))); } // Field Mismatches if (validation.fieldMismatches?.length > 0) { sections.push(...fmt.formatSection('**Field Mismatches:**', validation.fieldMismatches.map((mismatch) => `⚠️ ${mismatch.field}: Expected ${mismatch.expected}, got ${mismatch.actual}`))); } // Suggestions const suggestions = validation.suggestions || []; sections.push(...fmt.formatRecommendations(suggestions)); return this.createTextResponse(sections.join('\n').trim()); } catch (error) { throw new Error(`Failed to validate Pydantic models: ${error instanceof Error ? error.message : String(error)}`); } } async debugDatabaseSchema(args) { try { const schemaDebug = await this.pythonEngine.debugDatabaseSchema(args.schemaFilePath, args.migrationError, args.databaseType); const sections = [ '🗄️ **Database Schema Debug**', '', fmt.formatKeyValue('Schema File', args.schemaFilePath), fmt.formatKeyValue('Database Type', args.databaseType || 'Unknown'), '' ]; // Schema Analysis if (schemaDebug.tables?.length > 0) { sections.push(...fmt.formatSection('**Tables Found:**', schemaDebug.tables.map((table) => `📊 ${table.name}: ${table.columns.length} columns`))); } // Migration Issues if (schemaDebug.migrationIssues?.length > 0) { sections.push(...fmt.formatSection('**Migration Issues:**', schemaDebug.migrationIssues.map((issue) => `⚠️ ${issue.type}: ${issue.description}`))); } // Schema Inconsistencies if (schemaDebug.inconsistencies?.length > 0) { sections.push(...fmt.formatSection('**Schema Inconsistencies:**', schemaDebug.inconsistencies.map((inconsistency) => `❌ ${inconsistency.table}: ${inconsistency.issue}`))); } // Recommendations const recommendations = schemaDebug.recommendations || []; sections.push(...fmt.formatRecommendations(recommendations)); return this.createTextResponse(sections.join('\n').trim()); } catch (error) { throw new Error(`Failed to debug database schema: ${error instanceof Error ? error.message : String(error)}`); } } async analyzeBackendLogic(args) { try { const analysis = await this.pythonEngine.analyzeBackendLogic(args.codeFilePath, args.errorMessage, args.logContext, args.analysisType); const sections = [ '🔧 **Backend Logic Analysis**', '', fmt.formatKeyValue('Code File', args.codeFilePath), fmt.formatKeyValue('Analysis Type', args.analysisType || 'General'), '' ]; // Code Structure if (analysis.structure) { sections.push(...fmt.formatSection('**Code Structure:**', [ `Functions: ${analysis.structure.functions || 0}`, `Classes: ${analysis.structure.classes || 0}`, `Lines of Code: ${analysis.structure.lines || 0}` ])); } // Error Analysis if (analysis.errorAnalysis) { sections.push(...fmt.formatSection('**Error Analysis:**', [ `Error Type: ${analysis.errorAnalysis.type}`, `Root Cause: ${analysis.errorAnalysis.rootCause}`, `Location: ${analysis.errorAnalysis.location}` ])); } // Logic Issues if (analysis.logicIssues?.length > 0) { sections.push(...fmt.formatSection('**Logic Issues:**', analysis.logicIssues.map((issue) => `⚠️ ${issue.type}: ${issue.description}`))); } // Suggestions const suggestions = analysis.suggestions || []; sections.push(...fmt.formatRecommendations(suggestions)); return this.createTextResponse(sections.join('\n').trim()); } catch (error) { throw new Error(`Failed to analyze backend logic: ${error instanceof Error ? error.message : String(error)}`); } } async debugPythonImports(args) { try { const importDebug = await this.pythonEngine.debugImports(args.projectPath, args.importError); const sections = [ '📦 **Python Import Debug**', '', fmt.formatKeyValue('Project Path', args.projectPath), '' ]; // Import Analysis if (importDebug.modules?.length > 0) { sections.push(...fmt.formatSection('**Modules Found:**', importDebug.modules.map((module) => `📄 ${module.name}: ${module.path}`))); } // Import Errors if (importDebug.errors?.length > 0) { sections.push(...fmt.formatSection('**Import Errors:**', importDebug.errors.map((error) => `❌ ${error.module}: ${error.message}`))); } // Path Issues if (importDebug.pathIssues?.length > 0) { sections.push(...fmt.formatSection('**Path Issues:**', importDebug.pathIssues.map((issue) => `⚠️ ${issue.type}: ${issue.description}`))); } // Solutions const solutions = importDebug.solutions || []; sections.push(...fmt.formatRecommendations(solutions)); return this.createTextResponse(sections.join('\n').trim()); } catch (error) { throw new Error(`Failed to debug Python imports: ${error instanceof Error ? error.message : String(error)}`); } } async analyzeApiIntegration(args) { try { const apiAnalysis = await this.pythonEngine.analyzeApiIntegration(args.apiEndpointPath, args.requestData, args.responseError, args.frameworkType); const sections = [ '🔌 **API Integration Analysis**', '', fmt.formatKeyValue('Endpoint File', args.apiEndpointPath), fmt.formatKeyValue('Framework', args.frameworkType || 'Unknown'), '' ]; // Endpoint Analysis if (apiAnalysis.endpoints?.length > 0) { sections.push(...fmt.formatSection('**Endpoints Found:**', apiAnalysis.endpoints.map((endpoint) => `🔗 ${endpoint.method} ${endpoint.path}: ${endpoint.status}`))); } // Request/Response Issues if (apiAnalysis.issues?.length > 0) { sections.push(...fmt.formatSection('**Integration Issues:**', apiAnalysis.issues.map((issue) => `⚠️ ${issue.type}: ${issue.description}`))); } // Data Validation if (apiAnalysis.validation) { sections.push(...fmt.formatSection('**Data Validation:**', [ `Request Valid: ${apiAnalysis.validation.requestValid ? 'Yes' : 'No'}`, `Response Valid: ${apiAnalysis.validation.responseValid ? 'Yes' : 'No'}`, `Schema Matches: ${apiAnalysis.validation.schemaMatches ? 'Yes' : 'No'}` ])); } // Recommendations const recommendations = apiAnalysis.recommendations || []; sections.push(...fmt.formatRecommendations(recommendations)); return this.createTextResponse(sections.join('\n').trim()); } catch (error) { throw new Error(`Failed to analyze API integration: ${error instanceof Error ? error.message : String(error)}`); } } } //# sourceMappingURL=python-backend-handler.js.map