UNPKG

universal-mcp-orchestration

Version:

šŸ† UNIVERSAL AI DEVELOPMENT SYSTEM: 100% OPTIMIZED! Complete plug-and-play MCP orchestration with 20/20 agents operational, 101MB optimization, zero-error operations, and enterprise-grade reliability. Works with ANY project type at ANY scale.

337 lines (286 loc) • 10.6 kB
#!/usr/bin/env node /** * Dynamic Agent Loader for MCP Orchestration * Optimizes context usage by loading agents based on profiles * Part of Sprint-38: MCP Context Optimization */ const fs = require('fs'); const path = require('path'); const { execSync } = require('child_process'); class AgentLoader { constructor() { this.profilesDir = path.join(__dirname, 'profiles'); this.configPath = path.join(process.cwd(), '.claude', 'settings.local.json'); this.currentProfile = null; this.loadedAgents = []; } /** * Load a specific profile * @param {string} profileName - Name of the profile (minimal, standard, full) */ async loadProfile(profileName = 'standard') { console.log(`\nšŸš€ Loading MCP Agent Profile: ${profileName}`); try { // Load profile configuration const profilePath = path.join(this.profilesDir, `${profileName}.json`); if (!fs.existsSync(profilePath)) { throw new Error(`Profile '${profileName}' not found`); } const profile = JSON.parse(fs.readFileSync(profilePath, 'utf8')); this.currentProfile = profile; // Update Claude settings this.updateClaudeSettings(profile); // Display profile info this.displayProfileInfo(profile); // Verify agents are connected await this.verifyAgents(profile.agents); console.log(`\nāœ… Profile '${profileName}' loaded successfully!`); console.log(`šŸ“Š Estimated token usage: ~${profile.estimatedTokens.toLocaleString()} tokens`); return profile; } catch (error) { console.error(`āŒ Error loading profile: ${error.message}`); throw error; } } /** * Update Claude settings.local.json with selected agents */ updateClaudeSettings(profile) { let settings = {}; // Load existing settings if they exist if (fs.existsSync(this.configPath)) { settings = JSON.parse(fs.readFileSync(this.configPath, 'utf8')); } // Update enabled MCP servers based on profile settings.enabledMcpjsonServers = profile.agents; // Update MCP configuration settings.mcp = { ...settings.mcp, currentProfile: profile.name, profileVersion: profile.version, estimatedTokens: profile.estimatedTokens, autoUseAgents: true, preferredAgentOrder: profile.agents.slice(0, 5), // Top 5 as preferred agentSelectionStrategy: 'profile-based', autoConnectOnStartup: true, reconnectOnFailure: true, maxRetries: 3 }; // Add profile metadata settings.profileMetadata = { name: profile.name, description: profile.description, loadedAt: new Date().toISOString(), agentCount: profile.agents.length, estimatedTokens: profile.estimatedTokens }; // Ensure directory exists const settingsDir = path.dirname(this.configPath); if (!fs.existsSync(settingsDir)) { fs.mkdirSync(settingsDir, { recursive: true }); } // Write updated settings fs.writeFileSync( this.configPath, JSON.stringify(settings, null, 2), 'utf8' ); console.log(`šŸ“ Updated Claude settings for '${profile.name}' profile`); } /** * Display profile information */ displayProfileInfo(profile) { console.log(`\nšŸ“‹ Profile: ${profile.name}`); console.log(`šŸ“„ Description: ${profile.description}`); console.log(`\nšŸ¤– Loading ${profile.agents.length} agents:`); profile.agents.forEach((agent, index) => { const rationale = profile.rationale[agent] || 'Specialized agent'; console.log(` ${index + 1}. ${agent}: ${rationale}`); }); if (profile.useCases && profile.useCases.length > 0) { console.log(`\n✨ Best for:`); profile.useCases.forEach(useCase => { console.log(` • ${useCase}`); }); } if (profile.limitations && profile.limitations.length > 0) { console.log(`\nāš ļø Limitations:`); profile.limitations.forEach(limitation => { console.log(` • ${limitation}`); }); } } /** * Verify agents are properly connected */ async verifyAgents(agents) { console.log(`\nšŸ” Verifying agent connections...`); try { // Run claude mcp list to check connections const output = execSync('claude mcp list', { encoding: 'utf8' }); const connectedAgents = output.split('\n') .filter(line => line.includes(':')) .map(line => line.split(':')[0].trim()); let verified = 0; let missing = []; agents.forEach(agent => { if (connectedAgents.some(connected => connected.includes(agent))) { verified++; } else { missing.push(agent); } }); if (verified === agents.length) { console.log(`āœ… All ${verified} agents verified and connected`); } else { console.log(`āš ļø ${verified}/${agents.length} agents connected`); if (missing.length > 0) { console.log(`āŒ Missing agents: ${missing.join(', ')}`); console.log(`šŸ’” Run 'npm run fix-agents' to restart MCP servers`); } } this.loadedAgents = agents; return verified === agents.length; } catch (error) { console.error(`āš ļø Could not verify agents: ${error.message}`); return false; } } /** * Analyze current context usage */ analyzeContext() { console.log(`\nšŸ“Š Analyzing current MCP context usage...`); try { const output = execSync('claude doctor', { encoding: 'utf8' }); // Parse context usage from doctor output const contextMatch = output.match(/Large MCP tools context \(~([\d,]+) tokens/); if (contextMatch) { const tokens = parseInt(contextMatch[1].replace(/,/g, '')); console.log(`\nšŸ“ˆ Current context usage: ~${tokens.toLocaleString()} tokens`); if (tokens > 25000) { console.log(`āš ļø WARNING: Context usage exceeds recommended limit (25,000 tokens)`); console.log(`šŸ’” Recommendation: Use 'minimal' or 'standard' profile`); } else if (tokens > 15000) { console.log(`šŸ“Œ Context usage is moderate`); console.log(`šŸ’” Consider 'minimal' profile for better performance`); } else { console.log(`āœ… Context usage is optimal`); } return tokens; } } catch (error) { console.error(`Could not analyze context: ${error.message}`); } return null; } /** * Auto-select best profile based on project */ async autoSelectProfile() { console.log(`\nšŸŽÆ Auto-selecting optimal profile...`); // Check for package.json to determine project type const packageJsonPath = path.join(process.cwd(), 'package.json'); let projectType = 'general'; if (fs.existsSync(packageJsonPath)) { const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8')); const deps = { ...packageJson.dependencies, ...packageJson.devDependencies }; // Detect project type if (deps.react || deps.vue || deps.angular) { projectType = 'frontend'; } if (deps.express || deps.fastapi || deps.django) { projectType = 'backend'; } if ((deps.react || deps.vue) && (deps.express || deps.fastapi)) { projectType = 'fullstack'; } } // Select profile based on project type let selectedProfile = 'minimal'; switch (projectType) { case 'fullstack': selectedProfile = 'standard'; console.log(`šŸŽÆ Detected full-stack project → Using 'standard' profile`); break; case 'frontend': case 'backend': selectedProfile = 'standard'; console.log(`šŸŽÆ Detected ${projectType} project → Using 'standard' profile`); break; default: selectedProfile = 'minimal'; console.log(`šŸŽÆ General project → Using 'minimal' profile for optimal performance`); } return this.loadProfile(selectedProfile); } /** * Show current status */ showStatus() { console.log(`\nšŸ“Š MCP Agent Loader Status`); console.log(`═══════════════════════════`); if (this.currentProfile) { console.log(`šŸ“‹ Current Profile: ${this.currentProfile.name}`); console.log(`šŸ¤– Loaded Agents: ${this.loadedAgents.length}`); console.log(`šŸ“ˆ Estimated Tokens: ~${this.currentProfile.estimatedTokens.toLocaleString()}`); console.log(`\nšŸ”§ Active Agents:`); this.loadedAgents.forEach((agent, index) => { console.log(` ${index + 1}. ${agent}`); }); } else { console.log(`āŒ No profile currently loaded`); console.log(`šŸ’” Run 'npm run mcp:minimal' or 'npm run mcp:standard' to load a profile`); } // Show current context usage this.analyzeContext(); } } // CLI execution if (require.main === module) { const loader = new AgentLoader(); const args = process.argv.slice(2); const command = args[0]; switch (command) { case 'minimal': loader.loadProfile('minimal'); break; case 'standard': loader.loadProfile('standard'); break; case 'full': loader.loadProfile('full'); break; case 'auto': loader.autoSelectProfile(); break; case 'analyze': loader.analyzeContext(); break; case 'status': loader.showStatus(); break; default: console.log(` šŸš€ MCP Agent Loader - Optimize Context Usage Usage: node agent-loader.js [command] Commands: minimal - Load minimal profile (4 agents, ~10k tokens) standard - Load standard profile (10 agents, ~25k tokens) full - Load full profile (20 agents, ~52k tokens) auto - Auto-select best profile for project analyze - Analyze current context usage status - Show current profile and agents Examples: node agent-loader.js minimal # For quick tasks node agent-loader.js standard # For development node agent-loader.js auto # Let system decide `); } } module.exports = AgentLoader;