@yinzhouzhi/mcp-filesystem-server
Version:
本地文件系统操作服务器 - 基于STDIO通信的MCP服务,支持文件和目录操作
316 lines (296 loc) • 14 kB
JavaScript
#!/usr/bin/env node
/**
* 文件系统MCP服务器命令行工具
* 提供通过命令行启动和配置MCP服务器的功能
*/
const { program } = require('commander');
const { startServer } = require('../index');
const path = require('path');
const fs = require('fs');
const os = require('os');
const packageJson = require('../package.json');
// 获取版本号
const version = packageJson.version;
// 显示Banner
function showBanner() {
console.log('=================================================');
console.log(' 文件系统MCP服务器 CLI ');
console.log('=================================================');
console.log(`版本: ${version}`);
console.log('框架: Model Context Protocol SDK');
console.log('=================================================');
}
// 配置命令行参数
program
.name('mcp-filesystem-server')
.description('基于MCP的文件系统操作服务器')
.version(version);
// 启动服务器命令
program
.command('start')
.description('启动MCP文件系统服务器')
.option('-d, --debug', '启用调试模式')
.option('-l, --log-level <level>', '设置日志级别 (debug, info, warn, error)', 'info')
.option('-p, --log-path <path>', '设置日志目录路径', path.join(process.cwd(), 'logs'))
.action(async (options) => {
// 显示Banner
showBanner();
// 设置环境变量
process.env.DEBUG_MODE = options.debug ? 'true' : 'false';
process.env.LOG_LEVEL = options.logLevel;
// 确保日志目录存在
const logDir = options.logPath;
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
console.log('系统信息:');
console.log(`- 操作系统: ${os.type()} ${os.release()}`);
console.log(`- Node.js: ${process.version}`);
console.log(`- 工作目录: ${process.cwd()}`);
console.log(`- 日志级别: ${options.logLevel}`);
console.log(`- 调试模式: ${options.debug ? '启用' : '禁用'}`);
console.log(`- 日志目录: ${logDir}`);
console.log('=================================================');
console.log('开始启动MCP服务器...');
try {
// 启动服务器 - 注意这里只传递日志目录路径,由startServer函数负责生成完整的日志文件路径
const result = await startServer({
debug: options.debug,
logLevel: options.logLevel,
logDir: logDir // 重命名参数为logDir,而不是logPath,更清晰表明这是一个目录
});
if (result && result.success) {
console.log('MCP服务器启动成功!');
console.log('服务器正在运行中,等待MCP连接...');
console.log('按 Ctrl+C 停止服务器');
} else {
console.error('服务器启动失败!');
process.exit(1);
}
} catch (error) {
console.error('服务器启动错误:', error);
process.exit(1);
}
});
// 显示工具列表命令
program
.command('list-tools')
.description('列出所有可用的MCP工具')
.action(() => {
console.log('=================================================');
console.log(' 可用MCP工具列表 ');
console.log('=================================================');
console.log('文件操作:');
console.log('- read_file: 读取文件内容');
console.log('- write_file: 写入文件内容');
console.log('- append_file: 追加文件内容');
console.log('- delete_file: 删除文件');
console.log('- copy_file: 复制文件');
console.log('- move_file: 移动文件');
console.log('- get_file_info: 获取文件信息');
console.log('- file_exists: 检查文件是否存在');
console.log('\n目录操作:');
console.log('- list_directory: 列出目录内容');
console.log('- create_directory: 创建目录');
console.log('- remove_directory: 删除目录');
console.log('- directory_exists: 检查目录是否存在');
console.log('\n行操作:');
console.log('- read_lines: 读取文件指定行');
console.log('- write_lines: 写入文件指定行');
console.log('- insert_line: 插入行');
console.log('- delete_lines: 删除行');
console.log('- search_file_content: 搜索文件内容');
console.log('\n监控工具:');
console.log('- watch_path: 监控文件或目录变更');
console.log('- stop_watch: 停止监控');
console.log('- list_watchers: 列出所有监控');
console.log('\n系统工具:');
console.log('- get_server_status: 获取服务器状态');
console.log('=================================================');
});
// 处理示例命令
program
.command('example')
.description('显示如何通过Node.js连接到MCP服务器的示例代码')
.option('--npx', '显示使用npx的示例代码')
.option('--electron', '显示在Electron中使用的示例代码')
.action((options) => {
showBanner();
if (options.npx) {
console.log('=================================================');
console.log(' 使用npx连接到MCP服务器示例代码 ');
console.log('=================================================');
console.log('```javascript');
console.log('const { spawn } = require(\'child_process\');');
console.log('const { McpClient } = require(\'@modelcontextprotocol/sdk/client/mcp.js\');');
console.log('const { StdioClientTransport } = require(\'@modelcontextprotocol/sdk/client/stdio.js\');');
console.log('');
console.log('async function connectWithNpx() {');
console.log(' // 使用npx启动MCP服务器');
console.log(' const serverProcess = spawn(\'npx\', [\'@yinzhouzhi/mcp-filesystem-server\', \'start\'], {');
console.log(' stdio: [\'pipe\', \'pipe\', \'pipe\']');
console.log(' });');
console.log('');
console.log(' // 创建STDIO传输');
console.log(' const transport = new StdioClientTransport({');
console.log(' input: serverProcess.stdout,');
console.log(' output: serverProcess.stdin,');
console.log(' error: serverProcess.stderr');
console.log(' });');
console.log('');
console.log(' // 创建客户端');
console.log(' const client = new McpClient();');
console.log(' await client.connect(transport);');
console.log('');
console.log(' // 调用工具示例');
console.log(' const result = await client.invokeTool(\'read_file\', {');
console.log(' path: \'./example.txt\',');
console.log(' encoding: \'utf8\'');
console.log(' });');
console.log('');
console.log(' console.log(\'文件内容:\', result);');
console.log('');
console.log(' // 关闭连接');
console.log(' await client.disconnect();');
console.log(' serverProcess.kill();');
console.log('}');
console.log('```');
} else if (options.electron) {
console.log('=================================================');
console.log(' 在Electron中使用MCP服务器示例代码 ');
console.log('=================================================');
console.log('```javascript');
console.log('// 主进程中');
console.log('const { app, BrowserWindow, ipcMain } = require(\'electron\');');
console.log('const { McpClient } = require(\'@modelcontextprotocol/sdk/client/mcp.js\');');
console.log('const { StdioClientTransport } = require(\'@modelcontextprotocol/sdk/client/stdio.js\');');
console.log('const { spawn } = require(\'child_process\');');
console.log('');
console.log('let mcpClient = null;');
console.log('let mcpServerProcess = null;');
console.log('');
console.log('async function setupMcpServer() {');
console.log(' // 启动MCP文件系统服务器');
console.log(' mcpServerProcess = spawn(\'npx\', [\'@yinzhouzhi/mcp-filesystem-server\', \'start\'], {');
console.log(' stdio: [\'pipe\', \'pipe\', \'pipe\']');
console.log(' });');
console.log('');
console.log(' // 创建传输层');
console.log(' const transport = new StdioClientTransport({');
console.log(' input: mcpServerProcess.stdout,');
console.log(' output: mcpServerProcess.stdin,');
console.log(' error: mcpServerProcess.stderr');
console.log(' });');
console.log('');
console.log(' // 创建客户端并连接');
console.log(' mcpClient = new McpClient();');
console.log(' await mcpClient.connect(transport);');
console.log('');
console.log(' // 向渲染进程提供IPC接口');
console.log(' ipcMain.handle(\'fs-tool\', async (event, toolName, params) => {');
console.log(' try {');
console.log(' return await mcpClient.invokeTool(toolName, params);');
console.log(' } catch (error) {');
console.log(' console.error(`执行工具 ${toolName} 失败:`, error);');
console.log(' throw error;');
console.log(' }');
console.log(' });');
console.log('}');
console.log('');
console.log('// 在应用启动时初始化');
console.log('app.whenReady().then(setupMcpServer);');
console.log('');
console.log('// 应用退出时清理');
console.log('app.on(\'will-quit\', async () => {');
console.log(' if (mcpClient) {');
console.log(' await mcpClient.disconnect();');
console.log(' }');
console.log(' if (mcpServerProcess) {');
console.log(' mcpServerProcess.kill();');
console.log(' }');
console.log('});');
console.log('```');
console.log('');
console.log('在渲染进程中使用:');
console.log('```javascript');
console.log('// 在渲染进程中调用MCP工具');
console.log('async function readFile(path) {');
console.log(' return await window.ipcRenderer.invoke(\'fs-tool\', \'read_file\', { path });');
console.log('}');
console.log('');
console.log('// 调用示例');
console.log('document.getElementById(\'readBtn\').addEventListener(\'click\', async () => {');
console.log(' try {');
console.log(' const content = await readFile(\'./example.txt\');');
console.log(' document.getElementById(\'output\').textContent = content;');
console.log(' } catch (error) {');
console.log(' console.error(\'读取文件失败:\', error);');
console.log(' }');
console.log('});');
console.log('```');
} else {
console.log('=================================================');
console.log(' 通过Node.js连接到MCP服务器示例代码 ');
console.log('=================================================');
console.log('```javascript');
console.log('const { McpClient } = require(\'@modelcontextprotocol/sdk/client/mcp.js\');');
console.log('const { StdioClientTransport } = require(\'@modelcontextprotocol/sdk/client/stdio.js\');');
console.log('const { spawn } = require(\'child_process\');');
console.log('');
console.log('async function connectToMcpServer() {');
console.log(' // 启动MCP服务器进程');
console.log(' const serverProcess = spawn(\'mcp-filesystem-server\', [\'start\'], {');
console.log(' stdio: [\'pipe\', \'pipe\', \'pipe\']');
console.log(' });');
console.log('');
console.log(' // 创建STDIO传输');
console.log(' const transport = new StdioClientTransport({');
console.log(' input: serverProcess.stdout,');
console.log(' output: serverProcess.stdin,');
console.log(' error: serverProcess.stderr');
console.log(' });');
console.log('');
console.log(' // 创建客户端');
console.log(' const client = new McpClient();');
console.log(' await client.connect(transport);');
console.log('');
console.log(' // 查看所有可用的示例:');
console.log(' // npx @yinzhouzhi/mcp-filesystem-server example --npx');
console.log(' // npx @yinzhouzhi/mcp-filesystem-server example --electron');
console.log('');
console.log(' // 调用工具示例');
console.log(' const result = await client.invokeTool(\'read_file\', {');
console.log(' path: \'./example.txt\',');
console.log(' encoding: \'utf8\'');
console.log(' });');
console.log('');
console.log(' console.log(\'文件内容:\', result);');
console.log('');
console.log(' // 关闭连接');
console.log(' await client.disconnect();');
console.log(' serverProcess.kill();');
console.log('}');
console.log('```');
}
console.log('=================================================');
console.log('查看更多示例:');
console.log(' npx @yinzhouzhi/mcp-filesystem-server example --npx # 使用npx的示例');
console.log(' npx @yinzhouzhi/mcp-filesystem-server example --electron # 在Electron中使用的示例');
console.log('=================================================');
});
// 解析命令行参数
program.parse(process.argv);
// 如果没有提供命令,显示帮助
if (!process.argv.slice(2).length) {
showBanner();
program.help();
}
// 处理进程退出
process.on('exit', () => {
console.log('MCP服务器已关闭');
});
// 处理Ctrl+C
process.on('SIGINT', () => {
console.log('接收到停止信号,MCP服务器即将关闭...');
process.exit(0);
});