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

353 lines (299 loc) • 12.1 kB
#!/usr/bin/env node /** * Automatic MCP Setup for task-engine-ai-core * * This script automatically configures MCP for IDEs when the package is installed. * It detects the IDE, finds the project root, and creates the appropriate MCP configuration. * * @version 0.3.4 * @author Task Engine AI Team */ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'fs'; import { dirname, resolve, join } from 'path'; import { execSync } from 'child_process'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); class AutoMCPSetup { constructor() { this.packageVersion = '0.3.7'; this.isGlobalInstall = false; this.packageRoot = ''; this.projectRoot = ''; this.ideConfigs = { cursor: '.cursor/mcp.json', vscode: '.vscode/mcp.json', claude: 'claude_desktop_config.json' }; } /** * Main auto-setup function */ async autoSetup() { console.log('šŸš€ Task Engine AI Core - Automatic MCP Setup v0.3.4'); console.log('====================================================\n'); try { // Detect installation type and paths await this.detectInstallation(); // Detect IDE and project const ide = this.detectIDE(); const projectRoot = this.findProjectRoot(); console.log(`šŸ“± Detected IDE: ${ide}`); console.log(`šŸ“ Project root: ${projectRoot}`); console.log(`šŸ“¦ Package root: ${this.packageRoot}`); console.log(`šŸŒ Installation type: ${this.isGlobalInstall ? 'Global' : 'Local'}\n`); // Create MCP configuration await this.createAutoMCPConfig(ide, projectRoot); // Initialize Task Engine if needed await this.initializeTaskEngine(projectRoot); console.log('\nāœ… Automatic MCP setup completed successfully!'); console.log('\nšŸ“š Next steps:'); console.log('1. Restart your IDE to load the new MCP configuration'); console.log('2. Test the connection by asking Claude to list tasks'); console.log('3. Start using Task Engine AI through MCP!'); } catch (error) { console.error('\nāŒ Auto-setup failed:', error.message); console.error('\nšŸ”§ Manual setup available:'); console.error('Run: npx task-engine-ai-core setup-mcp'); process.exit(1); } } /** * Detect installation type and package location */ async detectInstallation() { try { // Get global npm root const globalPath = execSync('npm root -g', { encoding: 'utf8' }).trim(); // Check if task-engine-ai-core is installed globally try { const globalPackagePath = join(globalPath, 'task-engine-ai-core'); if (existsSync(globalPackagePath)) { this.isGlobalInstall = true; this.packageRoot = globalPackagePath; console.log(`šŸ“¦ Using global package: ${this.packageRoot}`); return; } } catch (error) { // Global package not found, continue to local detection } // Fallback to local package detection const currentPath = resolve(__dirname, '..'); this.isGlobalInstall = false; this.packageRoot = currentPath; console.log(`šŸ“¦ Using local package: ${this.packageRoot}`); } catch (error) { // Fallback to current directory this.packageRoot = resolve(__dirname, '..'); this.isGlobalInstall = false; console.log(`šŸ“¦ Package location (fallback): ${this.packageRoot}`); } } /** * Detect the current IDE */ detectIDE() { const cwd = process.cwd(); // Check for IDE-specific directories if (existsSync(join(cwd, '.cursor'))) return 'cursor'; if (existsSync(join(cwd, '.vscode'))) return 'vscode'; // Check environment variables if (process.env.CURSOR_USER_DATA) return 'cursor'; if (process.env.VSCODE_PID) return 'vscode'; // Check parent directories let currentDir = cwd; for (let i = 0; i < 5; i++) { if (existsSync(join(currentDir, '.cursor'))) return 'cursor'; if (existsSync(join(currentDir, '.vscode'))) return 'vscode'; const parentDir = dirname(currentDir); if (parentDir === currentDir) break; currentDir = parentDir; } // Default to cursor if no specific IDE detected return 'cursor'; } /** * Find the project root directory */ findProjectRoot() { // Check environment variable first if (process.env.TASK_MASTER_PROJECT_ROOT && existsSync(process.env.TASK_MASTER_PROJECT_ROOT)) { return process.env.TASK_MASTER_PROJECT_ROOT; } // Start from current working directory let currentDir = process.cwd(); // Look for project indicators const projectIndicators = [ 'package.json', '.git', '.taskmaster', 'tsconfig.json', 'pyproject.toml', 'Cargo.toml', 'go.mod' ]; // Search up the directory tree for (let i = 0; i < 10; i++) { // Check for project indicators for (const indicator of projectIndicators) { if (existsSync(join(currentDir, indicator))) { return currentDir; } } const parentDir = dirname(currentDir); if (parentDir === currentDir) break; currentDir = parentDir; } // Fallback to current working directory return process.cwd(); } /** * Create automatic MCP configuration */ async createAutoMCPConfig(ide, projectRoot) { console.log(`\nāš™ļø Creating automatic MCP configuration for ${ide}...`); const configPath = this.ideConfigs[ide]; const configDir = dirname(configPath); const fullConfigPath = join(projectRoot, configPath); const fullConfigDir = join(projectRoot, configDir); // Create directory if it doesn't exist if (!existsSync(fullConfigDir)) { mkdirSync(fullConfigDir, { recursive: true }); console.log(`šŸ“ Created directory: ${configDir}`); } // Generate configuration const config = this.generateAutoMCPConfig(ide, projectRoot); // Merge with existing configuration if it exists let finalConfig = config; if (existsSync(fullConfigPath)) { try { const existingConfig = JSON.parse(readFileSync(fullConfigPath, 'utf8')); finalConfig = this.mergeConfigurations(existingConfig, config, ide); console.log(`šŸ”„ Merged with existing configuration`); } catch (error) { console.log(`āš ļø Could not parse existing config, creating new one`); } } // Write configuration file writeFileSync(fullConfigPath, JSON.stringify(finalConfig, null, 2)); console.log(`āœ… Created/updated MCP configuration: ${configPath}`); } /** * Generate automatic MCP configuration */ generateAutoMCPConfig(ide, projectRoot) { // Use the simple and efficient npx approach like taskmaster-ai const serverCommand = 'npx'; const serverArgs = ['-y', '--package=task-engine-ai-core', 'task-master-mcp']; const baseEnv = { TASK_ENGINE_VERSION: this.packageVersion, TASK_ENGINE_ENVIRONMENT: 'development', TASK_ENGINE_DEBUG: 'true', TASK_ENGINE_LOG_LEVEL: 'info', MODEL: 'claude-3-5-sonnet-20241022', MAX_TOKENS: '64000', TEMPERATURE: '0.2', DEFAULT_SUBTASKS: '5', DEFAULT_PRIORITY: 'medium' }; const serverConfig = { command: serverCommand, args: serverArgs, env: baseEnv }; console.log(`šŸ”§ Using npx approach: ${serverCommand} ${serverArgs.join(' ')}`); console.log(`šŸ“ Project root: ${projectRoot}`); if (ide === 'cursor') { return { mcpServers: { 'task-engine-ai-core': serverConfig } }; } else if (ide === 'vscode') { return { servers: { 'task-engine-ai-core': { ...serverConfig, env: { ...baseEnv, MODEL: 'claude-3-5-sonnet-20241022', MAX_TOKENS: '64000', TEMPERATURE: '0.2' } } } }; } else { // Claude Desktop configuration return { mcpServers: { 'task-engine-ai-core': serverConfig } }; } } /** * Merge new configuration with existing configuration */ mergeConfigurations(existing, newConfig, ide) { const serverKey = ide === 'vscode' ? 'servers' : 'mcpServers'; if (!existing[serverKey]) { existing[serverKey] = {}; } // Update or add the task-engine-ai-core configuration existing[serverKey]['task-engine-ai-core'] = newConfig[serverKey]['task-engine-ai-core']; return existing; } /** * Initialize Task Engine if needed */ async initializeTaskEngine(projectRoot) { const taskMasterDir = join(projectRoot, '.taskmaster'); if (!existsSync(taskMasterDir)) { console.log('\nšŸ”§ Initializing Task Engine project...'); try { // Create basic Task Engine structure mkdirSync(taskMasterDir, { recursive: true }); mkdirSync(join(taskMasterDir, 'tasks'), { recursive: true }); mkdirSync(join(taskMasterDir, 'docs'), { recursive: true }); mkdirSync(join(taskMasterDir, 'reports'), { recursive: true }); // Create basic configuration const basicConfig = { version: this.packageVersion, projectRoot: projectRoot, initialized: new Date().toISOString(), autoSetup: true }; writeFileSync( join(taskMasterDir, 'config.json'), JSON.stringify(basicConfig, null, 2) ); // Create empty tasks file const emptyTasks = { version: "1.0", tasks: [], metadata: { created: new Date().toISOString(), autoGenerated: true } }; writeFileSync( join(taskMasterDir, 'tasks', 'tasks.json'), JSON.stringify(emptyTasks, null, 2) ); console.log('āœ… Task Engine project initialized'); } catch (error) { console.log(`āš ļø Could not initialize Task Engine: ${error.message}`); } } } } // Run auto-setup if called directly if (import.meta.url === `file://${process.argv[1]}`) { const autoSetup = new AutoMCPSetup(); autoSetup.autoSetup().catch(error => { console.error('Auto-setup failed:', error); process.exit(1); }); } export default AutoMCPSetup;