UNPKG

mcp-adr-analysis-server

Version:

MCP server for analyzing Architectural Decision Records and project architecture

889 lines 398 kB
#!/usr/bin/env node /** * MCP ADR Analysis Server * Main entry point for the Model Context Protocol server * * This server provides Tools, Resources, and Prompts for analyzing * Architectural Decision Records and project architecture. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { readFileSync } from 'fs'; import { join } from 'path'; import { getCurrentDirCompat } from './utils/directory-compat.js'; import { McpAdrError } from './types/index.js'; import { CONVERSATION_CONTEXT_SCHEMA } from './types/conversation-context.js'; import { maskMcpResponse, createMaskingConfig, } from './utils/output-masking.js'; import { loadConfig, validateProjectPath, createLogger, printConfigSummary, } from './utils/config.js'; import { KnowledgeGraphManager } from './utils/knowledge-graph-manager.js'; import { getEnhancedModeDefault, getKnowledgeEnhancementDefault, } from './utils/test-aware-defaults.js'; import { StateReinforcementManager } from './utils/state-reinforcement-manager.js'; import { ConversationMemoryManager } from './utils/conversation-memory-manager.js'; import { MemoryEntityManager } from './utils/memory-entity-manager.js'; import { RootManager } from './utils/root-manager.js'; import { ServerContextGenerator } from './utils/server-context-generator.js'; import { createNoOpContext } from './types/tool-context.js'; import { executeSearchTools, getSearchToolsDefinition, } from './tools/tool-dispatcher.js'; import { shouldUseCEMCPDirective, getCEMCPDirective, formatDirectiveResponse, } from './tools/ce-mcp-tools.js'; import { loadAIConfig, isCEMCPEnabled } from './config/ai-config.js'; /** * Get version from package.json */ function getPackageVersion() { try { // Handle both Jest environment and normal execution const currentDir = getCurrentDirCompat(); // Strategy 1: Try multiple possible locations for package.json const possiblePaths = [ join(currentDir, 'package.json'), join(currentDir, '..', 'package.json'), join(currentDir, '..', '..', 'package.json'), join(process.cwd(), 'package.json'), ]; for (const packageJsonPath of possiblePaths) { try { const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8')); if (packageJson.name === 'mcp-adr-analysis-server') { return packageJson.version; } } catch { // Try next path } } // Strategy 2: Use process.env.npm_package_version if available (during npm scripts) if (process.env['npm_package_version']) { return process.env['npm_package_version']; } // Final fallback: Use generic version instead of hardcoded specific version // This prevents the need to update this code when version changes return 'unknown'; // Generic fallback - no longer tied to specific version } catch (error) { console.error('Error reading package.json:', error); return 'unknown'; // Generic fallback - no longer tied to specific version } } /** * Server configuration */ const SERVER_INFO = { name: 'mcp-adr-analysis-server', version: getPackageVersion(), description: 'MCP server for analyzing Architectural Decision Records and project architecture', }; /** * Main server class */ export class McpAdrAnalysisServer { server; maskingConfig; config; logger; kgManager; stateReinforcementManager; conversationMemoryManager; memoryEntityManager; rootManager; contextGenerator; constructor() { // Load and validate configuration this.config = loadConfig(); this.logger = createLogger(this.config); this.kgManager = new KnowledgeGraphManager(); this.stateReinforcementManager = new StateReinforcementManager(this.kgManager); this.conversationMemoryManager = new ConversationMemoryManager(this.kgManager); this.memoryEntityManager = new MemoryEntityManager(); // Initialize root manager for file access control this.rootManager = new RootManager(this.config.projectPath, this.config.adrDirectory); // Initialize server context generator this.contextGenerator = new ServerContextGenerator(); // Print configuration summary printConfigSummary(this.config); // Note: Validation will be done during startup this.server = new Server(SERVER_INFO, { capabilities: { tools: {}, resources: {}, prompts: {}, }, }); this.maskingConfig = createMaskingConfig(); this.setupHandlers(); } /** * Validate configuration and project setup */ async validateConfiguration() { try { await validateProjectPath(this.config.projectPath); this.logger.info(`Project path validated: ${this.config.projectPath}`); } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); this.logger.error(`Configuration validation failed: ${errorMessage}`); throw error; } } /** * Public health check method for testing */ async healthCheck() { await this.validateConfiguration(); this.logger.info('Health check completed successfully'); } /** * Setup MCP protocol handlers * * @description Configures all Model Context Protocol request handlers for the ADR Analysis Server. * Implements the complete MCP specification including tools, resources, and prompts. * * @private * @since 2.0.0 * @category MCP Protocol */ setupHandlers() { /** * List Tools Handler - MCP Protocol Endpoint * * @description Returns the complete catalog of available tools for ADR analysis, * research, validation, and deployment operations. Each tool includes comprehensive * input schemas and descriptions for client integration. * * @returns {Promise<{tools: Array}>} Complete tool catalog with schemas * * @example * ```typescript * // MCP Client usage * const tools = await mcpClient.listTools(); * console.log(tools.tools.length); // 20+ available tools * * // Find specific tool * const researchTool = tools.tools.find(t => t.name === 'perform_research'); * console.log(researchTool.description); // Tool description * ``` * * @mcp-endpoint * @category Tools */ this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ // Meta-tool for dynamic tool discovery (CE-MCP Phase 3) getSearchToolsDefinition(), { name: 'analyze_project_ecosystem', description: 'Comprehensive recursive project ecosystem analysis with advanced prompting techniques (Knowledge Generation + Reflexion)', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project directory to analyze (optional, uses configured PROJECT_PATH if not provided)', }, includePatterns: { type: 'array', items: { type: 'string' }, description: 'File patterns to include in analysis', }, enhancedMode: { type: 'boolean', description: 'Enable advanced prompting features (Knowledge Generation + Reflexion)', default: true, }, knowledgeEnhancement: { type: 'boolean', description: 'Enable Knowledge Generation for technology-specific insights', default: true, }, learningEnabled: { type: 'boolean', description: 'Enable Reflexion learning from past analysis outcomes', default: true, }, technologyFocus: { type: 'array', items: { type: 'string' }, description: 'Specific technologies to focus analysis on (auto-detected if not provided)', }, analysisDepth: { type: 'string', enum: ['basic', 'detailed', 'comprehensive'], description: 'Depth of ecosystem analysis', default: 'comprehensive', }, includeEnvironment: { type: 'boolean', description: 'Automatically include comprehensive environment analysis (default: true)', default: true, }, recursiveDepth: { type: 'string', description: 'Depth of recursive project analysis', enum: ['shallow', 'moderate', 'deep', 'comprehensive'], default: 'comprehensive', }, analysisScope: { type: 'array', items: { type: 'string' }, description: 'Specific analysis areas to focus on (e.g., ["security", "performance", "architecture", "dependencies"])', }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, required: [], }, }, { name: 'get_architectural_context', description: 'Get detailed architectural context for specific files or the entire project, automatically sets up ADR infrastructure if missing, and provides outcome-focused workflow for project success', inputSchema: { type: 'object', properties: { filePath: { type: 'string', description: 'Specific file path to analyze (optional, analyzes entire project if not provided)', }, includeCompliance: { type: 'boolean', description: 'Include compliance checks in the analysis', default: true, }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, }, }, { name: 'generate_adrs_from_prd', description: 'Generate Architectural Decision Records from a Product Requirements Document with advanced prompting techniques (APE + Knowledge Generation)', inputSchema: { type: 'object', properties: { prdPath: { type: 'string', description: 'Path to the PRD.md file', }, outputDirectory: { type: 'string', description: 'Directory to output generated ADRs (optional, uses configured ADR_DIRECTORY if not provided)', }, enhancedMode: { type: 'boolean', description: 'Enable advanced prompting features (APE + Knowledge Generation)', default: true, }, promptOptimization: { type: 'boolean', description: 'Enable Automatic Prompt Engineering for optimized ADR generation', default: true, }, knowledgeEnhancement: { type: 'boolean', description: 'Enable Knowledge Generation for domain-specific insights', default: true, }, prdType: { type: 'string', enum: [ 'web-application', 'mobile-app', 'microservices', 'data-platform', 'api-service', 'general', ], description: 'Type of PRD for optimized knowledge generation', default: 'general', }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, required: ['prdPath'], }, }, { name: 'compare_adr_progress', description: 'Compare TODO.md progress against ADRs and current environment to validate implementation status', inputSchema: { type: 'object', properties: { todoPath: { type: 'string', description: 'Path to TODO.md file to analyze', default: 'TODO.md', }, adrDirectory: { type: 'string', description: 'Directory containing ADR files', default: 'docs/adrs', }, projectPath: { type: 'string', description: 'Path to project root for environment analysis', default: '.', }, environment: { type: 'string', enum: ['development', 'staging', 'production', 'testing', 'auto-detect'], description: 'Target environment context for validation (auto-detect will infer from project structure)', default: 'auto-detect', }, environmentConfig: { type: 'object', description: 'Environment-specific configuration and requirements', properties: { requiredFiles: { type: 'array', items: { type: 'string' }, description: 'Files required for this environment', }, requiredServices: { type: 'array', items: { type: 'string' }, description: 'Services that must be implemented for this environment', }, securityLevel: { type: 'string', enum: ['low', 'medium', 'high', 'critical'], description: 'Required security level for this environment', }, performanceRequirements: { type: 'object', description: 'Performance requirements for this environment', }, }, }, validationType: { type: 'string', enum: ['full', 'todo-only', 'adr-only', 'environment-only'], description: 'Type of validation to perform', default: 'full', }, includeFileChecks: { type: 'boolean', description: 'Include file existence and implementation checks', default: true, }, includeRuleValidation: { type: 'boolean', description: 'Include architectural rule compliance validation', default: true, }, deepCodeAnalysis: { type: 'boolean', description: 'Perform deep code analysis to distinguish mock from production implementations', default: true, }, functionalValidation: { type: 'boolean', description: 'Validate that code actually functions according to ADR goals, not just exists', default: true, }, strictMode: { type: 'boolean', description: 'Enable strict validation mode with reality-check mechanisms against overconfident assessments', default: true, }, environmentValidation: { type: 'boolean', description: 'Enable environment-specific validation rules and checks', default: true, }, }, }, }, { name: 'analyze_content_security', description: 'Analyze content for sensitive information using AI-powered detection with optional memory integration for security pattern learning', inputSchema: { type: 'object', properties: { content: { type: 'string', description: 'Content to analyze for sensitive information', }, contentType: { type: 'string', enum: ['code', 'documentation', 'configuration', 'logs', 'general'], description: 'Type of content being analyzed', default: 'general', }, userDefinedPatterns: { type: 'array', items: { type: 'string' }, description: 'User-defined sensitive patterns to detect', }, enableMemoryIntegration: { type: 'boolean', description: 'Enable memory entity storage for security pattern learning and institutional knowledge building', default: true, }, knowledgeEnhancement: { type: 'boolean', description: 'Enable Generated Knowledge Prompting for security and privacy expertise', default: true, }, enhancedMode: { type: 'boolean', description: 'Enable advanced prompting features', default: true, }, }, required: ['content'], }, }, { name: 'generate_content_masking', description: 'Generate masking instructions for detected sensitive content', inputSchema: { type: 'object', properties: { content: { type: 'string', description: 'Content to mask', }, detectedItems: { type: 'array', items: { type: 'object', properties: { type: { type: 'string' }, content: { type: 'string' }, startPosition: { type: 'number' }, endPosition: { type: 'number' }, severity: { type: 'string' }, }, }, description: 'Detected sensitive items to mask', }, maskingStrategy: { type: 'string', enum: ['full', 'partial', 'placeholder', 'environment'], description: 'Strategy for masking content', default: 'full', }, }, required: ['content', 'detectedItems'], }, }, { name: 'configure_custom_patterns', description: 'Configure custom sensitive patterns for a project', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project directory', }, existingPatterns: { type: 'array', items: { type: 'string' }, description: 'Existing patterns to consider', }, }, required: ['projectPath'], }, }, { name: 'apply_basic_content_masking', description: 'Apply basic content masking (fallback when AI is not available)', inputSchema: { type: 'object', properties: { content: { type: 'string', description: 'Content to mask', }, maskingStrategy: { type: 'string', enum: ['full', 'partial', 'placeholder'], description: 'Strategy for masking content', default: 'full', }, }, required: ['content'], }, }, { name: 'validate_content_masking', description: 'Validate that content masking was applied correctly', inputSchema: { type: 'object', properties: { originalContent: { type: 'string', description: 'Original content before masking', }, maskedContent: { type: 'string', description: 'Content after masking', }, }, required: ['originalContent', 'maskedContent'], }, }, { name: 'manage_cache', description: 'Manage MCP resource cache (clear, stats, cleanup)', inputSchema: { type: 'object', properties: { action: { type: 'string', enum: ['clear', 'stats', 'cleanup', 'invalidate'], description: 'Cache management action to perform', }, key: { type: 'string', description: 'Specific cache key to invalidate (for invalidate action)', }, }, required: ['action'], }, }, { name: 'configure_output_masking', description: 'Configure content masking for all MCP outputs', inputSchema: { type: 'object', properties: { enabled: { type: 'boolean', description: 'Enable or disable output masking', }, strategy: { type: 'string', enum: ['full', 'partial', 'placeholder', 'environment'], description: 'Masking strategy to use', }, customPatterns: { type: 'array', items: { type: 'string' }, description: 'Custom patterns to mask', }, action: { type: 'string', enum: ['get', 'set', 'reset'], description: 'Configuration action', default: 'get', }, }, }, }, { name: 'suggest_adrs', description: 'Suggest architectural decisions with advanced prompting techniques (Knowledge Generation + Reflexion). TIP: Read @.mcp-server-context.md first for project history, patterns, and previous ADRs to ensure consistency.', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project directory', default: '.', }, analysisType: { type: 'string', enum: ['implicit_decisions', 'code_changes', 'comprehensive'], description: 'Type of analysis to perform', default: 'comprehensive', }, beforeCode: { type: 'string', description: 'Code before changes (for code_changes analysis)', }, afterCode: { type: 'string', description: 'Code after changes (for code_changes analysis)', }, changeDescription: { type: 'string', description: 'Description of the changes (for code_changes analysis)', }, commitMessages: { type: 'array', items: { type: 'string' }, description: 'Related commit messages (for code_changes analysis)', }, existingAdrs: { type: 'array', items: { type: 'string' }, description: 'List of existing ADR titles to avoid duplication', }, enhancedMode: { type: 'boolean', description: 'Enable advanced prompting features (Knowledge Generation + Reflexion)', default: true, }, learningEnabled: { type: 'boolean', description: 'Enable Reflexion learning from past experiences', default: true, }, knowledgeEnhancement: { type: 'boolean', description: 'Enable Knowledge Generation for domain-specific insights', default: true, }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, }, }, { name: 'generate_adr_from_decision', description: 'Generate a complete ADR from decision data. TIP: Reference @.mcp-server-context.md to align with existing architectural patterns and decisions.', inputSchema: { type: 'object', properties: { decisionData: { type: 'object', properties: { title: { type: 'string', description: 'Decision title' }, context: { type: 'string', description: 'Decision context and problem' }, decision: { type: 'string', description: 'The architectural decision' }, consequences: { type: 'string', description: 'Decision consequences' }, alternatives: { type: 'array', items: { type: 'string' }, description: 'Alternative approaches considered', }, evidence: { type: 'array', items: { type: 'string' }, description: 'Supporting evidence for the decision', }, }, required: ['title', 'context', 'decision', 'consequences'], }, templateFormat: { type: 'string', enum: ['nygard', 'madr', 'custom'], description: 'ADR template format to use', default: 'nygard', }, existingAdrs: { type: 'array', items: { type: 'string' }, description: 'List of existing ADRs for numbering and references', }, adrDirectory: { type: 'string', description: 'Directory where ADRs are stored', default: 'docs/adrs', }, }, required: ['decisionData'], }, }, { name: 'generate_adr_bootstrap', description: "Generate bootstrap.sh and validate_bootstrap.sh scripts to ensure deployed code follows ADR requirements. **CRITICAL**: Before generating scripts, use WebFetch to query the base code repository (e.g., https://github.com/validatedpatterns/common for OpenShift) and authoritative pattern documentation (e.g., https://play.validatedpatterns.io/). Merge the base repository code into your project and have bootstrap.sh call the pattern's scripts rather than generating everything from scratch. This ensures compliance with validated deployment patterns.", inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project directory', default: '.', }, adrDirectory: { type: 'string', description: 'Directory where ADRs are stored', default: 'docs/adrs', }, outputPath: { type: 'string', description: 'Directory where to generate scripts', default: '.', }, scriptType: { type: 'string', enum: ['bootstrap', 'validate', 'both'], description: 'Which scripts to generate', default: 'both', }, includeTests: { type: 'boolean', description: 'Include test execution in bootstrap', default: true, }, includeDeployment: { type: 'boolean', description: 'Include deployment steps in bootstrap', default: true, }, customValidations: { type: 'array', items: { type: 'string' }, description: 'Custom validation commands to include', }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, }, }, { name: 'bootstrap_validation_loop', description: '**GUIDED EXECUTION MODE**: This tool guides you through an interactive, step-by-step deployment validation workflow. It does NOT execute commands internally - instead, it tells YOU what commands to run and processes the results iteratively. **Workflow**: (1) First call with iteration=0: Detects platform (OpenShift/K8s/Docker), validates environment connection, and requests human approval for target platform. (2) Subsequent calls: After running each command and reporting back with output, the tool provides next steps. **Environment Validation**: Before deployment, the tool verifies connection to the target platform (e.g., `oc status` for OpenShift, `kubectl cluster-info` for K8s) and requires explicit human confirmation. **Validated Patterns Integration**: Automatically identifies base code repositories (e.g., validatedpatterns/common for OpenShift) and guides you to merge them into your project. **Deployment Cleanup**: Supports CI/CD-style workflows with deployment teardown/restart guidance. **Call this tool iteratively**, passing previous command output back each time.', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project directory', default: '.', }, adrDirectory: { type: 'string', description: 'Directory where ADRs are stored', default: 'docs/adrs', }, targetEnvironment: { type: 'string', enum: ['development', 'staging', 'production', 'testing'], description: 'Target deployment environment', default: 'development', }, maxIterations: { type: 'number', description: 'Maximum validation/fix iterations', default: 5, }, autoFix: { type: 'boolean', description: 'Whether to generate auto-fix suggestions in guidance', default: true, }, updateAdrsWithLearnings: { type: 'boolean', description: 'Update ADRs with deployment learnings (non-sensitive)', default: true, }, currentIteration: { type: 'number', description: 'Current iteration number (0 for initial call, then increment). Used to track workflow progress.', default: 0, }, previousExecutionOutput: { type: 'string', description: 'Output from the previous command execution. Paste the stdout/stderr from running the command that was recommended in the previous iteration.', default: '', }, previousExecutionSuccess: { type: 'boolean', description: 'Whether the previous command execution succeeded (exit code 0). Set to true if command succeeded, false if it failed.', default: false, }, deploymentCleanupRequested: { type: 'boolean', description: 'Set to true to request deployment cleanup/teardown guidance (for CI/CD workflows that need to delete and restart deployments).', default: false, }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, }, }, { name: 'discover_existing_adrs', description: 'Discover and catalog existing ADRs in the project', inputSchema: { type: 'object', properties: { adrDirectory: { type: 'string', description: 'Directory to search for ADRs', default: 'docs/adrs', }, includeContent: { type: 'boolean', description: 'Whether to include ADR content in analysis', default: false, }, }, }, }, { name: 'analyze_adr_timeline', description: 'Analyze ADR timeline with smart time tracking, adaptive thresholds, and actionable recommendations. Auto-detects project context (startup/growth/mature) and generates prioritized work queue based on staleness, implementation lag, and technical debt.', inputSchema: { type: 'object', properties: { projectPath: { type: 'string', description: 'Path to the project directory', default: '.', }, adrDirectory: { type: 'string', description: 'Directory containing ADR files', default: 'docs/adrs', }, generateActions: { type: 'boolean', description: 'Generate actionable work items with priority and effort estimates', default: true, }, thresholdProfile: { type: 'string', enum: ['startup', 'growth', 'mature', 'maintenance', 'feature_development'], description: 'Threshold profile for action generation (auto-detected if not specified)', }, autoDetectContext: { type: 'boolean', description: 'Auto-detect project phase from git activity and ADR patterns', default: true, }, includeContent: { type: 'boolean', description: 'Include ADR content for better analysis', default: true, }, forceExtract: { type: 'boolean', description: 'Force timeline extraction even if ADRs have dates', default: false, }, }, }, }, { name: 'review_existing_adrs', description: 'Review existing ADRs against actual code implementation with cloud/DevOps expertise. TIP: After review, call get_server_context to update @.mcp-server-context.md with findings.', inputSchema: { type: 'object', properties: { adrDirectory: { type: 'string', description: 'Directory containing ADR files', default: 'docs/adrs', }, projectPath: { type: 'string', description: 'Path to the project directory', default: '.', }, specificAdr: { type: 'string', description: 'Specific ADR filename or title to review (optional)', }, analysisDepth: { type: 'string', enum: ['basic', 'detailed', 'comprehensive'], description: 'Depth of analysis to perform', default: 'detailed', }, includeTreeSitter: { type: 'boolean', description: 'Use tree-sitter for enhanced code analysis', default: true, }, generateUpdatePlan: { type: 'boolean', description: 'Generate action plan for updating non-compliant ADRs', default: true, }, conversationContext: CONVERSATION_CONTEXT_SCHEMA, }, }, }, { name: 'validate_adr', description