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
JavaScript
/**
* 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;