UNPKG

@lanonasis/cli

Version:

LanOnasis Enterprise CLI - Memory as a Service, API Key Management, and Infrastructure Orchestration

155 lines (151 loc) 5.53 kB
#!/usr/bin/env node /** * CLI-Embedded MCP Server * Uses the same configuration and authentication as @lanonasis/cli v1.5.2+ * Can run standalone or be invoked by CLI commands */ import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; import { spawn } from 'child_process'; import { CLIConfig } from './utils/config.js'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); export class CLIMCPServer { config; constructor() { this.config = new CLIConfig(); } /** * Start MCP server using CLI configuration */ async start(options = {}) { await this.config.init(); const { mode = 'stdio', port = 3001, verbose = false, useRemote = this.config.shouldUseRemoteMCP() } = options; if (useRemote) { await this.startRemoteMCP(options); } else { await this.startLocalMCP(options); } } /** * Start local MCP server using CLI auth config */ async startLocalMCP(options) { const { mode, port, verbose } = options; // Path to CLI-aligned MCP server in submodule const mcpServerPath = join(__dirname, '../../../mcp-server/dist/cli-aligned-mcp-server.js'); const args = mode === 'http' ? ['--http'] : ['--stdio']; if (verbose) { console.error('🚀 Starting CLI-aligned MCP Server...'); console.error(`Mode: ${mode}`); console.error(`Config: ~/.maas/config.json`); console.error(`Auth: ${this.config.hasVendorKey() ? 'Vendor Key' : 'JWT Token'}`); } // Set environment variables from CLI config const env = { ...process.env, PORT: port?.toString(), MEMORY_API_URL: this.config.getApiUrl(), LANONASIS_VENDOR_KEY: this.config.getVendorKey(), LANONASIS_TOKEN: this.config.getToken(), MCP_VERBOSE: verbose ? 'true' : 'false', CLI_ALIGNED: 'true' }; const child = spawn('node', [mcpServerPath, ...args], { env, stdio: mode === 'stdio' ? ['pipe', 'pipe', 'inherit'] : 'inherit' }); if (mode === 'stdio') { // For stdio mode, pipe stdin/stdout for MCP protocol process.stdin.pipe(child.stdin); child.stdout.pipe(process.stdout); } child.on('error', (error) => { console.error('❌ MCP Server failed to start:', error.message); process.exit(1); }); child.on('exit', (code) => { if (code !== 0) { console.error(`❌ MCP Server exited with code ${code}`); process.exit(code || 1); } }); // Handle graceful shutdown process.on('SIGINT', () => { child.kill('SIGINT'); }); process.on('SIGTERM', () => { child.kill('SIGTERM'); }); } /** * Connect to remote MCP server */ async startRemoteMCP(options) { const { verbose } = options; if (verbose) { console.error('🌐 Connecting to remote MCP server...'); console.error(`URL: ${this.config.getMCPServerUrl()}`); } // For remote MCP, we'd need to implement a proxy or client // For now, fall back to local mode console.error('⚠️ Remote MCP not yet implemented, falling back to local mode'); await this.startLocalMCP({ ...options, useRemote: false }); } /** * Check if MCP server is available and configured */ async checkStatus() { await this.config.init(); return { available: true, // CLI always has MCP server available configured: this.config.hasVendorKey() || !!this.config.getToken(), authMethod: this.config.hasVendorKey() ? 'vendor_key' : this.config.getToken() ? 'jwt' : 'none', mode: this.config.shouldUseRemoteMCP() ? 'remote' : 'local' }; } } // Main execution when run as standalone script async function main() { const args = process.argv.slice(2); const server = new CLIMCPServer(); // Parse command line arguments const options = { mode: args.includes('--http') ? 'http' : 'stdio', port: parseInt(args.find(arg => arg.startsWith('--port='))?.split('=')[1] || '3001'), verbose: args.includes('--verbose') || args.includes('-v'), useRemote: args.includes('--remote') }; if (args.includes('--status')) { const status = await server.checkStatus(); console.log(JSON.stringify(status, null, 2)); return; } if (args.includes('--help')) { console.log(` CLI MCP Server - CLI-aligned Model Context Protocol server Usage: lanonasis-mcp-server [options] Options: --stdio Use stdio transport (default) --http Use HTTP transport --port=3001 HTTP port (default: 3001) --remote Use remote MCP server --verbose, -v Verbose logging --status Check server status --help Show this help Examples: lanonasis-mcp-server # Start stdio server lanonasis-mcp-server --http --port=3002 # Start HTTP server lanonasis-mcp-server --status # Check status `); return; } await server.start(options); } if (import.meta.url === `file://${process.argv[1]}`) { main().catch(console.error); } export default CLIMCPServer;