#!/usr/bin/env node
/**
* Global CLI command for MCP Self-Learning Server
* Provides system-wide access to learning tools and management
*/
import { program } from 'commander';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Import the client library
import SelfLearningClient from '../lib/self-learning-client.js';
program
.name('mcp-learn')
.description('MCP Self-Learning Server CLI')
.version('1.0.0');
// Server management commands
program
.command('start')
.description('Start the MCP Self-Learning Server')
.option('-d, --dev', 'Start in development mode')
.option('-p, --port <port>', 'API server port', '8765')
.action(async (options) => {
const { spawn } = await import('child_process');
const serverPath = path.join(__dirname, '..', 'mcp-self-learning-server.js');
const env = { ...process.env };
if (options.dev) {
env.NODE_ENV = 'development';
}
if (options.port) {
env.MCP_LEARN_PORT = options.port;
}
console.log('π Starting MCP Self-Learning Server...');
const server = spawn('node', [serverPath], {
env,
stdio: 'inherit'
});
server.on('exit', (code) => {
console.log(`Server exited with code ${code}`);
});
});
program
.command('api')
.description('Start the REST API server')
.option('-p, --port <port>', 'API server port', '8765')
.option('--host <host>', 'API server host', 'localhost')
.action(async (options) => {
const { spawn } = await import('child_process');
const apiPath = path.join(__dirname, '..', 'api', 'rest-server.js');
const env = {
...process.env,
MCP_LEARN_PORT: options.port,
MCP_LEARN_HOST: options.host
};
console.log(`π Starting REST API server on ${options.host}:${options.port}...`);
const server = spawn('node', [apiPath], {
env,
stdio: 'inherit'
});
server.on('exit', (code) => {
console.log(`API server exited with code ${code}`);
});
});
// Learning commands
program
.command('analyze')
.description('Analyze a pattern for learning')
.requiredOption('-t, --type <type>', 'Pattern type (e.g., tool_usage, interaction)')
.requiredOption('-i, --input <input>', 'Input data')
.requiredOption('-o, --output <output>', 'Output data')
.option('-c, --context <context>', 'Context data (JSON)', '{}')
.option('--success', 'Mark as successful', true)
.option('--duration <ms>', 'Duration in milliseconds', '0')
.action(async (options) => {
try {
const client = new SelfLearningClient();
const interaction = {
type: options.type,
input: options.input,
output: options.output,
context: JSON.parse(options.context),
performance: { duration: parseInt(options.duration) },
success: options.success
};
console.log('π§ Analyzing pattern...');
const result = await client.analyzePattern(interaction);
console.log('β
Pattern analyzed:', JSON.stringify(result, null, 2));
} catch (error) {
console.error('β Error:', error.message);
process.exit(1);
}
});
program
.command('insights')
.description('Get learning insights and analytics')
.option('-f, --format <format>', 'Output format (json, table)', 'table')
.action(async (options) => {
try {
const client = new SelfLearningClient();
console.log('π Fetching insights...');
const result = await client.getInsights();
if (options.format === 'json') {
console.log(JSON.stringify(result, null, 2));
} else {
displayInsightsTable(result.insights);
}
} catch (error) {
console.error('β Error:', error.message);
process.exit(1);
}
});
program
.command('export')
.description('Export learned knowledge')
.option('-f, --format <format>', 'Export format (json, markdown)', 'json')
.option('-o, --output <file>', 'Output file path')
.action(async (options) => {
try {
const client = new SelfLearningClient();
console.log(`π¦ Exporting knowledge in ${options.format} format...`);
const result = await client.exportKnowledge({ format: options.format });
console.log('β
Knowledge exported:', result.path);
if (options.output && result.path !== options.output) {
const fs = await import('fs/promises');
await fs.copyFile(result.path, options.output);
console.log(`π Copied to: ${options.output}`);
}
} catch (error) {
console.error('β Error:', error.message);
process.exit(1);
}
});
program
.command('status')
.description('Check server and learning status')
.option('-v, --verbose', 'Show detailed information')
.action(async (options) => {
try {
const client = new SelfLearningClient();
console.log('π Checking status...');
const status = await client.getStatus();
displayStatusTable(status, options.verbose);
} catch (error) {
console.error('β Error:', error.message);
console.error(' Make sure the MCP Self-Learning Server is running');
process.exit(1);
}
});
program
.command('monitor')
.description('Real-time monitoring of learning activity')
.option('-i, --interval <seconds>', 'Update interval', '5')
.option('-d, --details', 'Show detailed information')
.action(async (options) => {
const { spawn } = await import('child_process');
const monitorPath = path.join(__dirname, '..', 'tools', 'monitor.js');
const args = [];
if (options.interval !== '5') {
args.push('--interval', options.interval);
}
if (options.details) {
args.push('--details');
}
console.log('π Starting real-time monitoring...');
const monitor = spawn('node', [monitorPath, ...args], {
stdio: 'inherit'
});
monitor.on('exit', (code) => {
console.log(`Monitor exited with code ${code}`);
});
});
program
.command('health')
.description('Run comprehensive health check')
.action(async () => {
const { spawn } = await import('child_process');
const healthPath = path.join(__dirname, '..', 'tools', 'health-check.js');
console.log('π₯ Running health check...');
const health = spawn('node', [healthPath], {
stdio: 'inherit'
});
health.on('exit', (code) => {
process.exit(code);
});
});
// Integration commands
program
.command('integrate')
.description('Integrate with other system components')
.option('--claudio', 'Integrate with Claudio orchestrator')
.option('--claudia', 'Integrate with Claudia voice assistant')
.option('--all', 'Integrate with all available systems')
.action(async (options) => {
console.log('π Setting up integrations...');
if (options.all || options.claudio) {
console.log(' π€ Configuring Claudio integration...');
await setupClaudioIntegration();
}
if (options.all || options.claudia) {
console.log(' π€ Configuring Claudia integration...');
await setupClaudiaIntegration();
}
console.log('β
Integration setup complete');
});
// Helper functions
function displayInsightsTable(insights) {
console.log('\nπ Learning Insights:');
console.log('=====================');
if (insights.topPatterns?.length > 0) {
console.log('\nπ Top Patterns:');
insights.topPatterns.forEach((pattern, i) => {
console.log(` ${i + 1}. ${pattern.type} (confidence: ${(pattern.confidence * 100).toFixed(1)}%)`);
});
}
if (insights.performanceMetrics) {
console.log('\nβ‘ Performance:');
console.log(` Average Response Time: ${insights.performanceMetrics.averageResponseTime}ms`);
console.log(` Success Rate: ${(insights.performanceMetrics.successRate * 100).toFixed(1)}%`);
console.log(` Total Interactions: ${insights.performanceMetrics.totalInteractions}`);
}
if (insights.recommendations?.length > 0) {
console.log('\nπ‘ Recommendations:');
insights.recommendations.forEach(rec => {
console.log(` β’ ${rec}`);
});
}
}
function displayStatusTable(status, verbose) {
console.log('\nπ System Status:');
console.log('=================');
console.log(`π Server: ${status.running ? 'β
Running' : 'β Stopped'}`);
if (status.uptime) {
console.log(`β±οΈ Uptime: ${formatUptime(status.uptime)}`);
}
if (status.learning) {
console.log(`π§ Learning Engine: ${status.learning.active ? 'β
Active' : 'β Inactive'}`);
console.log(`π Patterns: ${status.learning.patterns}`);
console.log(`π Learning Cycles: ${status.learning.cycles}`);
}
if (status.persistence) {
console.log(`πΎ Persistence: ${status.persistence.enabled ? 'β
Enabled' : 'β Disabled'}`);
if (status.persistence.lastSave) {
console.log(`πΏ Last Save: ${new Date(status.persistence.lastSave).toLocaleString()}`);
}
}
if (verbose && status.memory) {
console.log(`\nπ» Memory Usage:`);
console.log(` RSS: ${Math.round(status.memory.rss / 1024 / 1024)}MB`);
console.log(` Heap: ${Math.round(status.memory.heapUsed / 1024 / 1024)}MB`);
}
}
function formatUptime(ms) {
const seconds = Math.floor(ms / 1000);
const hours = Math.floor(seconds / 3600);
const minutes = Math.floor((seconds % 3600) / 60);
const secs = seconds % 60;
if (hours > 0) {
return `${hours}h ${minutes}m ${secs}s`;
} else if (minutes > 0) {
return `${minutes}m ${secs}s`;
} else {
return `${secs}s`;
}
}
async function setupClaudioIntegration() {
// Implementation for Claudio integration will be added later
console.log(' β Claudio integration configured');
}
async function setupClaudiaIntegration() {
// Implementation for Claudia integration will be added later
console.log(' β Claudia integration configured');
}
// Parse command line arguments
program.parse();