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