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