Skip to main content
Glama
start-server.js6.76 kB
const { spawn } = require('child_process'); const path = require('path'); const fs = require('fs'); // Get repository name for log directory const REPO_NAME = process.env.REPO_NAME || ''; // Validate REPO_NAME is required if (!REPO_NAME || REPO_NAME.trim() === '') { console.error('ERROR: REPO_NAME environment variable is required but not set.'); console.error('Please set REPO_NAME environment variable before starting the server.'); console.error('Example: export REPO_NAME="my-repo"'); console.error('You can use "mgit list" to view available repository names.'); process.exit(1); } // 日志配置 const getLogConfig = () => { // Default log directory: .setting/ or .setting.<REPO_NAME>/ let defaultLogDir = './.setting'; if (REPO_NAME) { defaultLogDir = `./.setting.${REPO_NAME}`; } const logDir = process.env.MCP_LOG_DIR || defaultLogDir; const logFile = process.env.MCP_LOG_FILE || 'mcp-mgit-managed.log'; return { dir: logDir, file: logFile, fullPath: path.join(logDir, logFile) }; }; // 确保日志目录存在 const ensureLogDir = () => { const { dir } = getLogConfig(); if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } }; // 写入日志 const writeLog = (level, message, data = null) => { const timestamp = new Date().toISOString(); const logEntry = { timestamp, level, message, data: data ? JSON.stringify(data) : null }; const logLine = `${timestamp} | ${level} | ${message}${data ? ` | ${JSON.stringify(data)}` : ''}\n`; try { ensureLogDir(); const { fullPath } = getLogConfig(); fs.appendFileSync(fullPath, logLine, 'utf8'); } catch (err) { console.error('Failed to write log file:', err.message); } // 同时输出到控制台 console.error(`[${level}] ${message}`); }; // Get server script path const serverPath = path.resolve(__dirname, './src/server-final.js'); // Check if server file exists if (!fs.existsSync(serverPath)) { const errorMsg = `Server file not found: ${serverPath}`; writeLog('ERROR', errorMsg); process.exit(1); } writeLog('INFO', `Starting MCP MGit server (managed mode) from: ${serverPath}`); let server = null; let restartCount = 0; const maxRestarts = 10; // Function to start server function startServer() { // Create environment object const env = { ...process.env, // Ensure environment variables are passed MGIT_CMD: process.env.MGIT_CMD || 'mgit', REPO_NAME: process.env.REPO_NAME || '', PROJECT_NAME: process.env.PROJECT_NAME || '', LANGUAGE: process.env.LANGUAGE || 'en', MCP_LOG_DIR: process.env.MCP_LOG_DIR || (process.env.REPO_NAME ? `./.setting.${process.env.REPO_NAME}` : './.setting'), MCP_LOG_FILE: process.env.MCP_LOG_FILE || 'mcp-mgit.log', }; writeLog('INFO', 'Starting MCP MGit server with environment:', { MGIT_CMD: env.MGIT_CMD, REPO_NAME: env.REPO_NAME, PROJECT_NAME: env.PROJECT_NAME || '(not set)', LANGUAGE: env.LANGUAGE, MCP_LOG_DIR: env.MCP_LOG_DIR, MCP_LOG_FILE: env.MCP_LOG_FILE }); server = spawn('node', [serverPath], { stdio: ['inherit', 'inherit', 'inherit'], env: env }); writeLog('INFO', `MCP MGit server process started with PID: ${server.pid} (restart count: ${restartCount})`); // Add signal handling debug info writeLog('INFO', 'Signal handlers registered for SIGINT and SIGTERM'); writeLog('INFO', 'Press Ctrl+C to gracefully shutdown the server'); } // Start the server startServer(); // Handle process exit server.on('close', (code) => { writeLog('INFO', `MCP MGit server exited with code: ${code}`); // If server exited with error and we haven't exceeded max restarts, restart it if (code !== 0 && restartCount < maxRestarts) { restartCount++; writeLog('INFO', `Server crashed, restarting... (${restartCount}/${maxRestarts})`); setTimeout(() => { startServer(); }, 2000); // Wait 2 seconds before restart } else if (code !== 0) { writeLog('ERROR', `Server crashed ${maxRestarts} times, giving up`); process.exit(1); } else { // Server exited normally writeLog('INFO', 'Server exited normally'); process.exit(0); } }); // Handle server error server.on('error', (err) => { writeLog('ERROR', 'Server process error:', { error: err.message, stack: err.stack }); if (restartCount < maxRestarts) { restartCount++; writeLog('INFO', `Server error, restarting... (${restartCount}/${maxRestarts})`); setTimeout(() => { startServer(); }, 2000); } else { writeLog('ERROR', `Server error ${maxRestarts} times, giving up`); process.exit(1); } }); // Handle signals process.on('SIGINT', () => { writeLog('INFO', 'Received SIGINT, shutting down server...'); gracefulShutdown('SIGINT'); }); process.on('SIGTERM', () => { writeLog('INFO', 'Received SIGTERM, shutting down server...'); gracefulShutdown('SIGTERM'); }); // Handle Windows specific signals process.on('SIGBREAK', () => { writeLog('INFO', 'Received SIGBREAK, shutting down server...'); gracefulShutdown('SIGTERM'); }); // Handle process exit process.on('exit', (code) => { writeLog('INFO', `Managed server process exiting with code: ${code}`); }); // Graceful shutdown function function gracefulShutdown(signal) { // Set a timeout to force exit if server doesn't respond global.shutdownTimeout = setTimeout(() => { writeLog('WARN', 'Server shutdown timeout, forcing exit...'); try { if (server) { server.kill('SIGKILL'); } } catch (err) { writeLog('ERROR', 'Failed to force kill server:', { error: err.message }); } process.exit(1); }, 10000); // 10 seconds timeout // Try graceful shutdown try { if (server) { server.kill(signal); writeLog('INFO', `Sent ${signal} signal to server process ${server.pid}`); } else { writeLog('WARN', 'No server process to shutdown'); process.exit(0); } } catch (err) { writeLog('ERROR', `Failed to send ${signal} signal to server:`, { error: err.message }); if (global.shutdownTimeout) { clearTimeout(global.shutdownTimeout); } process.exit(1); } } // Handle uncaught exceptions process.on('uncaughtException', (err) => { writeLog('ERROR', 'Uncaught exception in managed server:', { error: err.message, stack: err.stack }); if (server) { server.kill('SIGTERM'); } process.exit(1); }); process.on('unhandledRejection', (reason, promise) => { writeLog('ERROR', 'Unhandled Promise rejection in managed server:', { reason: reason.toString(), promise: promise.toString() }); if (server) { server.kill('SIGTERM'); } process.exit(1); });

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/liliangshan/mcp-server-mgit'

If you have feedback or need assistance with the MCP directory API, please join our Discord server