UNPKG

lmstudio-mcp-server

Version:

LM Studio MCP server with concurrent multi-agent support and memory safety

250 lines (207 loc) 8.35 kB
#!/usr/bin/env node /** * LM Studio MCP Server - NPM Package Entry Point * This script downloads and runs the LM Studio MCP server */ const { spawn } = require('child_process'); const path = require('path'); const fs = require('fs'); const https = require('https'); const { URL } = require('url'); // Configuration const CONFIG = { GITHUB_REPO: 'samscarrow/lmstudio-mcp-consolidated', PYTHON_SCRIPT: 'lmstudio_bridge.py', INSTALL_DIR: path.join(require('os').homedir(), '.lmstudio-mcp'), DEFAULT_API_BASE: 'http://localhost:1234/v1' }; class LMStudioMCPRunner { constructor() { this.installDir = CONFIG.INSTALL_DIR; this.scriptPath = path.join(this.installDir, CONFIG.PYTHON_SCRIPT); } async log(message, type = 'info') { const timestamp = new Date().toISOString(); const prefix = type === 'error' ? '❌' : type === 'warn' ? '⚠️' : 'ℹ️'; console.log(`${prefix} [${timestamp}] ${message}`); } async checkPython() { return new Promise((resolve) => { const python = spawn('python3', ['--version'], { stdio: 'pipe' }); python.on('close', (code) => resolve(code === 0)); python.on('error', () => resolve(false)); }); } async downloadFile(url, destPath) { return new Promise((resolve, reject) => { const file = fs.createWriteStream(destPath); https.get(url, (response) => { if (response.statusCode === 302 || response.statusCode === 301) { // Handle redirect return this.downloadFile(response.headers.location, destPath) .then(resolve) .catch(reject); } if (response.statusCode !== 200) { reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`)); return; } response.pipe(file); file.on('finish', () => resolve()); file.on('error', reject); }).on('error', reject); }); } async ensureInstalled() { // Check if already installed if (fs.existsSync(this.scriptPath)) { this.log('LM Studio MCP server already installed'); return true; } this.log('Installing LM Studio MCP server...'); // Create install directory if (!fs.existsSync(this.installDir)) { fs.mkdirSync(this.installDir, { recursive: true }); } // Download main files const filesToDownload = [ 'lmstudio_bridge.py', 'requirements.txt', 'README.md' ]; for (const file of filesToDownload) { try { const url = `https://raw.githubusercontent.com/${CONFIG.GITHUB_REPO}/main/${file}`; const destPath = path.join(this.installDir, file); this.log(`Downloading ${file}...`); await this.downloadFile(url, destPath); } catch (error) { this.log(`Failed to download ${file}: ${error.message}`, 'error'); // Continue with other files } } // Install Python dependencies try { this.log('Installing Python dependencies...'); const pip = spawn('pip3', ['install', '-r', path.join(this.installDir, 'requirements.txt')], { stdio: 'inherit' }); await new Promise((resolve, reject) => { pip.on('close', (code) => { if (code === 0) resolve(); else reject(new Error(`pip install failed with code ${code}`)); }); pip.on('error', reject); }); this.log('✅ Installation complete!'); return true; } catch (error) { this.log(`Failed to install dependencies: ${error.message}`, 'error'); this.log('You may need to install dependencies manually:', 'warn'); this.log(` pip3 install -r ${path.join(this.installDir, 'requirements.txt')}`, 'warn'); return true; // Continue anyway } } async run() { try { // Check prerequisites if (!await this.checkPython()) { this.log('Python 3 is required but not found. Please install Python 3.7+', 'error'); this.log('Visit: https://python.org/downloads', 'error'); process.exit(1); } // Ensure installed await this.ensureInstalled(); // Check if script exists if (!fs.existsSync(this.scriptPath)) { this.log('LM Studio MCP script not found. Installation may have failed.', 'error'); process.exit(1); } // Set environment variables const env = { ...process.env, LMSTUDIO_API_BASE: process.env.LMSTUDIO_API_BASE || CONFIG.DEFAULT_API_BASE, LOG_LEVEL: process.env.LOG_LEVEL || 'INFO' }; this.log('Starting LM Studio MCP server...'); this.log(`API Base: ${env.LMSTUDIO_API_BASE}`); // Run the Python script const python = spawn('python3', [this.scriptPath], { env, stdio: 'inherit', cwd: this.installDir }); // Handle process events python.on('error', (error) => { this.log(`Failed to start server: ${error.message}`, 'error'); process.exit(1); }); python.on('close', (code) => { this.log(`Server exited with code ${code}`); process.exit(code); }); // Handle termination signals process.on('SIGINT', () => { this.log('Shutting down...'); python.kill('SIGINT'); }); process.on('SIGTERM', () => { this.log('Shutting down...'); python.kill('SIGTERM'); }); } catch (error) { this.log(`Error: ${error.message}`, 'error'); process.exit(1); } } } // CLI argument parsing function showHelp() { console.log(` LM Studio MCP Server Usage: npx @samscarrow/lmstudio-mcp [options] Options: --help, -h Show this help message --version, -v Show version information --api-base <url> Set LM Studio API base URL (default: http://localhost:1234/v1) --log-level <level> Set log level (DEBUG, INFO, WARNING, ERROR) --install-dir <path> Set custom installation directory Environment Variables: LMSTUDIO_API_BASE LM Studio API endpoint LOG_LEVEL Logging level Examples: npx @samscarrow/lmstudio-mcp npx @samscarrow/lmstudio-mcp --api-base http://192.168.1.100:1234/v1 LMSTUDIO_API_BASE=http://localhost:1234/v1 npx @samscarrow/lmstudio-mcp `); } // Main execution if (require.main === module) { const args = process.argv.slice(2); // Handle command line arguments if (args.includes('--help') || args.includes('-h')) { showHelp(); process.exit(0); } if (args.includes('--version') || args.includes('-v')) { const pkg = require('../package.json'); console.log(`${pkg.name} v${pkg.version}`); process.exit(0); } // Parse other arguments const apiBaseIndex = args.indexOf('--api-base'); if (apiBaseIndex !== -1 && apiBaseIndex + 1 < args.length) { process.env.LMSTUDIO_API_BASE = args[apiBaseIndex + 1]; } const logLevelIndex = args.indexOf('--log-level'); if (logLevelIndex !== -1 && logLevelIndex + 1 < args.length) { process.env.LOG_LEVEL = args[logLevelIndex + 1]; } const installDirIndex = args.indexOf('--install-dir'); if (installDirIndex !== -1 && installDirIndex + 1 < args.length) { CONFIG.INSTALL_DIR = args[installDirIndex + 1]; } // Run the server const runner = new LMStudioMCPRunner(); runner.run(); }