Mail MCP Tool

by shuakami
Verified
import * as fs from 'fs'; import * as path from 'path'; // 锁文件路径配置 const LOCK_FILE = path.join(process.cwd(), '.mcp-mail.lock'); export class ProcessManager { private instanceId: string; constructor() { // 生成唯一实例ID this.instanceId = Date.now().toString(); // 注册进程退出处理 this.registerCleanup(); } private registerCleanup(): void { // 注册多个信号以确保清理 process.on('SIGINT', () => this.cleanup()); process.on('SIGTERM', () => this.cleanup()); process.on('exit', () => this.cleanup()); } private cleanup(): void { try { if (fs.existsSync(LOCK_FILE)) { const lockData = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf8')); // 只清理自己的锁文件 if (lockData.instanceId === this.instanceId) { fs.unlinkSync(LOCK_FILE); console.log('已清理进程锁文件'); } } } catch (error) { console.error('清理锁文件时出错:', error); } } private async waitForProcessExit(pid: number, timeout: number = 5000): Promise<boolean> { const startTime = Date.now(); while (Date.now() - startTime < timeout) { try { process.kill(pid, 0); // 进程还在运行,等待100ms await new Promise(resolve => setTimeout(resolve, 100)); } catch (e) { // 进程已退出 return true; } } return false; } public async checkAndCreateLock(): Promise<boolean> { try { // 检查锁文件是否存在 if (fs.existsSync(LOCK_FILE)) { const lockData = JSON.parse(fs.readFileSync(LOCK_FILE, 'utf8')); try { // 检查进程是否还在运行 process.kill(lockData.pid, 0); console.log('检测到已有MCP实例运行,发送终止信号'); // 发送终止信号 process.kill(lockData.pid, 'SIGTERM'); // 等待旧进程退出 console.log('等待旧实例退出...'); const exited = await this.waitForProcessExit(lockData.pid); if (!exited) { console.error('等待旧实例退出超时'); return false; } // 删除旧的锁文件 fs.unlinkSync(LOCK_FILE); } catch (e) { // 进程不存在,删除过期的锁文件 console.log('检测到过期的锁文件,将创建新实例'); fs.unlinkSync(LOCK_FILE); } } // 创建新的锁文件 fs.writeFileSync(LOCK_FILE, JSON.stringify({ pid: process.pid, instanceId: this.instanceId, timestamp: Date.now() })); console.log('已创建MCP实例锁文件'); return true; } catch (error) { console.error('处理锁文件时出错:', error); return false; } } }