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

378 lines (319 loc) โ€ข 13.6 kB
#!/usr/bin/env node /** * Setup MCP IDE Integration * Automatically configures MCP for real IDE integration */ import fs from 'fs/promises'; import path from 'path'; import os from 'os'; import { fileURLToPath } from 'url'; import IDEDetection from '../src/bridge/ide-detection.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); class MCPIDESetup { constructor() { this.ideDetection = new IDEDetection(); this.projectRoot = process.cwd(); } /** * Main setup function */ async setup() { console.log('๐Ÿ”ง Setting up MCP IDE Integration...\n'); try { // Step 1: Detect available IDEs const detectionResults = await this.detectIDEs(); // Step 2: Choose best IDE or let user select const selectedIDE = await this.selectIDE(detectionResults); // Step 3: Configure MCP for selected IDE await this.configureMCP(selectedIDE); // Step 4: Test the configuration await this.testConfiguration(selectedIDE); console.log('\nโœ… MCP IDE Integration setup complete!'); this.printUsageInstructions(selectedIDE); } catch (error) { console.error('โŒ Setup failed:', error.message); process.exit(1); } } /** * Detect available IDEs */ async detectIDEs() { console.log('๐Ÿ” Detecting available IDEs...'); const availableIDEs = await this.ideDetection.detectAvailableIDEs(); const bestIDE = await this.ideDetection.getBestIDE(); console.log('\nDetection Results:'); Object.entries(availableIDEs).forEach(([ide, info]) => { if (info.detected) { console.log(` โœ… ${ide}: Found (confidence: ${Math.round(info.confidence * 100)}%)`); if (info.path) console.log(` Path: ${info.path}`); if (info.version) console.log(` Version: ${info.version}`); } else { console.log(` โŒ ${ide}: Not found`); } }); if (bestIDE.type) { console.log(`\n๐ŸŽฏ Best IDE detected: ${bestIDE.type} (${Math.round(bestIDE.info.confidence * 100)}% confidence)`); } else { console.log('\nโš ๏ธ No IDEs detected automatically'); } return { availableIDEs, bestIDE }; } /** * Select IDE for configuration */ async selectIDE(detectionResults) { const { availableIDEs, bestIDE } = detectionResults; // If we have a clear best choice, use it if (bestIDE.type && bestIDE.info.confidence > 0.8) { console.log(`\nโœจ Using detected IDE: ${bestIDE.type}`); return bestIDE; } // Otherwise, let user choose or provide options const detectedIDEs = Object.entries(availableIDEs) .filter(([_, info]) => info.detected) .map(([ide, info]) => ({ type: ide, info })); if (detectedIDEs.length === 0) { console.log('\nโš ๏ธ No IDEs detected. You can still configure manually.'); return { type: 'manual', info: { confidence: 0 } }; } if (detectedIDEs.length === 1) { console.log(`\nโœจ Using only detected IDE: ${detectedIDEs[0].type}`); return detectedIDEs[0]; } // For now, use the best one. In a real CLI, we'd prompt the user console.log(`\nโœจ Multiple IDEs detected, using best: ${bestIDE.type}`); return bestIDE; } /** * Configure MCP for selected IDE */ async configureMCP(selectedIDE) { console.log(`\nโš™๏ธ Configuring MCP for ${selectedIDE.type}...`); const mcpConfigs = await this.generateMCPConfigs(selectedIDE); // Write configuration files for (const [configPath, config] of Object.entries(mcpConfigs)) { await this.writeMCPConfig(configPath, config); } console.log('โœ… MCP configuration files created'); } /** * Generate MCP configurations for different IDEs */ async generateMCPConfigs(selectedIDE) { const projectRoot = this.projectRoot; const configs = {}; // Base configuration for Task Master AI (local development) const baseTaskMasterConfig = { command: "node", args: [path.join(projectRoot, "mcp-server/server.js")], env: { ANTHROPIC_API_KEY: "YOUR_ANTHROPIC_API_KEY_HERE", PERPLEXITY_API_KEY: "YOUR_PERPLEXITY_API_KEY_HERE", MODEL: "claude-3-5-sonnet-20241022", PERPLEXITY_MODEL: "sonar-pro", MAX_TOKENS: "64000", TEMPERATURE: "0.2", DEFAULT_SUBTASKS: "5", DEFAULT_PRIORITY: "medium", OPENAI_API_KEY: "YOUR_OPENAI_API_KEY_HERE", GOOGLE_API_KEY: "YOUR_GOOGLE_API_KEY_HERE", XAI_API_KEY: "YOUR_XAI_API_KEY_HERE", OPENROUTER_API_KEY: "YOUR_OPENROUTER_API_KEY_HERE", MISTRAL_API_KEY: "YOUR_MISTRAL_API_KEY_HERE", AZURE_OPENAI_API_KEY: "YOUR_AZURE_OPENAI_API_KEY_HERE", OLLAMA_API_KEY: "YOUR_OLLAMA_API_KEY_HERE" } }; // Base configuration for IDE Bridge (local development) const baseIDEBridgeConfig = { command: "node", args: [path.join(projectRoot, "src/bridge/mcp-bridge-server.js")], env: { BRIDGE_ENABLED: "true", BRIDGE_PORT: "8765", BRIDGE_HOST: "localhost", IDE_TYPE: selectedIDE.type, IDE_FALLBACK_TO_EXTERNAL: "true" } }; // IDE-specific configurations switch (selectedIDE.type) { case 'cursor': // Cursor uses mcpServers format configs['.cursor/mcp.json'] = { mcpServers: { "taskmaster-ai": baseTaskMasterConfig, "taskmaster-ide-bridge": { ...baseIDEBridgeConfig, env: { ...baseIDEBridgeConfig.env, CURSOR_API_PORT: selectedIDE.info.apiPort || "42000", CURSOR_API_HOST: "localhost" } } } }; break; case 'vscode': // VS Code uses servers format configs['.vscode/mcp.json'] = { servers: { "taskmaster-ai": baseTaskMasterConfig, "taskmaster-ide-bridge": { ...baseIDEBridgeConfig, env: { ...baseIDEBridgeConfig.env, VSCODE_EXTENSIONS_PATH: selectedIDE.info.extensionsPath || "" } } } }; break; case 'windsurf': // Windsurf uses mcpServers format configs['.windsurf/mcp.json'] = { mcpServers: { "taskmaster-ai": baseTaskMasterConfig, "taskmaster-ide-bridge": { ...baseIDEBridgeConfig, env: { ...baseIDEBridgeConfig.env, WINDSURF_CASCADE_PORT: selectedIDE.info.cascadePort || "43000", WINDSURF_CASCADE_HOST: "localhost" } } } }; break; default: // Generic configuration configs['mcp.json'] = { mcpServers: { "taskmaster-ai": baseTaskMasterConfig, "taskmaster-ide-bridge": baseIDEBridgeConfig } }; } return configs; } /** * Write MCP configuration file */ async writeMCPConfig(configPath, config) { const fullPath = path.join(this.projectRoot, configPath); const dir = path.dirname(fullPath); // Create directory if it doesn't exist try { await fs.mkdir(dir, { recursive: true }); } catch (error) { // Directory might already exist } // Check if file already exists let existingConfig = null; try { const existingContent = await fs.readFile(fullPath, 'utf8'); existingConfig = JSON.parse(existingContent); } catch (error) { // File doesn't exist or is invalid JSON } let finalConfig; if (existingConfig) { // Merge with existing configuration console.log(` ๐Ÿ“ Updating existing ${configPath}`); finalConfig = this.mergeConfigs(existingConfig, config); } else { // Create new configuration console.log(` ๐Ÿ“ Creating new ${configPath}`); finalConfig = config; } // Write the configuration await fs.writeFile(fullPath, JSON.stringify(finalConfig, null, 2)); console.log(` โœ… ${configPath} configured`); } /** * Merge MCP configurations */ mergeConfigs(existing, newConfig) { const merged = { ...existing }; // Merge servers/mcpServers const serversKey = newConfig.mcpServers ? 'mcpServers' : 'servers'; if (!merged[serversKey]) { merged[serversKey] = {}; } Object.assign(merged[serversKey], newConfig[serversKey]); return merged; } /** * Test the configuration */ async testConfiguration(selectedIDE) { console.log('\n๐Ÿงช Testing MCP configuration...'); try { // Basic validation - check if files exist const expectedPaths = this.getExpectedConfigPaths(selectedIDE.type); for (const configPath of expectedPaths) { const fullPath = path.join(this.projectRoot, configPath); try { await fs.access(fullPath); console.log(` โœ… ${configPath} exists`); } catch (error) { console.log(` โŒ ${configPath} missing`); } } console.log('โœ… Configuration test completed'); } catch (error) { console.log('โš ๏ธ Configuration test failed:', error.message); } } /** * Get expected config paths for IDE type */ getExpectedConfigPaths(ideType) { switch (ideType) { case 'cursor': return ['.cursor/mcp.json']; case 'vscode': return ['.vscode/mcp.json']; case 'windsurf': return ['.windsurf/mcp.json']; default: return ['mcp.json']; } } /** * Print usage instructions */ printUsageInstructions(selectedIDE) { console.log('\n๐Ÿ“– Usage Instructions:'); console.log('======================'); console.log('\n1. **Restart your IDE** to load the new MCP configuration'); console.log('\n2. **Set your API keys** in the MCP configuration file:'); const configPaths = this.getExpectedConfigPaths(selectedIDE.type); configPaths.forEach(path => { console.log(` - Edit ${path}`); }); console.log(' - Replace placeholder values with your actual API keys'); console.log('\n3. **Test the integration** using MCP tools:'); console.log(' - detect_ide: Detect available IDEs'); console.log(' - connect_ide: Connect to your IDE agent'); console.log(' - ide_generate_text: Generate text using your IDE'); console.log(' - ide_status: Check connection status'); console.log('\n4. **Verify real IDE connection**:'); console.log(' - The system will try to connect to your real IDE first'); console.log(' - If real connection fails, it will fallback to mock responses'); console.log(' - Check the logs to see which mode is being used'); console.log('\n5. **Troubleshooting**:'); console.log(' - Ensure your IDE is running'); console.log(' - Check that API access is enabled in your IDE settings'); console.log(' - Verify the correct ports are configured'); console.log('\n๐ŸŽ‰ You\'re ready to use real IDE integration with Task Master!'); } } // Run setup if called directly if (import.meta.url === `file://${process.argv[1]}`) { const setup = new MCPIDESetup(); setup.setup().catch(console.error); } export default MCPIDESetup;