UNPKG

task-engine-ai-core

Version:

Revolutionary AI-driven task management system with complete transformation trilogy: Frontend v0.1.0, Backend v0.2.0, CLI v0.3.0 - Enterprise-grade performance with 95% improvements

252 lines (209 loc) • 9.4 kB
#!/usr/bin/env node /** * Validate MCP Configuration * Checks MCP configuration files for syntax errors and common issues */ import fs from 'fs/promises'; import path from 'path'; class MCPConfigValidator { constructor() { this.projectRoot = process.cwd(); this.errors = []; this.warnings = []; } /** * Validate all MCP configurations */ async validate() { console.log('šŸ” Validating MCP Configuration Files...\n'); const configPaths = [ '.cursor/mcp.json', '.vscode/mcp.json', '.windsurf/mcp.json' ]; let validConfigs = 0; let totalConfigs = 0; for (const configPath of configPaths) { const fullPath = path.join(this.projectRoot, configPath); try { await fs.access(fullPath); totalConfigs++; console.log(`šŸ“„ Validating ${configPath}...`); if (await this.validateConfigFile(configPath, fullPath)) { validConfigs++; console.log(` āœ… ${configPath} is valid\n`); } else { console.log(` āŒ ${configPath} has errors\n`); } } catch (error) { console.log(` āš ļø ${configPath} not found (this is OK if you don't use this IDE)\n`); } } this.printSummary(validConfigs, totalConfigs); if (this.errors.length > 0) { process.exit(1); } } /** * Validate a single config file */ async validateConfigFile(configPath, fullPath) { let isValid = true; try { // Read and parse JSON const configContent = await fs.readFile(fullPath, 'utf8'); let config; try { config = JSON.parse(configContent); } catch (parseError) { this.errors.push(`${configPath}: Invalid JSON - ${parseError.message}`); console.log(` āŒ JSON Syntax Error: ${parseError.message}`); return false; } // Validate structure const serversKey = config.mcpServers ? 'mcpServers' : 'servers'; if (!config[serversKey]) { this.errors.push(`${configPath}: Missing ${serversKey} section`); console.log(` āŒ Missing ${serversKey} section`); isValid = false; } else { console.log(` āœ… Has ${serversKey} section`); } const servers = config[serversKey] || {}; // Check for taskmaster-ai server if (!servers['taskmaster-ai']) { this.warnings.push(`${configPath}: Missing taskmaster-ai server`); console.log(` āš ļø Missing taskmaster-ai server`); } else { console.log(` āœ… Has taskmaster-ai server`); this.validateServer(configPath, 'taskmaster-ai', servers['taskmaster-ai']); } // Check for taskmaster-ide-bridge server if (!servers['taskmaster-ide-bridge']) { this.warnings.push(`${configPath}: Missing taskmaster-ide-bridge server`); console.log(` āš ļø Missing taskmaster-ide-bridge server`); } else { console.log(` āœ… Has taskmaster-ide-bridge server`); this.validateServer(configPath, 'taskmaster-ide-bridge', servers['taskmaster-ide-bridge']); } } catch (error) { this.errors.push(`${configPath}: ${error.message}`); console.log(` āŒ Error: ${error.message}`); isValid = false; } return isValid; } /** * Validate individual server configuration */ validateServer(configPath, serverName, serverConfig) { // Check required fields if (!serverConfig.command) { this.errors.push(`${configPath}: ${serverName} missing command`); console.log(` āŒ ${serverName}: Missing command`); } else { console.log(` āœ… ${serverName}: Has command (${serverConfig.command})`); } if (!serverConfig.args || !Array.isArray(serverConfig.args)) { this.errors.push(`${configPath}: ${serverName} missing or invalid args`); console.log(` āŒ ${serverName}: Missing or invalid args`); } else { console.log(` āœ… ${serverName}: Has args (${serverConfig.args.length} items)`); } // Check for environment variables if (!serverConfig.env) { this.warnings.push(`${configPath}: ${serverName} missing env section`); console.log(` āš ļø ${serverName}: Missing env section`); } else { console.log(` āœ… ${serverName}: Has env section`); // Check for placeholder API keys const env = serverConfig.env; let hasPlaceholders = false; Object.entries(env).forEach(([key, value]) => { if (typeof value === 'string' && value.includes('YOUR_') && value.includes('_HERE')) { hasPlaceholders = true; } }); if (hasPlaceholders) { this.warnings.push(`${configPath}: ${serverName} has placeholder API keys`); console.log(` āš ļø ${serverName}: Has placeholder API keys (remember to replace them)`); } } // Validate specific server configurations if (serverName === 'taskmaster-ide-bridge') { this.validateIDEBridgeConfig(configPath, serverConfig); } } /** * Validate IDE bridge specific configuration */ validateIDEBridgeConfig(configPath, serverConfig) { const env = serverConfig.env || {}; // Check for IDE bridge specific environment variables const requiredEnvVars = [ 'BRIDGE_ENABLED', 'IDE_TYPE', 'TASK_MASTER_PROJECT_ROOT' ]; requiredEnvVars.forEach(envVar => { if (!env[envVar]) { this.warnings.push(`${configPath}: IDE bridge missing ${envVar}`); console.log(` āš ļø IDE bridge: Missing ${envVar}`); } else { console.log(` āœ… IDE bridge: Has ${envVar} (${env[envVar]})`); } }); // Check command path for local development if (serverConfig.command === 'node' && serverConfig.args) { const scriptPath = serverConfig.args[0]; if (scriptPath && scriptPath.includes('mcp-bridge-server.js')) { console.log(` āœ… IDE bridge: Using local development path`); } } else if (serverConfig.command === 'npx') { console.log(` āš ļø IDE bridge: Using npx (may not work in local development)`); } } /** * Print validation summary */ printSummary(validConfigs, totalConfigs) { console.log('šŸ“‹ Validation Summary'); console.log('===================='); if (totalConfigs === 0) { console.log('āŒ No MCP configuration files found'); console.log(' Run "npm run setup:mcp-ide" to create them'); return; } console.log(`šŸ“Š Validated ${totalConfigs} configuration file(s)`); console.log(`āœ… Valid configurations: ${validConfigs}`); console.log(`āŒ Invalid configurations: ${totalConfigs - validConfigs}`); if (this.errors.length > 0) { console.log(`\nāŒ Errors (${this.errors.length}):`); this.errors.forEach(error => console.log(` • ${error}`)); } if (this.warnings.length > 0) { console.log(`\nāš ļø Warnings (${this.warnings.length}):`); this.warnings.forEach(warning => console.log(` • ${warning}`)); } if (this.errors.length === 0 && this.warnings.length === 0) { console.log('\nšŸŽ‰ All configurations are perfect!'); } else if (this.errors.length === 0) { console.log('\nāœ… All configurations are valid (with minor warnings)'); } console.log('\nšŸ’” Next Steps:'); if (this.errors.length > 0) { console.log(' 1. Fix the errors listed above'); console.log(' 2. Run this validator again'); } else { console.log(' 1. Restart your IDE to load the configuration'); console.log(' 2. Replace placeholder API keys with real ones'); console.log(' 3. Test the MCP integration in your IDE'); } } } // Run validation if called directly if (import.meta.url === `file://${process.argv[1]}`) { const validator = new MCPConfigValidator(); validator.validate().catch(console.error); } export default MCPConfigValidator;