Skip to main content
Glama
troubleshoot-guided-workflow-tool.tsโ€ข52.5 kB
/** * MCP Tool for guided troubleshooting workflow * Provides systematic troubleshooting with ADR/TODO alignment * Integrates with other MCP tools for comprehensive analysis * Enhanced with memory integration and intelligent decision capabilities */ import { z } from 'zod'; import { McpAdrError } from '../types/index.js'; import { MemoryEntityManager } from '../utils/memory-entity-manager.js'; // Note: Memory entity types are imported implicitly through MemoryEntityManager import { EnhancedLogger } from '../utils/enhanced-logging.js'; import { findFiles, findRelatedCode } from '../utils/file-system.js'; import { ResearchOrchestrator } from '../utils/research-orchestrator.js'; // Structured failure schema const FailureInfoSchema = z.object({ failureType: z .enum([ 'test_failure', 'deployment_failure', 'build_failure', 'runtime_error', 'performance_issue', 'security_issue', 'other', ]) .describe('Type of failure'), failureDetails: z .object({ command: z.string().optional().describe('Command that failed'), exitCode: z.number().optional().describe('Exit code of failed process'), errorMessage: z.string().describe('Primary error message'), stackTrace: z.string().optional().describe('Stack trace if available'), logOutput: z.string().optional().describe('Relevant log output'), environment: z.string().optional().describe('Environment where failure occurred'), timestamp: z.string().optional().describe('When the failure occurred'), affectedFiles: z.array(z.string()).optional().describe('Files involved in the failure'), }) .describe('Detailed failure information'), context: z .object({ recentChanges: z.string().optional().describe('Recent changes that might be related'), reproducible: z.boolean().optional().describe('Whether the failure is reproducible'), frequency: z.string().optional().describe('How often this failure occurs'), impact: z .enum(['low', 'medium', 'high', 'critical']) .optional() .describe('Impact level of the failure'), }) .optional() .describe('Additional context about the failure'), }); // Troubleshooting operation schema const TroubleshootSchema = z.object({ operation: z .enum(['analyze_failure', 'generate_test_plan', 'full_workflow']) .describe('Type of troubleshooting operation'), failure: FailureInfoSchema.optional().describe( 'Structured failure information (required for analyze_failure and generate_test_plan)' ), projectPath: z.string().optional().describe('Path to project directory'), adrDirectory: z.string().default('docs/adrs').describe('ADR directory path'), todoPath: z.string().default('TODO.md').describe('Path to TODO.md file'), }); type TroubleshootArgs = z.infer<typeof TroubleshootSchema>; type FailureInfo = z.infer<typeof FailureInfoSchema>; /** * Enhanced Troubleshooting Memory Manager with Intelligence * Handles memory persistence and intelligent decision-making for troubleshooting */ class TroubleshootingMemoryManager { private memoryManager: MemoryEntityManager; private logger: EnhancedLogger; constructor() { this.memoryManager = new MemoryEntityManager(); this.logger = new EnhancedLogger(); } async initialize(): Promise<void> { await this.memoryManager.initialize(); } /** * Store troubleshooting session as memory entity */ async storeTroubleshootingSession( failure: FailureInfo, analysisSteps: string[], effectiveness: number, resolutionTimeMinutes?: number ): Promise<void> { try { const sessionData = { failurePattern: { failureType: failure.failureType, errorSignature: this.generateErrorSignature(failure), frequency: await this.calculateFailureFrequency(failure.failureType), environments: failure.failureDetails.environment ? [failure.failureDetails.environment] : [], }, failureDetails: { command: failure.failureDetails.command, exitCode: failure.failureDetails.exitCode, errorMessage: failure.failureDetails.errorMessage, stackTrace: failure.failureDetails.stackTrace, logOutput: failure.failureDetails.logOutput, environment: failure.failureDetails.environment, timestamp: failure.failureDetails.timestamp || new Date().toISOString(), affectedFiles: failure.failureDetails.affectedFiles || [], }, analysisSteps, solutionEffectiveness: effectiveness, resolutionTimeMinutes: resolutionTimeMinutes, preventionMeasures: this.generatePreventionMeasures(failure), relatedADRs: await this.findRelatedADRs(failure), environmentContext: this.extractEnvironmentContext(failure), followUpActions: await this.determineFollowUpActions(failure, effectiveness), }; await this.memoryManager.upsertEntity({ type: 'troubleshooting_session', title: `Troubleshooting: ${failure.failureType} - ${failure.failureDetails.errorMessage.substring(0, 50)}...`, description: `Troubleshooting session for ${failure.failureType} failure in ${failure.failureDetails.environment || 'unknown environment'}`, tags: [ 'troubleshooting', failure.failureType, failure.failureDetails.environment || 'unknown-env', effectiveness > 0.7 ? 'effective-solution' : 'needs-improvement', ], sessionData, relationships: [], context: { projectPhase: 'troubleshooting', technicalStack: [], environmentalFactors: failure.failureDetails.environment ? [failure.failureDetails.environment] : [], stakeholders: [], }, accessPattern: { lastAccessed: new Date().toISOString(), accessCount: 1, accessContext: ['troubleshooting-session'], }, evolution: { origin: 'created', transformations: [ { timestamp: new Date().toISOString(), type: 'session_creation', description: 'Troubleshooting session created from failure analysis', agent: 'troubleshoot-guided-workflow-tool', }, ], }, validation: { isVerified: effectiveness > 0.5, verificationMethod: 'solution-effectiveness-score', verificationTimestamp: new Date().toISOString(), }, }); this.logger.info( `Troubleshooting session stored for ${failure.failureType}`, 'TroubleshootingMemoryManager', { failureType: failure.failureType, effectiveness, followUpActions: sessionData.followUpActions.length, } ); } catch (error) { this.logger.error( 'Failed to store troubleshooting session', 'TroubleshootingMemoryManager', error as Error ); throw error; } } /** * Analyze failure patterns and determine intelligent suggestions */ async analyzeFailurePatterns(): Promise<{ suggestADR: boolean; suggestResearch: boolean; patterns: any[]; recommendations: string[]; knowledgeGaps: any[]; }> { try { const sessions = await this.memoryManager.queryEntities({ entityTypes: ['troubleshooting_session'], limit: 100, sortBy: 'lastModified', }); // Analyze patterns across sessions const failureTypes = sessions.entities.map( (s: any) => s.sessionData.failurePattern.failureType ); const repeatedFailures = this.detectRepeatedFailures(failureTypes); const environmentalFactors = this.extractEnvironmentalFactors(sessions.entities); const knowledgeGaps = this.detectKnowledgeGaps(sessions.entities); // Decision logic for suggestions const suggestADR = repeatedFailures.length > 2 || this.detectArchitecturalGaps(sessions.entities); const suggestResearch = knowledgeGaps.length > 0; return { suggestADR, suggestResearch, patterns: repeatedFailures, recommendations: this.generateRecommendations(repeatedFailures, environmentalFactors), knowledgeGaps, }; } catch (error) { this.logger.error( 'Failed to analyze failure patterns', 'TroubleshootingMemoryManager', error as Error ); throw error; } } /** * Trigger ADR suggestion based on failure patterns */ async triggerADRSuggestion(failureContext: FailureInfo): Promise<any> { try { const { suggestAdrs } = await import('./adr-suggestion-tool.js'); return await suggestAdrs({ analysisType: 'comprehensive', enhancedMode: true, knowledgeEnhancement: true, conversationContext: { userGoals: ['Address recurring failures', 'Improve system reliability'], focusAreas: ['architecture', 'reliability', 'troubleshooting'], humanRequest: `Create ADR to address recurring ${failureContext.failureType} failures: ${failureContext.failureDetails.errorMessage}`, projectPhase: 'improvement', constraints: ['Must address root cause', 'Should prevent future occurrences'], }, }); } catch (error) { this.logger.error( 'Failed to trigger ADR suggestion', 'TroubleshootingMemoryManager', error as Error ); throw error; } } /** * Trigger research question generation for knowledge gaps */ async triggerResearchGeneration(knowledgeGaps: any[]): Promise<any> { try { const { generateResearchQuestions } = await import('./research-question-tool.js'); return await generateResearchQuestions({ analysisType: 'comprehensive', researchContext: { topic: 'Troubleshooting and System Reliability', category: 'operational_excellence', scope: 'failure_analysis', objectives: [ 'Understand root causes of recurring failures', 'Identify system reliability improvements', 'Document troubleshooting best practices', 'Develop proactive monitoring strategies', ], constraints: ['Must be actionable', 'Should be measurable'], timeline: '2-4 weeks', }, problems: knowledgeGaps.map(gap => ({ id: gap.id, description: gap.description, category: 'troubleshooting', severity: gap.severity, context: gap.context, })), knowledgeEnhancement: true, enhancedMode: true, }); } catch (error) { this.logger.error( 'Failed to trigger research generation', 'TroubleshootingMemoryManager', error as Error ); throw error; } } // Private helper methods private generateErrorSignature(failure: FailureInfo): string { const errorMsg = failure.failureDetails.errorMessage.toLowerCase(); const command = failure.failureDetails.command?.toLowerCase() || ''; return `${failure.failureType}:${command}:${errorMsg.substring(0, 100)}`; } private async calculateFailureFrequency(failureType: string): Promise<number> { try { const sessions = await this.memoryManager.queryEntities({ entityTypes: ['troubleshooting_session'], limit: 50, }); return sessions.entities.filter( (s: any) => s.sessionData.failurePattern.failureType === failureType ).length; } catch { return 1; } } private generatePreventionMeasures(failure: FailureInfo): string[] { const measures: string[] = []; switch (failure.failureType) { case 'deployment_failure': measures.push('Implement deployment health checks'); measures.push('Add environment validation scripts'); measures.push('Create deployment rollback procedures'); break; case 'test_failure': measures.push('Improve test environment consistency'); measures.push('Add test data validation'); measures.push('Implement test isolation mechanisms'); break; case 'build_failure': measures.push('Standardize build environment'); measures.push('Add dependency locking'); measures.push('Implement build reproducibility checks'); break; case 'performance_issue': measures.push('Add performance monitoring'); measures.push('Implement resource usage alerts'); measures.push('Create performance regression tests'); break; case 'security_issue': measures.push('Enhance security scanning'); measures.push('Implement security policy enforcement'); measures.push('Add vulnerability monitoring'); break; default: measures.push('Improve monitoring and alerting'); measures.push('Document troubleshooting procedures'); measures.push('Create failure response playbooks'); } return measures; } private async findRelatedADRs(_failure: FailureInfo): Promise<string[]> { // This would typically search for ADRs related to the failure context // For now, return empty array - this will be enhanced when ADR search is integrated return []; } private extractEnvironmentContext(failure: FailureInfo): Record<string, any> { return { environment: failure.failureDetails.environment, command: failure.failureDetails.command, exitCode: failure.failureDetails.exitCode, timestamp: failure.failureDetails.timestamp, reproducible: failure.context?.reproducible, frequency: failure.context?.frequency, impact: failure.context?.impact, }; } private async determineFollowUpActions( failure: FailureInfo, effectiveness: number ): Promise<any[]> { const actions = []; // Low effectiveness suggests need for research if (effectiveness < 0.7) { actions.push({ action: 'Generate research questions to improve troubleshooting approach', type: 'research_generation', priority: effectiveness < 0.5 ? 'high' : 'medium', triggered: false, reason: `Solution effectiveness (${effectiveness}) indicates knowledge gaps`, }); } // Architectural failure types suggest ADR needs const architecturalTypes = ['deployment_failure', 'performance_issue', 'security_issue']; if (architecturalTypes.includes(failure.failureType)) { actions.push({ action: 'Suggest ADR to address architectural concerns', type: 'adr_suggestion', priority: 'medium', triggered: false, reason: `${failure.failureType} suggests architectural decision needed`, }); } // Always suggest process improvement for repeated failures const frequency = await this.calculateFailureFrequency(failure.failureType); if (frequency >= 3) { actions.push({ action: 'Implement process improvements to prevent recurring failures', type: 'process_improvement', priority: 'high', triggered: false, reason: `${failure.failureType} has occurred ${frequency} times`, }); } return actions; } private detectRepeatedFailures(failureTypes: string[]): any[] { const frequency: Record<string, number> = {}; failureTypes.forEach(type => { frequency[type] = (frequency[type] || 0) + 1; }); return Object.entries(frequency) .filter(([_, count]) => count >= 3) .map(([type, count]) => ({ type, frequency: count })); } private detectArchitecturalGaps(sessions: any[]): boolean { const architecturalIndicators = ['deployment_failure', 'performance_issue', 'security_issue']; return sessions.some(session => architecturalIndicators.includes(session.sessionData.failurePattern.failureType) ); } private detectKnowledgeGaps(sessions: any[]): any[] { const patterns = sessions.filter(session => session.sessionData.solutionEffectiveness < 0.7); return patterns.map(pattern => ({ id: pattern.id, description: `Low solution effectiveness for ${pattern.sessionData.failurePattern.failureType}`, severity: pattern.sessionData.solutionEffectiveness < 0.5 ? 'high' : 'medium', context: pattern.sessionData.failurePattern.failureDetails.errorMessage, })); } private extractEnvironmentalFactors(sessions: any[]): string[] { const factors = new Set<string>(); sessions.forEach(session => { const env = session.sessionData.failurePattern.environments; if (env && Array.isArray(env)) { env.forEach(e => factors.add(e)); } }); return Array.from(factors); } private generateRecommendations( repeatedFailures: any[], environmentalFactors: string[] ): string[] { const recommendations = []; if (repeatedFailures.length > 0) { recommendations.push( `Address recurring ${repeatedFailures[0].type} failures with architectural decision` ); recommendations.push('Implement prevention measures for top failure patterns'); } if (environmentalFactors.length > 1) { recommendations.push('Standardize environments to reduce environment-specific failures'); } recommendations.push('Build knowledge base from troubleshooting sessions'); recommendations.push('Create automated monitoring for detected failure patterns'); return recommendations; } } /** * Research environment context for troubleshooting */ async function researchTroubleshootingContext( failure: FailureInfo, projectPath: string ): Promise<{ answer: string; confidence: number; sources: Array<{ type: string; found: boolean }>; environmentInsights: string[]; }> { try { const orchestrator = new ResearchOrchestrator(projectPath, 'docs/adrs'); // Build research question based on failure type let researchQuestion = `Troubleshoot ${failure.failureType} issue: Error: ${failure.failureDetails.errorMessage}`; if (failure.failureDetails.command) { researchQuestion += `\nFailed Command: ${failure.failureDetails.command}`; } if (failure.failureDetails.environment) { researchQuestion += `\nEnvironment: ${failure.failureDetails.environment}`; } researchQuestion += `\n\nProvide: 1. Similar past issues and resolutions 2. Environment state and configuration issues 3. Related ADR decisions that may affect this 4. Known deployment/infrastructure issues`; const research = await orchestrator.answerResearchQuestion(researchQuestion); const environmentInsights: string[] = []; // Analyze environment sources for insights const envSource = research.sources.find(s => s.type === 'environment'); if (envSource) { const capabilities = envSource.data?.capabilities || []; environmentInsights.push(`Environment tools available: ${capabilities.join(', ')}`); // Check for specific tools related to failure if (failure.failureType === 'deployment_failure') { const hasK8s = capabilities.includes('kubernetes'); const hasDocker = capabilities.includes('docker'); const hasPodman = capabilities.includes('podman'); if (!hasK8s && !hasDocker && !hasPodman) { environmentInsights.push('โš ๏ธ No container orchestration tools detected'); } } } // Check project files for configuration issues const projectSource = research.sources.find(s => s.type === 'project_files'); if (projectSource) { environmentInsights.push(`Project files analyzed: ${research.metadata.filesAnalyzed}`); } // Check ADRs for relevant decisions (knowledge_graph type) const adrSource = research.sources.find(s => s.type === 'knowledge_graph'); if (adrSource) { environmentInsights.push('Found related architectural decisions'); } return { answer: research.answer || 'No research results available', confidence: research.confidence, sources: research.sources.map(s => ({ type: s.type, found: true, // Sources in array are already found })), environmentInsights, }; } catch (error) { return { answer: `Research failed: ${error instanceof Error ? error.message : String(error)}`, confidence: 0, sources: [], environmentInsights: ['Research unavailable - proceeding with basic analysis'], }; } } /** * Analyze structured failure information */ async function analyzeFailure( failure: FailureInfo, projectPath: string = process.cwd() ): Promise<string> { // Step 0: Research environment and historical context const researchContext = await researchTroubleshootingContext(failure, projectPath); const report = [ '# ๐Ÿšจ Failure Analysis', '', `## Failure Type: ${failure.failureType.toUpperCase()}`, '', '## Error Details', `**Primary Error**: ${failure.failureDetails.errorMessage}`, '', ]; // Smart Code Linking - find files related to the failure let relatedCodeAnalysis = ''; try { // Create context from failure information for Smart Code Linking const failureContext = [ `Failure Type: ${failure.failureType}`, `Error Message: ${failure.failureDetails.errorMessage}`, failure.failureDetails.command ? `Failed Command: ${failure.failureDetails.command}` : '', failure.failureDetails.environment ? `Environment: ${failure.failureDetails.environment}` : '', failure.context?.recentChanges ? `Recent Changes: ${failure.context.recentChanges}` : '', ] .filter(Boolean) .join('\n'); // Find related code files using Smart Code Linking const relatedCodeResult = await findRelatedCode( 'troubleshooting-failure-analysis', failureContext, projectPath, { useAI: true, useRipgrep: true, maxFiles: 15, includeContent: false, } ); if (relatedCodeResult.relatedFiles.length > 0) { relatedCodeAnalysis = [ '', '## ๐Ÿ”— Smart Code Linking Analysis', '', `Found **${relatedCodeResult.relatedFiles.length}** files potentially related to this failure:`, '', ...relatedCodeResult.relatedFiles .slice(0, 10) .map((file, index) => `${index + 1}. **${file.path}**`), '', relatedCodeResult.relatedFiles.length > 10 ? `*Showing top 10 of ${relatedCodeResult.relatedFiles.length} related files*` : '', '', `**Analysis Confidence**: ${(relatedCodeResult.confidence * 100).toFixed(0)}%`, `**Keywords Used**: ${relatedCodeResult.keywords?.slice(0, 8).join(', ') || 'N/A'}`, '', ] .filter(Boolean) .join('\n'); } } catch (error) { // Don't fail the analysis if Smart Code Linking fails console.warn('Smart Code Linking failed for failure analysis:', error); } // Add command and exit code if available if (failure.failureDetails.command) { report.push(`**Failed Command**: \`${failure.failureDetails.command}\``); } if (failure.failureDetails.exitCode !== undefined) { report.push(`**Exit Code**: ${failure.failureDetails.exitCode}`); } if (failure.failureDetails.environment) { report.push(`**Environment**: ${failure.failureDetails.environment}`); } if (failure.failureDetails.timestamp) { report.push(`**Timestamp**: ${failure.failureDetails.timestamp}`); } report.push(''); // Add stack trace if available if (failure.failureDetails.stackTrace) { report.push('## Stack Trace'); report.push('```'); report.push(failure.failureDetails.stackTrace); report.push('```'); report.push(''); } // Add log output if available if (failure.failureDetails.logOutput) { report.push('## Log Output'); report.push('```'); report.push(failure.failureDetails.logOutput); report.push('```'); report.push(''); } // Add affected files if (failure.failureDetails.affectedFiles && failure.failureDetails.affectedFiles.length > 0) { report.push('## Affected Files'); report.push(...failure.failureDetails.affectedFiles.map(file => `- ${file}`)); report.push(''); } // Add context information if (failure.context) { if (failure.context.recentChanges) { report.push('## Recent Changes'); report.push(failure.context.recentChanges); report.push(''); } if (failure.context.impact) { report.push(`**Impact Level**: ${failure.context.impact.toUpperCase()}`); } if (failure.context.reproducible !== undefined) { report.push(`**Reproducible**: ${failure.context.reproducible ? 'Yes' : 'No'}`); } if (failure.context.frequency) { report.push(`**Frequency**: ${failure.context.frequency}`); } report.push(''); } // Recommended next steps based on failure type report.push('## ๐ŸŽฏ Recommended Test Plan'); report.push(''); switch (failure.failureType) { case 'test_failure': report.push('1. **Run specific failing tests** to isolate the issue'); report.push('2. **Check test dependencies** and setup requirements'); report.push('3. **Verify test data and fixtures** are correctly configured'); report.push('4. **Check for environmental differences** between local and CI'); break; case 'deployment_failure': report.push('1. **Verify deployment configuration** and environment variables'); report.push('2. **Check resource availability** (disk space, memory, CPU)'); report.push('3. **Validate network connectivity** and service dependencies'); report.push('4. **Review deployment logs** for detailed error information'); break; case 'build_failure': report.push('1. **Check build dependencies** and toolchain versions'); report.push('2. **Verify source code syntax** and compilation errors'); report.push('3. **Clean build cache** and rebuild from scratch'); report.push('4. **Check for missing or corrupted files**'); break; case 'runtime_error': report.push('1. **Reproduce the error** in a controlled environment'); report.push('2. **Check application logs** for detailed error traces'); report.push('3. **Verify data integrity** and input validation'); report.push('4. **Monitor system resources** during error occurrence'); break; default: report.push('1. **Gather additional diagnostic information**'); report.push('2. **Check system logs and monitoring**'); report.push('3. **Verify configuration and dependencies**'); report.push('4. **Test in isolated environment**'); } // Add research-driven context analysis report.push('## ๐Ÿ” Research-Driven Context Analysis'); report.push(''); report.push(`**Research Confidence**: ${(researchContext.confidence * 100).toFixed(1)}%`); report.push(''); report.push('### Environment & Historical Context'); report.push(researchContext.answer); report.push(''); report.push('### Sources Consulted'); researchContext.sources.forEach(s => { report.push(`- ${s.type}: ${s.found ? 'โœ… Available' : 'โŒ Not found'}`); }); report.push(''); if (researchContext.environmentInsights.length > 0) { report.push('### Environment Insights'); researchContext.environmentInsights.forEach(insight => { report.push(`- ${insight}`); }); report.push(''); } // Add Smart Code Linking analysis to the report if (relatedCodeAnalysis) { report.push(relatedCodeAnalysis); } report.push(''); report.push( '*Use `generate_test_plan` operation to get specific commands and validation steps.*' ); return report.join('\n'); } /** * Generate AI-powered test plan based on failure analysis */ async function generateTestPlan(failure: FailureInfo, args: TroubleshootArgs): Promise<string> { const { loadAIConfig, isAIExecutionEnabled, getRecommendedModel } = await import( '../config/ai-config.js' ); const aiConfig = loadAIConfig(); if (!isAIExecutionEnabled(aiConfig)) { return generateFallbackTestPlan(failure, args); } // Smart Code Linking - gather project context for better test plan generation let projectContext = ''; try { const projectPath = args.projectPath || process.cwd(); // Find files related to the failure for better context const failureContext = [ `Failure Type: ${failure.failureType}`, `Error Message: ${failure.failureDetails.errorMessage}`, failure.failureDetails.command ? `Failed Command: ${failure.failureDetails.command}` : '', failure.failureDetails.environment ? `Environment: ${failure.failureDetails.environment}` : '', ] .filter(Boolean) .join('\n'); const relatedCodeResult = await findRelatedCode( 'test-plan-generation', failureContext, projectPath, { useAI: true, useRipgrep: true, maxFiles: 8, includeContent: false, } ); if (relatedCodeResult.relatedFiles.length > 0) { projectContext = `\n\nProject Context (Smart Code Linking found ${relatedCodeResult.relatedFiles.length} related files):\n` + relatedCodeResult.relatedFiles .slice(0, 5) .map(file => `- ${file.path}`) .join('\n'); } } catch (error) { // Don't fail test plan generation if Smart Code Linking fails console.warn('Smart Code Linking failed for test plan generation:', error); } const systemPrompt = `You are an expert debugging assistant. Analyze the structured failure information and generate specific, actionable test commands. Return a JSON response with this exact structure: { "testPlan": { "summary": "Brief analysis of the failure", "priority": "high|medium|low", "testSections": [ { "title": "Test section name", "description": "What this section accomplishes", "commands": [ { "command": "actual command to run", "description": "what this command does", "expected": "what output indicates success" } ] } ], "followupInstructions": [ "What to do after running tests", "How to report results back" ] } } Be specific and contextual based on the actual failure details provided.`; const failureContext = `Failure Analysis: - Type: ${failure.failureType} - Error: ${failure.failureDetails.errorMessage} - Command: ${failure.failureDetails.command || 'N/A'} - Exit Code: ${failure.failureDetails.exitCode || 'N/A'} - Environment: ${failure.failureDetails.environment || 'N/A'} - Project Path: ${args.projectPath || '.'} ${failure.failureDetails.stackTrace ? `- Stack Trace: ${failure.failureDetails.stackTrace.substring(0, 500)}...` : ''} ${failure.context?.recentChanges ? `- Recent Changes: ${failure.context.recentChanges}` : ''}${projectContext} Generate specific test commands to diagnose and resolve this failure. Use the project context above to provide more targeted and relevant test commands.`; try { const response = await fetch(aiConfig.baseURL + '/chat/completions', { method: 'POST', headers: { Authorization: `Bearer ${aiConfig.apiKey}`, 'Content-Type': 'application/json', 'HTTP-Referer': aiConfig.siteUrl || '', 'X-Title': aiConfig.siteName || '', }, body: JSON.stringify({ model: getRecommendedModel('analysis'), messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: failureContext }, ], temperature: 0.2, max_tokens: 2000, response_format: { type: 'json_object' }, }), }); if (!response.ok) { throw new Error(`OpenRouter API error: ${response.status}`); } const result = await response.json(); const planContent = result.choices?.[0]?.message?.content; if (!planContent) { throw new Error('No test plan generated from AI'); } const aiPlan = JSON.parse(planContent); return formatAITestPlan(aiPlan.testPlan, args.projectPath || '.'); } catch { // Fallback to hardcoded templates if AI fails return generateFallbackTestPlan(failure, args); } } /** * Format AI-generated test plan into readable markdown */ function formatAITestPlan(testPlan: any, projectPath: string): string { const report = [ '# ๐Ÿงช AI-Generated Test Plan', '', `## Analysis Summary`, testPlan.summary || 'AI analysis of the failure', '', `**Priority**: ${testPlan.priority?.toUpperCase() || 'MEDIUM'}`, '', ]; if (testPlan.testSections && Array.isArray(testPlan.testSections)) { testPlan.testSections.forEach((section: any, index: number) => { report.push(`### ${index + 1}. ${section.title}`); if (section.description) { report.push(section.description); } report.push(''); if (section.commands && Array.isArray(section.commands)) { report.push('```bash'); section.commands.forEach((cmd: any) => { if (cmd.description) { report.push(`# ${cmd.description}`); } report.push(cmd.command); if (cmd.expected) { report.push(`# Expected: ${cmd.expected}`); } report.push(''); }); report.push('```'); report.push(''); } }); } report.push('## ๐Ÿ“‹ After Running Tests'); report.push(''); if (testPlan.followupInstructions && Array.isArray(testPlan.followupInstructions)) { testPlan.followupInstructions.forEach((instruction: string) => { report.push(`- ${instruction}`); }); } else { report.push('- Execute each command in sequence'); report.push('- Note any errors or unexpected output'); report.push('- Report results back to the MCP server'); } report.push(''); report.push('**Return results using this JSON format:**'); report.push('```json'); report.push('{'); report.push(' "operation": "process_test_results",'); report.push(' "testResults": {'); report.push(' "testCommand": "command that was executed",'); report.push(' "exitCode": 0,'); report.push(' "stdout": "standard output from command",'); report.push(' "stderr": "any error output",'); report.push(' "executionTime": 1234'); report.push(' },'); report.push(' "projectPath": "' + projectPath + '"'); report.push('}'); report.push('```'); report.push(''); report.push('*This test plan was generated by AI based on your specific failure details.*'); return report.join('\n'); } /** * Fallback test plan generation when AI is not available */ function generateFallbackTestPlan(failure: FailureInfo, args: TroubleshootArgs): string { const report = [ '# ๐Ÿงช Test Plan Generation (Fallback)', '', `## For Failure Type: ${failure.failureType.toUpperCase()}`, '', '## Specific Commands to Execute', '', ]; const projectPath = args.projectPath || '.'; switch (failure.failureType) { case 'test_failure': report.push('### 1. Run Failing Tests'); if (failure.failureDetails.command) { report.push(`\`\`\`bash`); report.push(`# Re-run the original failing command`); report.push(failure.failureDetails.command); report.push(`\`\`\``); } else { report.push(`\`\`\`bash`); report.push(`# Run tests with verbose output`); report.push(`npm test -- --verbose`); report.push(`# Or for specific test file`); report.push(`npm test -- path/to/failing/test.js`); report.push(`\`\`\``); } report.push(''); report.push('### 2. Check Test Environment'); report.push(`\`\`\`bash`); report.push(`# Check Node.js version`); report.push(`node --version`); report.push(`# Check npm version`); report.push(`npm --version`); report.push(`# Verify dependencies`); report.push(`npm ls --depth=0`); report.push(`\`\`\``); break; case 'deployment_failure': report.push('### 1. Verify Deployment Environment'); report.push(`\`\`\`bash`); report.push(`# Check available resources`); report.push(`df -h # Disk space`); report.push(`free -m # Memory`); report.push(`# Check environment variables`); report.push(`env | grep -E "(NODE_ENV|PORT|DATABASE)" # Common vars`); report.push(`\`\`\``); report.push(''); report.push('### 2. Test Deployment Components'); if (failure.failureDetails.command) { report.push(`\`\`\`bash`); report.push(`# Re-run deployment command with debug`); report.push(`${failure.failureDetails.command} --verbose`); report.push(`\`\`\``); } else { report.push(`\`\`\`bash`); report.push(`# Test basic deployment steps`); report.push(`npm run build`); report.push(`npm start --dry-run`); report.push(`\`\`\``); } break; case 'build_failure': report.push('### 1. Clean and Rebuild'); report.push(`\`\`\`bash`); report.push(`# Clean build artifacts`); report.push(`npm run clean # or rm -rf dist build`); report.push(`# Clear npm cache`); report.push(`npm cache clean --force`); report.push(`# Reinstall dependencies`); report.push(`rm -rf node_modules package-lock.json`); report.push(`npm install`); report.push(`\`\`\``); report.push(''); report.push('### 2. Build with Verbose Output'); if (failure.failureDetails.command) { report.push(`\`\`\`bash`); report.push(`# Re-run build with debug info`); report.push(`${failure.failureDetails.command} --verbose`); report.push(`\`\`\``); } else { report.push(`\`\`\`bash`); report.push(`# Standard build with verbose output`); report.push(`npm run build -- --verbose`); report.push(`\`\`\``); } break; case 'runtime_error': report.push('### 1. Reproduce in Debug Mode'); report.push(`\`\`\`bash`); report.push(`# Start application in debug mode`); report.push(`NODE_ENV=development npm start`); report.push(`# Or with debug logging`); report.push(`DEBUG=* npm start`); report.push(`\`\`\``); report.push(''); report.push('### 2. Check Application Health'); report.push(`\`\`\`bash`); report.push(`# Check if app starts successfully`); report.push(`npm start &`); report.push(`sleep 5`); report.push(`curl -I http://localhost:3000/health # Health check`); report.push(`\`\`\``); break; default: report.push('### 1. General Diagnostic Commands'); report.push(`\`\`\`bash`); report.push(`# Check project structure`); report.push(`ls -la ${projectPath}`); report.push(`# Check package.json scripts`); report.push(`cat package.json | jq .scripts`); report.push(`# Run basic health checks`); report.push(`npm run lint || echo "No lint script"`); report.push(`npm run typecheck || echo "No typecheck script"`); report.push(`\`\`\``); } report.push(''); report.push('## ๐Ÿ“‹ After Running Tests'); report.push(''); report.push('**Return the following to the MCP server:**'); report.push(''); report.push('```json'); report.push('{'); report.push(' "operation": "process_test_results",'); report.push(' "testResults": {'); report.push(' "testCommand": "command that was executed",'); report.push(' "exitCode": 0,'); report.push(' "stdout": "standard output from command",'); report.push(' "stderr": "any error output",'); report.push(' "executionTime": 1234'); report.push(' },'); report.push(' "projectPath": "' + projectPath + '"'); report.push('}'); report.push('```'); report.push(''); report.push('*AI-powered analysis unavailable - using fallback templates.*'); return report.join('\n'); } /** * Run the full troubleshooting workflow with actual tool integration */ async function runFullWorkflow(args: TroubleshootArgs): Promise<string> { const projectPath = args.projectPath || process.cwd(); const report = [ '# ๐Ÿ”ง Guided Troubleshooting Workflow', '', '## Workflow Overview', '1. โœ… Issue collected and understood', '2. ๐Ÿ”„ Baseline reality check with ADRs', '3. ๐Ÿ”„ TODO alignment analysis', '4. ๐Ÿ”„ Generate targeted questions', '5. ๐Ÿ”„ ADR validation', '6. ๐Ÿ”„ Guided recommendations', '', ]; // Smart Code Linking - discover project structure for troubleshooting context try { // Find project files for comprehensive analysis const findResult = await findFiles(projectPath, [ '**/*.{ts,js,py,yml,yaml,json,md}', '!**/node_modules/**', '!**/dist/**', '!**/build/**', ]); if (findResult.files.length > 0) { report.push('## ๐Ÿ“Š Project Discovery'); report.push(`Found **${findResult.files.length}** relevant files in project:`); // Categorize files by type for troubleshooting context const filesByType = findResult.files.reduce( (acc, file) => { const ext = file.path.split('.').pop()?.toLowerCase() || 'other'; acc[ext] = (acc[ext] || 0) + 1; return acc; }, {} as Record<string, number> ); report.push(''); Object.entries(filesByType) .sort(([, a], [, b]) => b - a) .slice(0, 8) .forEach(([ext, count]) => { report.push(`- **${ext.toUpperCase()}**: ${count} files`); }); report.push(''); // Smart Code Linking for general troubleshooting context const troubleshootingContext = [ 'troubleshooting workflow', 'error handling', 'logging', 'monitoring', 'testing', 'deployment', 'configuration', ].join(' '); const relatedCodeResult = await findRelatedCode( 'troubleshooting-workflow-context', troubleshootingContext, projectPath, { useAI: true, useRipgrep: true, maxFiles: 10, includeContent: false, } ); if (relatedCodeResult.relatedFiles.length > 0) { report.push('## ๐Ÿ”— Troubleshooting-Relevant Files'); report.push('Files that may be relevant for troubleshooting:'); report.push(''); relatedCodeResult.relatedFiles.slice(0, 8).forEach((file, index) => { report.push(`${index + 1}. **${file.path}**`); }); report.push(''); report.push(`**Analysis Confidence**: ${(relatedCodeResult.confidence * 100).toFixed(0)}%`); report.push(''); } } } catch (error) { // Don't fail the workflow if Smart Code Linking fails console.warn('Smart Code Linking failed for workflow analysis:', error); } // Legacy workflow - simplified for backwards compatibility // Legacy full workflow - provides overview of troubleshooting approach report.push('## Step 2: Baseline Reality Check'); report.push('- Use `compare_adr_progress` to check environment vs ADR expectations'); report.push(''); report.push('## Step 3: TODO Alignment Analysis'); report.push('- Use `manage_todo` to identify incomplete tasks related to issues'); report.push(''); report.push('## Step 4: Targeted Analysis'); report.push('- Use `generate_research_questions` for structured investigation'); report.push(''); report.push('## Step 5: Resolution Planning'); report.push('- Analyze ADR compliance and generate targeted solutions'); report.push(''); report.push('---'); report.push(''); report.push('## Integration Notes'); report.push(''); report.push('This workflow is designed to integrate with existing MCP tools:'); report.push('- Use `compare_adr_progress` for baseline reality check'); report.push('- Use `manage_todo` for TODO alignment analysis'); report.push('- Use `generate_research_questions` for targeted questioning'); report.push('- Results guide structured troubleshooting process'); report.push(''); report.push('*This prevents AI from getting lost during troubleshooting by maintaining*'); report.push('*alignment with documented architectural decisions and planned work.*'); return report.join('\n'); } /** * Enhanced troubleshooting workflow with memory integration and intelligent decision triggering */ export async function troubleshootGuidedWorkflowEnhanced( args: TroubleshootArgs & { enableMemoryIntegration?: boolean; solutionEffectiveness?: number; resolutionTimeMinutes?: number; } ): Promise<any> { try { const validatedArgs = TroubleshootSchema.parse(args); // Initialize memory manager if enabled let memoryManager: TroubleshootingMemoryManager | null = null; if (args.enableMemoryIntegration !== false) { memoryManager = new TroubleshootingMemoryManager(); await memoryManager.initialize(); } // Execute original troubleshooting logic const result = await troubleshootGuidedWorkflow(validatedArgs); // Enhanced memory integration and intelligent suggestions if (memoryManager && validatedArgs.failure && args.solutionEffectiveness !== undefined) { try { // Store troubleshooting session await memoryManager.storeTroubleshootingSession( validatedArgs.failure, ['Analysis completed', 'Test plan generated', 'Solution provided'], args.solutionEffectiveness, args.resolutionTimeMinutes ); // Analyze patterns and trigger intelligent suggestions const patternAnalysis = await memoryManager.analyzeFailurePatterns(); // Enhance result with intelligent suggestions const enhancedResult = { ...result, memoryIntegration: { sessionStored: true, patternAnalysis: { repeatedFailures: patternAnalysis.patterns.length, suggestionsTriggered: [], recommendations: patternAnalysis.recommendations, }, }, }; // Trigger ADR suggestion if patterns detected if (patternAnalysis.suggestADR) { try { const adrSuggestion = await memoryManager.triggerADRSuggestion(validatedArgs.failure); enhancedResult.memoryIntegration.patternAnalysis.suggestionsTriggered.push({ type: 'adr_suggestion', reason: 'Recurring failure patterns detected', patterns: patternAnalysis.patterns, suggestion: adrSuggestion, }); } catch (error) { console.warn('Failed to trigger ADR suggestion:', error); } } // Trigger research generation if knowledge gaps detected if (patternAnalysis.suggestResearch) { try { const researchSuggestion = await memoryManager.triggerResearchGeneration( patternAnalysis.knowledgeGaps ); enhancedResult.memoryIntegration.patternAnalysis.suggestionsTriggered.push({ type: 'research_suggestion', reason: 'Knowledge gaps identified in troubleshooting', gaps: patternAnalysis.knowledgeGaps, suggestion: researchSuggestion, }); } catch (error) { console.warn('Failed to trigger research generation:', error); } } // Add intelligent suggestions to the content if (enhancedResult.memoryIntegration.patternAnalysis.suggestionsTriggered.length > 0) { const originalContent = enhancedResult.content[0].text; const suggestions = enhancedResult.memoryIntegration.patternAnalysis.suggestionsTriggered; const suggestionText = [ '', '---', '', '## ๐Ÿง  Intelligent Suggestions (Memory-Enhanced)', '', 'Based on analysis of historical troubleshooting patterns:', '', ]; suggestions.forEach((suggestion: any) => { suggestionText.push( `### ${suggestion.type === 'adr_suggestion' ? '๐Ÿ“‹ ADR Suggestion' : '๐Ÿ”ฌ Research Suggestion'}` ); suggestionText.push(`**Reason**: ${suggestion.reason}`); suggestionText.push(''); if (suggestion.type === 'adr_suggestion' && suggestion.patterns) { suggestionText.push( `**Patterns Detected**: ${suggestion.patterns.map((p: any) => `${p.type} (${p.frequency}x)`).join(', ')}` ); suggestionText.push( '**Recommendation**: Create architectural decision to address recurring failures' ); } else if (suggestion.type === 'research_suggestion' && suggestion.gaps) { suggestionText.push(`**Knowledge Gaps**: ${suggestion.gaps.length} areas identified`); suggestionText.push( '**Recommendation**: Generate research questions to improve troubleshooting effectiveness' ); } suggestionText.push(''); }); if (enhancedResult.memoryIntegration.patternAnalysis.recommendations.length > 0) { suggestionText.push('### ๐Ÿ’ก Additional Recommendations'); enhancedResult.memoryIntegration.patternAnalysis.recommendations.forEach( (rec: string) => { suggestionText.push(`- ${rec}`); } ); suggestionText.push(''); } suggestionText.push( '*These suggestions are generated automatically based on troubleshooting session analysis and failure pattern recognition.*' ); enhancedResult.content[0].text = originalContent + suggestionText.join('\n'); } return enhancedResult; } catch (memoryError) { console.warn('Memory integration failed, continuing with standard workflow:', memoryError); return result; } } return result; } catch (error) { if (error instanceof z.ZodError) { throw new McpAdrError( `Invalid input: ${error.issues.map(e => e.message).join(', ')}`, 'INVALID_INPUT' ); } throw new McpAdrError( `Enhanced troubleshooting workflow failed: ${error instanceof Error ? error.message : String(error)}`, 'TROUBLESHOOTING_ERROR' ); } } /** * Main troubleshooting workflow function (original implementation) */ export async function troubleshootGuidedWorkflow(args: TroubleshootArgs): Promise<any> { try { const validatedArgs = TroubleshootSchema.parse(args); let result: string; switch (validatedArgs.operation) { case 'analyze_failure': if (!validatedArgs.failure) { throw new McpAdrError( 'Failure information is required for analyze_failure operation', 'INVALID_INPUT' ); } result = await analyzeFailure(validatedArgs.failure, validatedArgs.projectPath); break; case 'generate_test_plan': if (!validatedArgs.failure) { throw new McpAdrError( 'Failure information is required for generate_test_plan operation', 'INVALID_INPUT' ); } result = await generateTestPlan(validatedArgs.failure, validatedArgs); break; case 'full_workflow': result = await runFullWorkflow(validatedArgs); break; default: throw new McpAdrError( `Unknown operation: ${(validatedArgs as any).operation}`, 'INVALID_INPUT' ); } return { content: [ { type: 'text', text: result, }, ], }; } catch (error) { if (error instanceof z.ZodError) { throw new McpAdrError( `Invalid input: ${error.issues.map(e => e.message).join(', ')}`, 'INVALID_INPUT' ); } throw new McpAdrError( `Troubleshooting workflow failed: ${error instanceof Error ? error.message : String(error)}`, 'TROUBLESHOOTING_ERROR' ); } }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tosin2013/mcp-adr-analysis-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server