UNPKG

local-file-operation-mcp

Version:

本地文件操作 MCP 服务器:安全的读写、编辑、搜索、比较、哈希、权限、压缩、监控、命令与任务管理工具集。

161 lines (139 loc) 4.52 kB
/** * 文件监控工具模块 * 支持监控文件变化 */ const fs = require('fs').promises; const path = require('path'); class FileWatchTool { constructor(securityValidator) { this.securityValidator = securityValidator; this.watchers = new Map(); } async handle(args) { const { path: watchPath, events = 'create,delete,modify', duration = 30, output_format = 'text' } = args; // 检查路径是否被允许 if (!this.securityValidator.isPathAllowed(watchPath)) { throw new Error(`不允许监控路径: ${watchPath}`); } // 验证事件类型 const validEvents = ['create', 'delete', 'modify']; const eventList = events.split(',').map(e => e.trim().toLowerCase()); const invalidEvents = eventList.filter(e => !validEvents.includes(e)); if (invalidEvents.length > 0) { throw new Error(`无效的监控事件: ${invalidEvents.join(', ')}。有效事件: ${validEvents.join(', ')}`); } try { const results = await this.watchPath(watchPath, eventList, duration); if (output_format === 'json') { return { content: [ { type: 'text', text: JSON.stringify({ watch_path: watchPath, duration: duration, events: eventList, changes: results }, null, 2) } ] }; } else { return { content: [ { type: 'text', text: this.formatWatchResults(watchPath, duration, eventList, results) } ] }; } } catch (error) { throw new Error(`文件监控失败: ${error.message}`); } } async watchPath(watchPath, events, duration) { return new Promise((resolve, reject) => { const changes = []; const startTime = Date.now(); // 检查路径是否存在 fs.stat(watchPath).catch(() => { // 如果路径不存在,创建目录 return fs.mkdir(watchPath, { recursive: true }); }).then(() => { // 使用 fs.watch 监控文件变化 const watcher = require('fs').watch(watchPath, { recursive: true }, (eventType, filename) => { const changeTime = new Date().toISOString(); const relativePath = path.join(watchPath, filename); let changeType; switch (eventType) { case 'rename': // 需要检查文件是否存在来判断是创建还是删除 fs.stat(relativePath).then(() => { changes.push({ type: 'create', path: relativePath, time: changeTime }); }).catch(() => { changes.push({ type: 'delete', path: relativePath, time: changeTime }); }); break; case 'change': changes.push({ type: 'modify', path: relativePath, time: changeTime }); break; } }); // 设置超时 const timeout = setTimeout(() => { watcher.close(); resolve(changes); }, duration * 1000); // 存储监控器引用 this.watchers.set(watchPath, { watcher, timeout }); }).catch(reject); }); } formatWatchResults(watchPath, duration, events, changes) { let result = `文件监控结果:\n`; result += `监控路径: ${watchPath}\n`; result += `监控时长: ${duration} 秒\n`; result += `监控事件: ${events.join(', ')}\n`; result += `变化数量: ${changes.length}\n\n`; if (changes.length > 0) { result += `变化详情:\n`; result += `${'='.repeat(60)}\n`; changes.forEach((change, index) => { result += `${index + 1}. 类型: ${change.type}\n`; result += ` 路径: ${change.path}\n`; result += ` 时间: ${change.time}\n`; result += `${'-'.repeat(40)}\n`; }); } else { result += `在监控期间未检测到任何变化。\n`; } return result; } // 清理所有监控器 cleanup() { for (const [path, { watcher, timeout }] of this.watchers) { watcher.close(); clearTimeout(timeout); } this.watchers.clear(); } } module.exports = FileWatchTool;