UNPKG

claude-expert-workflow-mcp

Version:

Production-ready MCP server for AI-powered product development consultation through specialized expert roles. Enterprise-grade with memory management, monitoring, and Claude Code integration.

428 lines 18.3 kB
// Configuration Validation System for Claude Expert Workflow MCP // Provides comprehensive validation and management of system configuration import { z } from 'zod'; import { correlationTracker } from '../utils/correlationTracker'; // Extended Thinking Configuration Schema export const extendedThinkingConfigSchema = z.object({ enabled: z.boolean().default(true), autoTriggerThreshold: z.number().min(0).max(1).default(0.7), maxThinkingBlocks: z.number().min(1).max(50).default(10), maxThinkingBlockSize: z.number().min(1000).max(500000).default(50000), // 50KB thinkingBlockTTL: z.number().min(300000).default(1800000), // 30 minutes default budgetTokens: z.number().min(1024).max(32768).default(8192), fallbackConfig: z.object({ maxThinkingBlocks: z.number().min(1).max(10).default(5), maxBudgetTokens: z.number().min(512).max(8192).default(4096) }).default({ maxThinkingBlocks: 5, maxBudgetTokens: 4096 }) }); // Memory Management Configuration Schema export const memoryConfigSchema = z.object({ maxTotalMemoryMB: z.number().min(50).max(2048).default(500), maxConversations: z.number().min(10).max(10000).default(1000), conversationTTL: z.number().min(300000).default(3600000), // 1 hour default maxMessagesPerConversation: z.number().min(10).max(1000).default(100), maxThinkingBlocks: z.number().min(1).max(50).default(10), maxThinkingBlockSize: z.number().min(1000).max(500000).default(50000), thinkingBlockTTL: z.number().min(300000).default(1800000), // 30 minutes cleanupInterval: z.number().min(60000).default(300000), // 5 minutes default gracefulDegradationThreshold: z.number().min(50).max(95).default(80), maxCacheEntries: z.number().min(100).max(5000).default(500), cacheTTL: z.number().min(300000).default(1800000) // 30 minutes }); // Resource Monitoring Configuration Schema export const resourceConfigSchema = z.object({ maxMemoryMB: z.number().min(100).max(4096).default(1024), maxHeapUsageMB: z.number().min(50).max(2048).default(512), maxCpuPercent: z.number().min(10).max(100).default(80), maxActiveHandles: z.number().min(100).max(10000).default(1000), maxEventLoopDelayMs: z.number().min(10).max(1000).default(100), memoryGrowthRateMBPerMin: z.number().min(1).max(500).default(50), monitoringInterval: z.number().min(5000).max(300000).default(30000) // 30 seconds }); // Graceful Degradation Configuration Schema export const degradationConfigSchema = z.object({ memoryThresholds: z.object({ warning: z.number().min(50).max(95).default(70), degraded: z.number().min(60).max(95).default(80), critical: z.number().min(70).max(98).default(90) }).default({ warning: 70, degraded: 80, critical: 90 }), degradationActions: z.object({ reduceThinkingBlocks: z.boolean().default(true), limitConversations: z.boolean().default(true), disableComplexFeatures: z.boolean().default(true), enableAggressiveCleanup: z.boolean().default(true) }).default({ reduceThinkingBlocks: true, limitConversations: true, disableComplexFeatures: true, enableAggressiveCleanup: true }), recoveryThresholds: z.object({ memoryRecoveryThreshold: z.number().min(30).max(80).default(60), stabilityRequiredMs: z.number().min(5000).max(300000).default(30000) }).default({ memoryRecoveryThreshold: 60, stabilityRequiredMs: 30000 }) }); // Correlation Tracking Configuration Schema export const correlationConfigSchema = z.object({ enabled: z.boolean().default(true), maxRequestHistory: z.number().min(100).max(10000).default(1000), requestTTL: z.number().min(300000).default(3600000), // 1 hour cleanupInterval: z.number().min(60000).default(300000), // 5 minutes correlationIdLength: z.number().min(8).max(64).default(16), enablePerformanceTracking: z.boolean().default(true), enableMetricsCollection: z.boolean().default(true) }); // MCP Server Configuration Schema export const mcpServerConfigSchema = z.object({ timeout: z.number().min(30000).max(600000).default(120000), // 2 minutes default maxConcurrentRequests: z.number().min(1).max(100).default(10), enableExtendedThinking: z.boolean().default(true), enableTaskMasterAI: z.boolean().default(false), retryAttempts: z.number().min(0).max(10).default(3), retryDelayMs: z.number().min(100).max(30000).default(1000) }); // Combined System Configuration Schema export const systemConfigSchema = z.object({ extendedThinking: extendedThinkingConfigSchema, memory: memoryConfigSchema, resources: resourceConfigSchema, degradation: degradationConfigSchema, correlation: correlationConfigSchema, mcpServer: mcpServerConfigSchema, environment: z.object({ nodeEnv: z.enum(['development', 'staging', 'production']).default('development'), logLevel: z.enum(['error', 'warn', 'info', 'debug']).default('info'), debug: z.boolean().default(false) }).default({ nodeEnv: 'development', logLevel: 'info', debug: false }) }); /** * Configuration Manager * Centralized configuration validation and management */ export class ConfigurationManager { constructor() { this.validationHistory = []; } static getInstance() { if (!ConfigurationManager.instance) { ConfigurationManager.instance = new ConfigurationManager(); } return ConfigurationManager.instance; } /** * Validate system configuration with comprehensive checks */ async validateConfiguration(config, correlationId) { const trackingCorrelationId = correlationId || correlationTracker.generateCorrelationId(); correlationTracker.startRequest('config-validation', trackingCorrelationId, trackingCorrelationId, { operation: 'validate-system-config', hasConfig: config !== undefined }); try { const result = await this.performValidation(config, trackingCorrelationId); // Store validation history this.validationHistory.push({ timestamp: Date.now(), correlationId: trackingCorrelationId, result: { isValid: result.isValid, errors: result.errors, warnings: result.warnings } }); // Maintain history size if (this.validationHistory.length > 100) { this.validationHistory = this.validationHistory.slice(-100); } correlationTracker.completeRequest(trackingCorrelationId, true); return result; } catch (error) { correlationTracker.completeRequest(trackingCorrelationId, false, error instanceof Error ? error.message : 'Unknown validation error'); throw error; } } /** * Perform comprehensive configuration validation */ async performValidation(config, correlationId) { const errors = []; const warnings = []; try { // Parse configuration with schema const parsedConfig = systemConfigSchema.parse(config); // Perform cross-validation checks this.validateCrossReferences(parsedConfig, errors, warnings); this.validateResourceConstraints(parsedConfig, errors, warnings); this.validatePerformanceSettings(parsedConfig, errors, warnings); this.validateSecuritySettings(parsedConfig, errors, warnings); // Store valid configuration if (errors.length === 0) { this.currentConfig = parsedConfig; } return { isValid: errors.length === 0, config: errors.length === 0 ? parsedConfig : undefined, errors, warnings }; } catch (zodError) { if (zodError instanceof z.ZodError) { // Convert Zod errors to our format zodError.errors.forEach(err => { errors.push({ path: err.path.map(p => String(p)), message: err.message, severity: 'error' }); }); } else { errors.push({ path: [], message: `Configuration validation failed: ${zodError instanceof Error ? zodError.message : 'Unknown error'}`, severity: 'error' }); } return { isValid: false, errors, warnings }; } } /** * Validate cross-references between configuration sections */ validateCrossReferences(config, errors, warnings) { // Extended Thinking and Memory alignment if (config.extendedThinking.maxThinkingBlocks > config.memory.maxThinkingBlocks) { warnings.push({ path: ['extendedThinking', 'maxThinkingBlocks'], message: 'Extended thinking max blocks exceeds memory management limit', recommendation: 'Align Extended Thinking maxThinkingBlocks with memory.maxThinkingBlocks' }); } if (config.extendedThinking.maxThinkingBlockSize > config.memory.maxThinkingBlockSize) { warnings.push({ path: ['extendedThinking', 'maxThinkingBlockSize'], message: 'Extended thinking block size exceeds memory management limit', recommendation: 'Align Extended Thinking maxThinkingBlockSize with memory.maxThinkingBlockSize' }); } // Memory and Resource alignment if (config.memory.maxTotalMemoryMB > config.resources.maxMemoryMB) { errors.push({ path: ['memory', 'maxTotalMemoryMB'], message: 'Memory manager total memory exceeds resource monitor limit', severity: 'error' }); } // Degradation thresholds validation if (config.degradation.memoryThresholds.warning >= config.degradation.memoryThresholds.degraded) { errors.push({ path: ['degradation', 'memoryThresholds', 'warning'], message: 'Warning threshold must be less than degraded threshold', severity: 'error' }); } if (config.degradation.memoryThresholds.degraded >= config.degradation.memoryThresholds.critical) { errors.push({ path: ['degradation', 'memoryThresholds', 'degraded'], message: 'Degraded threshold must be less than critical threshold', severity: 'error' }); } } /** * Validate resource constraints and limits */ validateResourceConstraints(config, errors, warnings) { // Memory constraints const estimatedMemoryUsage = this.estimateMemoryUsage(config); if (estimatedMemoryUsage > config.resources.maxMemoryMB * 0.8) { warnings.push({ path: ['memory'], message: `Estimated memory usage (${Math.round(estimatedMemoryUsage)}MB) may exceed 80% of resource limit`, recommendation: 'Consider reducing conversation limits or increasing resource limits' }); } // TTL consistency checks if (config.memory.conversationTTL < config.memory.cleanupInterval * 2) { warnings.push({ path: ['memory', 'conversationTTL'], message: 'Conversation TTL should be at least 2x the cleanup interval', recommendation: 'Increase conversationTTL or decrease cleanupInterval' }); } // Performance constraints if (config.mcpServer.maxConcurrentRequests * config.extendedThinking.maxThinkingBlocks > 100) { warnings.push({ path: ['mcpServer', 'maxConcurrentRequests'], message: 'High concurrent requests × thinking blocks may cause performance issues', recommendation: 'Consider reducing concurrent requests or thinking block limits' }); } } /** * Validate performance-related settings */ validatePerformanceSettings(config, errors, warnings) { // Monitoring intervals if (config.resources.monitoringInterval < 5000) { warnings.push({ path: ['resources', 'monitoringInterval'], message: 'Very frequent resource monitoring may impact performance', recommendation: 'Consider intervals >= 5 seconds' }); } // Cache settings if (config.memory.maxCacheEntries * 1000 > config.memory.maxTotalMemoryMB * 1024 * 1024 * 0.1) { warnings.push({ path: ['memory', 'maxCacheEntries'], message: 'Cache size may consume significant memory', recommendation: 'Reduce cache entries or increase memory limits' }); } // Extended Thinking performance if (config.extendedThinking.budgetTokens > 16384) { warnings.push({ path: ['extendedThinking', 'budgetTokens'], message: 'High token budget may cause slow responses', recommendation: 'Consider token budgets <= 16384 for better performance' }); } } /** * Validate security-related settings */ validateSecuritySettings(config, errors, warnings) { // Resource limits for security if (config.memory.maxConversations > 5000) { warnings.push({ path: ['memory', 'maxConversations'], message: 'Very high conversation limits may be exploitable', recommendation: 'Consider conversation limits <= 5000' }); } if (config.mcpServer.timeout > 300000) { // 5 minutes warnings.push({ path: ['mcpServer', 'timeout'], message: 'Long timeouts may cause resource exhaustion', recommendation: 'Consider timeouts <= 5 minutes' }); } // Correlation ID length for security if (config.correlation.correlationIdLength < 12) { warnings.push({ path: ['correlation', 'correlationIdLength'], message: 'Short correlation IDs may be predictable', recommendation: 'Use correlation ID length >= 12 characters' }); } } /** * Estimate memory usage based on configuration */ estimateMemoryUsage(config) { const conversationMemory = config.memory.maxConversations * (config.memory.maxMessagesPerConversation * 500 + // ~500 bytes per message config.memory.maxThinkingBlocks * config.memory.maxThinkingBlockSize) / (1024 * 1024); // Convert to MB const cacheMemory = config.memory.maxCacheEntries * 1000 / (1024 * 1024); // ~1KB per cache entry const systemOverhead = 50; // 50MB system overhead return conversationMemory + cacheMemory + systemOverhead; } /** * Get current validated configuration */ getCurrentConfig() { return this.currentConfig ? { ...this.currentConfig } : undefined; } /** * Get validation history */ getValidationHistory(limit = 10) { return this.validationHistory .slice(-limit) .map((entry) => ({ timestamp: entry.timestamp, correlationId: entry.correlationId, result: { isValid: entry.result.isValid, errors: entry.result.errors, warnings: entry.result.warnings } })); } /** * Generate configuration recommendations */ generateRecommendations(config) { const targetConfig = config || this.currentConfig; if (!targetConfig) return []; const recommendations = []; // Performance recommendations if (targetConfig.extendedThinking.budgetTokens > 8192) { recommendations.push({ category: 'performance', priority: 'medium', recommendation: 'Consider reducing Extended Thinking token budget for faster responses', impact: 'Improved response time, reduced resource usage' }); } // Memory optimization if (targetConfig.memory.conversationTTL > 7200000) { // 2 hours recommendations.push({ category: 'memory', priority: 'low', recommendation: 'Consider shorter conversation TTL to reduce memory usage', impact: 'Lower memory consumption, more frequent cleanup' }); } // Security improvements if (!targetConfig.correlation.enabled) { recommendations.push({ category: 'security', priority: 'high', recommendation: 'Enable correlation tracking for better debugging and security', impact: 'Enhanced debugging, security auditing, and system monitoring' }); } return recommendations; } /** * Clear validation history (for testing) */ clearValidationHistory() { this.validationHistory = []; } } // Singleton instance for easy access export const configurationManager = ConfigurationManager.getInstance(); /** * Helper function to validate partial configuration updates */ export async function validatePartialConfig(partialConfig, currentConfig) { // Merge partial config with current config const mergedConfig = { ...currentConfig, ...partialConfig }; return await configurationManager.validateConfiguration(mergedConfig); } /** * Helper function to create default configuration */ export function createDefaultConfig() { return systemConfigSchema.parse({}); } //# sourceMappingURL=configurationValidator.js.map