UNPKG

local-file-operation-mcp

Version:

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

432 lines (421 loc) 15.5 kB
#!/usr/bin/env node /** * 安全MCP服务器 - Node.js版本 v1.2.0 * 支持文件操作、文件编辑、文件搜索、文件比较、文件哈希、文件权限、文件压缩、文件监控和命令执行 * 包含安全限制,禁止操作敏感目录 */ const { Server } = require('@modelcontextprotocol/sdk/server/index.js'); const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js'); const { CallToolRequestSchema, ListToolsRequestSchema, } = require('@modelcontextprotocol/sdk/types.js'); // 导入工具模块 const SecurityValidator = require('./tools/securityValidator.js'); const FileOperationTool = require('./tools/fileOperation.js'); const FileEditTool = require('./tools/fileEdit.js'); const FileSearchTool = require('./tools/fileSearch.js'); const FileCompareTool = require('./tools/fileCompare.js'); const FileHashTool = require('./tools/fileHash.js'); const FilePermissionsTool = require('./tools/filePermissions.js'); const FileArchiveTool = require('./tools/fileArchive.js'); const FileWatchTool = require('./tools/fileWatch.js'); const CommandExecutionTool = require('./tools/commandExecution.js'); const TaskManagerTool = require('./tools/taskManager.js'); const TimeTool = require('./tools/timeTool.js'); class SecureMCPServer { constructor() { this.server = new Server( { name: 'secure-mcp-server', version: '2.0.2', }, { capabilities: { tools: {}, }, } ); // 初始化安全验证器和工具 this.securityValidator = new SecurityValidator(); this.tools = { file_operation: new FileOperationTool(this.securityValidator), file_edit: new FileEditTool(this.securityValidator), file_search: new FileSearchTool(this.securityValidator), file_compare: new FileCompareTool(this.securityValidator), file_hash: new FileHashTool(this.securityValidator), file_permissions: new FilePermissionsTool(this.securityValidator), file_archive: new FileArchiveTool(this.securityValidator), file_watch: new FileWatchTool(this.securityValidator), execute_command: new CommandExecutionTool(this.securityValidator), task_manager: new TaskManagerTool(this.securityValidator), time_tool: new TimeTool(this.securityValidator) }; this.setupHandlers(); } setupHandlers() { // 列出可用工具 this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: 'file_operation', description: '统一的文件操作工具,支持读取、写入、列表目录、创建目录、删除文件等操作。支持工作目录概念,可在指定目录下进行相对路径操作', inputSchema: { type: 'object', properties: { operation: { type: 'string', enum: ['read', 'write', 'list', 'create_dir', 'delete'], description: '操作类型:read(读取文件), write(写入文件), list(列出目录), create_dir(创建目录), delete(删除文件/目录)' }, path: { type: 'string', description: '文件或目录路径(可以是相对路径或绝对路径)' }, content: { type: 'string', description: '写入文件时的内容(仅在operation为write时需要)' }, working_directory: { type: 'string', description: '工作目录(可选),当path为相对路径时,会基于此目录解析。如果未指定,则基于当前工作目录' } }, required: ['operation', 'path'] } }, { name: 'time_tool', description: '获取当前真实时间,支持 ISO、RFC3339、UNIX(秒/毫秒)、本地与指定时区格式', inputSchema: { type: 'object', properties: { format: { type: 'string', enum: ['iso', 'rfc3339', 'unix', 'unix_ms', 'locale'], default: 'iso', description: '输出格式:iso、rfc3339、unix(秒)、unix_ms(毫秒)、locale(本地)' }, time_zone: { type: 'string', description: 'IANA 时区名称(如:Asia/Shanghai、UTC)。不填则使用系统时区' }, include_milliseconds: { type: 'boolean', default: true, description: '是否在可用格式中包含毫秒(对 iso/locale 等生效)' } } } }, { name: 'file_edit', description: '文件行级编辑工具,支持删除行、插入行、替换行等操作', inputSchema: { type: 'object', properties: { operation: { type: 'string', enum: ['delete_lines', 'insert_lines', 'replace_lines', 'append_lines'], description: '操作类型:delete_lines(删除行), insert_lines(插入行), replace_lines(替换行), append_lines(追加行)' }, path: { type: 'string', description: '文件路径' }, start_line: { type: 'integer', description: '起始行号(从1开始)' }, end_line: { type: 'integer', description: '结束行号(仅delete_lines和replace_lines需要)' }, content: { type: 'string', description: '要插入或替换的内容' }, encoding: { type: 'string', default: 'utf8', description: '文件编码(可选,默认utf8)' } }, required: ['operation', 'path'] } }, { name: 'file_search', description: '文件搜索工具,支持在文件中搜索内容,支持正则表达式', inputSchema: { type: 'object', properties: { search_path: { type: 'string', description: '搜索路径' }, pattern: { type: 'string', description: '搜索模式(支持正则表达式)' }, file_types: { type: 'string', default: '*', description: '文件类型过滤(如:txt,js,py 或 * 表示所有类型)' }, case_sensitive: { type: 'boolean', default: false, description: '是否区分大小写' }, max_results: { type: 'integer', default: 100, description: '最大搜索结果数量' } }, required: ['search_path', 'pattern'] } }, { name: 'file_compare', description: '文件比较工具,比较两个文件的差异', inputSchema: { type: 'object', properties: { file1: { type: 'string', description: '第一个文件路径' }, file2: { type: 'string', description: '第二个文件路径' }, output_format: { type: 'string', enum: ['text', 'json'], default: 'text', description: '输出格式' } }, required: ['file1', 'file2'] } }, { name: 'file_hash', description: '文件哈希工具,计算文件的MD5、SHA1、SHA256哈希值', inputSchema: { type: 'object', properties: { path: { type: 'string', description: '文件路径' }, algorithm: { type: 'string', enum: ['md5', 'sha1', 'sha256', 'sha512'], default: 'md5', description: '哈希算法' } }, required: ['path'] } }, { name: 'file_permissions', description: '文件权限工具,修改文件权限', inputSchema: { type: 'object', properties: { path: { type: 'string', description: '文件路径' }, mode: { type: 'string', description: '权限模式(如:755, 644)' }, recursive: { type: 'boolean', default: false, description: '是否递归应用权限' } }, required: ['path', 'mode'] } }, { name: 'file_archive', description: '文件压缩/解压工具,支持ZIP、TAR、GZ格式', inputSchema: { type: 'object', properties: { operation: { type: 'string', enum: ['compress', 'extract'], description: '操作类型:compress(压缩), extract(解压)' }, source: { type: 'string', description: '源文件或目录' }, destination: { type: 'string', description: '目标文件或目录(可选)' }, format: { type: 'string', enum: ['zip', 'tar', 'gz', 'tar.gz'], default: 'zip', description: '压缩格式' } }, required: ['operation', 'source'] } }, { name: 'file_watch', description: '文件监控工具,监控文件变化', inputSchema: { type: 'object', properties: { path: { type: 'string', description: '监控路径' }, events: { type: 'string', default: 'create,delete,modify', description: '监控事件(create,delete,modify)' }, duration: { type: 'integer', default: 30, description: '监控时长(秒)' }, output_format: { type: 'string', enum: ['text', 'json'], default: 'text', description: '输出格式' } }, required: ['path'] } }, { name: 'execute_command', description: '执行本地命令', inputSchema: { type: 'object', properties: { command: { type: 'string', description: '要执行的命令' }, working_directory: { type: 'string', description: '命令执行的工作目录(可选)' }, confirm: { type: 'boolean', default: false, description: '危险命令确认开关。高危命令需显式设为true方可执行;passwd一律禁止' } }, required: ['command'] } }, { name: 'task_manager', description: '任务管理工具,支持任务分解、排期、进度跟踪', inputSchema: { type: 'object', properties: { operation: { type: 'string', enum: ['create', 'update', 'delete', 'list', 'complete', 'get', 'clear'], description: '操作类型:create(创建), update(更新), delete(删除), list(列表), complete(完成), get(获取), clear(清空)' }, model_name: { type: 'string', default: 'default', description: '模型名称,用于区分不同模型的任务列表' }, task_id: { type: 'string', description: '任务ID(更新、删除、完成、获取时需要)' }, title: { type: 'string', description: '任务标题' }, description: { type: 'string', description: '任务描述' }, priority: { type: 'string', enum: ['low', 'medium', 'high', 'urgent'], default: 'medium', description: '优先级' }, due_date: { type: 'string', description: '截止日期(ISO格式,如:2024-01-15T10:00:00Z)' }, subtasks: { type: 'array', description: '子任务列表' }, status: { type: 'string', enum: ['pending', 'in_progress', 'completed', 'cancelled'], default: 'pending', description: '任务状态' }, progress: { type: 'integer', minimum: 0, maximum: 100, default: 0, description: '任务进度(0-100)' } }, required: ['operation'] } } ] }; }); // 处理工具调用 this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; try { if (this.tools[name]) { return await this.tools[name].handle(args); } else { throw new Error(`未知工具: ${name}`); } } catch (error) { return { content: [ { type: 'text', text: `错误: ${error.message}` } ] }; } }); } async start() { const transport = new StdioServerTransport(); await this.server.connect(transport); console.error('MCP服务器已启动'); } } // 启动服务器 const server = new SecureMCPServer(); server.start().catch(console.error);