Skip to main content
Glama

mcp-adr-analysis-server

by tosin2013
server-context-generator.ts14.9 kB
/** * Server Context Generator * * Generates a human-readable context file that LLMs can @ reference * to instantly understand the server's state, memory, and capabilities. * * This bridges the gap between internal memory systems (JSON in /tmp) * and LLM working context by creating a markdown file that can be * @ mentioned in conversations. */ import * as fs from 'fs/promises'; import * as path from 'path'; import { KnowledgeGraphManager } from './knowledge-graph-manager.js'; import { MemoryEntityManager } from './memory-entity-manager.js'; import { ConversationMemoryManager } from './conversation-memory-manager.js'; import { loadConfig } from './config.js'; import { EnhancedLogger } from './enhanced-logging.js'; export interface ServerContextOptions { outputPath?: string; includeDetailed?: boolean; maxRecentItems?: number; } export class ServerContextGenerator { private logger: EnhancedLogger; private config: ReturnType<typeof loadConfig>; constructor() { this.logger = new EnhancedLogger(); this.config = loadConfig(); } /** * Generate the complete server context markdown file */ async generateContext( kgManager: KnowledgeGraphManager, memoryManager: MemoryEntityManager, conversationManager: ConversationMemoryManager, options: ServerContextOptions = {} ): Promise<string> { const { maxRecentItems = 5 } = options; const sections: string[] = []; // Header sections.push(this.generateHeader()); // Server Quick Reference sections.push(this.generateServerInfo()); // Memory & Knowledge Graph Status sections.push( await this.generateMemoryStatus(kgManager, memoryManager, conversationManager, maxRecentItems) ); // Analytics sections.push(await this.generateAnalytics(kgManager)); // Patterns sections.push(await this.generatePatterns(memoryManager)); // Recommendations sections.push(await this.generateRecommendations(memoryManager)); // Usage guide sections.push(this.generateUsageGuide()); // Footer sections.push(this.generateFooter()); return sections.join('\n\n---\n\n'); } /** * Write context to file */ async writeContextFile( kgManager: KnowledgeGraphManager, memoryManager: MemoryEntityManager, conversationManager: ConversationMemoryManager, filePath?: string ): Promise<void> { const outputPath = filePath || path.join(this.config.projectPath, '.mcp-server-context.md'); const content = await this.generateContext(kgManager, memoryManager, conversationManager); await fs.writeFile(outputPath, content, 'utf-8'); this.logger.info('Server context file updated', 'ServerContextGenerator', { path: outputPath, size: content.length, }); } private generateHeader(): string { return `# MCP Server Context & Memory > **Purpose**: \`@\` reference this file to give LLMs instant context about the MCP ADR Analysis Server's state, capabilities, and recent activity. > > **Auto-generated**: This file is automatically updated by the server's memory systems. > > **Last Updated**: ${new Date().toISOString()}`; } private generateServerInfo(toolList?: Array<{ name: string; description: string }>): string { // Generate tool list from actual registered tools or use default list const tools = toolList || [ { name: 'adr_suggestion', description: 'Suggest new ADRs based on context' }, { name: 'smart_score', description: 'Score code quality and architecture (0-100)' }, { name: 'deployment_readiness', description: 'Validate deployment with zero-tolerance' }, { name: 'todo_management_v2', description: 'Advanced context-aware todo tracking' }, { name: 'smart_git_push', description: 'Intelligent git operations' }, { name: 'content_masking', description: 'Protect sensitive information' }, { name: 'tool_chain_orchestrator', description: 'Coordinate multi-tool workflows' }, { name: 'environment_analysis', description: 'Analyze project environment' }, { name: 'interactive_adr_planning', description: 'Interactive ADR creation' }, { name: 'conversation_memory', description: 'Manage conversation context' }, { name: 'adr_validation', description: 'Validate ADR content and structure' }, { name: 'rule_generation', description: 'Generate architectural rules' }, { name: 'deployment_guidance', description: 'Get deployment recommendations' }, { name: 'deployment_analysis', description: 'Analyze deployment configurations' }, { name: 'perform_research', description: 'Conduct architectural research' }, { name: 'research_question', description: 'Ask research questions' }, { name: 'research_integration', description: 'Integrate research findings' }, { name: 'expand_analysis', description: 'Expand on analysis results' }, { name: 'review_existing_adrs', description: 'Review and analyze existing ADRs' }, { name: 'bootstrap_validation_loop', description: 'Bootstrap validation workflows' }, { name: 'adr_bootstrap_validation', description: 'Validate ADR bootstrap process' }, { name: 'troubleshoot_guided_workflow', description: 'Guided troubleshooting' }, { name: 'llm_web_search', description: 'Search web for context' }, { name: 'llm_cloud_management', description: 'Manage cloud resources' }, { name: 'llm_database_management', description: 'Manage database operations' }, { name: 'memory_loading', description: 'Load and manage memory entities' }, { name: 'get_server_context', description: 'Get current server context' }, { name: 'mcp_planning', description: 'Plan MCP workflows' }, ]; // Group tools by category for better organization const categories = this.categorizeTools(tools); let toolsSection = '### Available Tools by Category\n\n'; for (const [category, categoryTools] of Object.entries(categories)) { toolsSection += `**${category}**\n`; categoryTools.forEach((tool, idx) => { toolsSection += `${idx + 1}. \`${tool.name}\` - ${tool.description}\n`; }); toolsSection += '\n'; } return `## 🎯 Server Quick Reference **Name**: mcp-adr-analysis-server **Purpose**: AI-powered architectural decision analysis and ADR management **Project Path**: \`${this.config.projectPath}\` **ADR Directory**: \`${this.config.adrDirectory}\` ${toolsSection} 📖 Full tool schemas available via MCP protocol • Total: ${tools.length} tools`; } /** * Categorize tools for better organization */ private categorizeTools( tools: Array<{ name: string; description: string }> ): Record<string, Array<{ name: string; description: string }>> { const categories: Record<string, Array<{ name: string; description: string }>> = { 'ADR Management': [], 'Deployment & Infrastructure': [], 'Research & Analysis': [], 'Development Workflow': [], 'Memory & Context': [], 'Cloud & Database': [], Other: [], }; tools.forEach(tool => { const name = tool.name.toLowerCase(); if (name.includes('adr') || name.includes('rule')) { categories['ADR Management']?.push(tool); } else if (name.includes('deploy') || name.includes('environment')) { categories['Deployment & Infrastructure']?.push(tool); } else if (name.includes('research') || name.includes('expand') || name.includes('review')) { categories['Research & Analysis']?.push(tool); } else if ( name.includes('git') || name.includes('todo') || name.includes('troubleshoot') || name.includes('bootstrap') || name.includes('validation') ) { categories['Development Workflow']?.push(tool); } else if ( name.includes('memory') || name.includes('conversation') || name.includes('context') ) { categories['Memory & Context']?.push(tool); } else if (name.includes('cloud') || name.includes('database') || name.includes('llm')) { categories['Cloud & Database']?.push(tool); } else { categories['Other']?.push(tool); } }); // Remove empty categories Object.keys(categories).forEach(key => { if (categories[key]?.length === 0) { delete categories[key]; } }); return categories; } private async generateMemoryStatus( kgManager: KnowledgeGraphManager, memoryManager: MemoryEntityManager, conversationManager: ConversationMemoryManager, maxRecent: number ): Promise<string> { // Get knowledge graph data const kg = await kgManager.loadKnowledgeGraph(); const activeIntents = await kgManager.getActiveIntents(); const completedIntents = await kgManager.getIntentsByStatus('completed'); // Get memory entity data const entityQuery = await memoryManager.queryEntities({ limit: 1000 }); const intelligence = await memoryManager.getIntelligence(); // Get conversation data let sessionInfo = 'None'; let turnCount = 0; let sessionDuration = '0m'; try { const stats = await conversationManager.getStats(); if (stats.activeSessions > 0) { sessionInfo = `${stats.activeSessions} active`; turnCount = stats.totalTurns; // Use average session duration if available sessionDuration = stats.activeSessions > 0 ? `${Math.floor(stats.totalTurns / stats.activeSessions)}t` : '0m'; } } catch { // Conversation manager not initialized } // Recent intents const recentIntents = kg.intents .slice(-maxRecent) .reverse() .map( intent => `- **${intent.humanRequest.substring(0, 60)}...** - ${intent.currentStatus} - ${new Date(intent.timestamp).toLocaleString()}` ) .join('\n'); // Entity breakdown const entityBreakdown = Object.entries(entityQuery.aggregations?.byType || {}) .map(([type, count]) => `- ${type}: ${count}`) .join('\n'); const avgConfidence = Math.round( (entityQuery.entities.reduce((sum, e) => sum + e.confidence, 0) / (entityQuery.entities.length || 1)) * 100 ); return `## 🧠 Memory & Knowledge Graph Status ### Active Intents **Total Intents**: ${kg.intents.length} **Active**: ${activeIntents.length} | **Completed**: ${completedIntents.length} **Recent Intents** (Last ${maxRecent}): ${recentIntents || '- No recent intents'} ### Memory Entities **Total Entities**: ${entityQuery.totalCount} **Relationships**: ${entityQuery.relationships.length} **Average Confidence**: ${avgConfidence}% **Entity Breakdown**: ${entityBreakdown || '- No entities yet'} **Recent Activity** (Last 24h): - Knowledge Gaps: ${intelligence.adaptiveRecommendations.knowledgeGaps.length} identified ### Conversation Context **Active Session**: ${sessionInfo} **Conversation Turns**: ${turnCount} **Session Duration**: ${sessionDuration}`; } private async generateAnalytics(kgManager: KnowledgeGraphManager): Promise<string> { const kg = await kgManager.loadKnowledgeGraph(); const trends = await kgManager.getProjectScoreTrends(); // Tool usage from analytics const toolUsage = kg.analytics.mostUsedTools .slice(0, 5) .map((t, i) => `${i + 1}. **${t.toolName}**: ${t.usageCount} calls`) .join('\n'); return `## 📊 Recent Analytics ### Tool Usage (Most Used) ${toolUsage || '- No tool usage yet'} ### Score Trends - **Current Project Score**: ${Math.round(trends.currentScore)}/100 - **Average Improvement per Intent**: ${Math.round(trends.averageImprovement)} ### Top Impacting Intents ${trends.topImpactingIntents .slice(0, 3) .map( i => `- **${i.humanRequest.substring(0, 50)}...**: ${i.scoreImprovement > 0 ? '+' : ''}${Math.round(i.scoreImprovement)} points` ) .join('\n')}`; } private async generatePatterns(memoryManager: MemoryEntityManager): Promise<string> { const intelligence = await memoryManager.getIntelligence(); const patterns = intelligence.patternRecognition.discoveredPatterns .slice(0, 5) .map(p => `- **${p.pattern}**: ${Math.round((p.confidence || 0) * 100)}% confidence`) .join('\n'); const suggestions = intelligence.relationshipInference.suggestedRelationships .slice(0, 3) .map( s => `- ${s.sourceId.substring(0, 8)} → ${s.targetId.substring(0, 8)}: **${s.type}** (${Math.round((s.confidence || 0) * 100)}%)` ) .join('\n'); return `## 🔍 Discovered Patterns ### Architectural Patterns ${patterns || '- No patterns discovered yet'} ### Suggested Relationships ${suggestions || '- No relationship suggestions yet'} **Emergent Behaviors**: ${intelligence.patternRecognition.emergentBehaviors.length} detected`; } private async generateRecommendations(memoryManager: MemoryEntityManager): Promise<string> { const intelligence = await memoryManager.getIntelligence(); const nextActions = intelligence.adaptiveRecommendations.nextActions .slice(0, 3) .map(a => `${a.priority}. **${a.action}** - ${a.reasoning}`) .join('\n'); const knowledgeGaps = intelligence.adaptiveRecommendations.knowledgeGaps .slice(0, 3) .map(gap => `- ${gap}`) .join('\n'); const opportunities = intelligence.adaptiveRecommendations.optimizationOpportunities .slice(0, 3) .map(opp => `- ${opp}`) .join('\n'); return `## 🎯 Recommendations for This Session ### Next Actions ${nextActions || '- No specific actions recommended'} ### Knowledge Gaps ${knowledgeGaps || '- No knowledge gaps identified'} ### Optimization Opportunities ${opportunities || '- No optimization opportunities identified'}`; } private generateUsageGuide(): string { return `## 📝 How to Use This Context **When starting a conversation**: \`\`\` @.mcp-server-context.md I need to understand our current architectural decisions \`\`\` **When resuming work**: \`\`\` @.mcp-server-context.md What were we working on? Show me the active intents \`\`\` **When making decisions**: \`\`\` @.mcp-server-context.md What patterns have we discovered that relate to [topic]? \`\`\` **When checking progress**: \`\`\` @.mcp-server-context.md How has our architecture score changed recently? \`\`\``; } private generateFooter(): string { return `## 🔄 Context Refresh This file is automatically updated: - After every tool execution - When memory entities change - When conversation sessions start/end - On server restart To manually refresh: Use the MCP tool \`get_server_context\` or restart the server --- _This context file bridges the gap between the server's persistent memory systems and your working conversation context._`; } }

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