@yinzhouzhi/mcp-filesystem-server
Version:
本地文件系统操作服务器 - 基于STDIO通信的MCP服务,支持文件和目录操作
314 lines (277 loc) • 8.42 kB
JavaScript
/**
* 本地文件系统操作服务器
* 基于STDIO通信,提供安全的文件系统操作能力
*/
const fs = require('fs');
const path = require('path');
const { pipeline } = require('stream');
const readline = require('readline');
const fileHandler = require('./handlers/file-handler');
const securityUtils = require('./config/security');
const logger = require('./utils/logging');
// 初始化环境
let isDebug = process.env.DEBUG_MODE === 'true';
const logLevel = process.env.LOG_LEVEL || (isDebug ? 'debug' : 'info');
// 配置日志
logger.initialize({
level: logLevel,
logToFile: true,
logFilePath: path.join(process.cwd(), 'logs', 'filesystem-server.log')
});
logger.info('文件系统服务器启动中...');
/**
* 处理接收到的命令
* @param {string} commandStr JSON格式的命令字符串
* @returns {Promise<Object>} 执行结果
*/
async function processCommand(commandStr) {
try {
// 解析命令
const command = JSON.parse(commandStr);
// 验证命令格式
if (!command.id || !command.type || !command.action) {
return {
success: false,
error: {
message: '无效的命令格式,缺少必要字段',
code: 'INVALID_COMMAND'
}
};
}
// 命令安全性检查
const securityCheck = securityUtils.validateCommand(command);
if (!securityCheck.isValid) {
logger.warn('命令安全验证失败', {
commandId: command.id,
reason: securityCheck.reason
});
return {
success: false,
id: command.id,
error: {
message: `安全验证失败: ${securityCheck.reason}`,
code: 'SECURITY_VIOLATION'
}
};
}
// 处理文件操作命令
if (command.type === 'fileOperation') {
const result = await fileHandler.handleFileOperation({
operation: command.action,
params: command.params || {}
});
return {
...result,
id: command.id
};
}
// 处理特殊控制命令
else if (command.type === 'control') {
return handleControlCommand(command);
}
// 未知命令类型
else {
logger.warn(`未知的命令类型: ${command.type}`, { commandId: command.id });
return {
success: false,
id: command.id,
error: {
message: `不支持的命令类型: ${command.type}`,
code: 'UNSUPPORTED_COMMAND_TYPE'
}
};
}
} catch (error) {
logger.error('处理命令时发生错误', { error: error.message, stack: error.stack });
// 命令格式错误(无法解析JSON)
if (error instanceof SyntaxError) {
return {
success: false,
error: {
message: '命令格式无效: 无法解析JSON',
code: 'INVALID_JSON'
}
};
}
// 其他错误
return {
success: false,
error: {
message: `处理命令时发生错误: ${error.message}`,
code: error.code || 'COMMAND_PROCESSING_ERROR'
}
};
}
}
/**
* 处理控制命令
* @param {Object} command 控制命令
* @returns {Object} 执行结果
*/
function handleControlCommand(command) {
const { action, params = {} } = command;
switch (action) {
// 获取服务信息
case 'getStatus':
return {
success: true,
id: command.id,
result: {
status: 'running',
version: require('../package.json').version,
pid: process.pid,
uptime: process.uptime(),
memoryUsage: process.memoryUsage(),
isDebug
}
};
// 获取支持的文件操作
case 'getSupportedOperations':
return {
success: true,
id: command.id,
result: fileHandler.getSupportedOperations()
};
// 设置日志级别
case 'setLogLevel':
if (params.level) {
logger.configure({ level: params.level });
logger.info(`日志级别已更改为: ${params.level}`);
return {
success: true,
id: command.id,
result: { level: params.level }
};
}
return {
success: false,
id: command.id,
error: {
message: '缺少必要参数: level',
code: 'MISSING_PARAM'
}
};
// 设置调试模式
case 'setDebugMode':
if (typeof params.enabled === 'boolean') {
isDebug = params.enabled;
logger.configure({
level: isDebug ? 'debug' : logLevel
});
logger.info(`调试模式已${isDebug ? '启用' : '禁用'}`);
return {
success: true,
id: command.id,
result: { debugMode: isDebug }
};
}
return {
success: false,
id: command.id,
error: {
message: '缺少必要参数: enabled (boolean)',
code: 'MISSING_PARAM'
}
};
// 关闭服务器
case 'shutdown':
logger.info('收到关闭服务器命令,即将关闭...');
// 发送成功响应后关闭
process.nextTick(() => {
process.exit(0);
});
return {
success: true,
id: command.id,
result: { message: '服务器正在关闭' }
};
default:
logger.warn(`未知的控制命令: ${action}`, { commandId: command.id });
return {
success: false,
id: command.id,
error: {
message: `不支持的控制命令: ${action}`,
code: 'UNSUPPORTED_CONTROL_ACTION'
}
};
}
}
/**
* 主函数:设置STDIO通信
*/
function main() {
// 创建readline接口以读取标准输入
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
// 显式关闭换行转换,确保原始二进制传输
if (process.stdin.setRawMode) {
process.stdin.setRawMode(true);
}
// 日志目录确保存在
const logDir = path.join(process.cwd(), 'logs');
if (!fs.existsSync(logDir)) {
fs.mkdirSync(logDir, { recursive: true });
}
logger.info('文件系统服务器已启动,等待命令...');
// 接收命令行
rl.on('line', async (line) => {
if (!line.trim()) return;
try {
logger.debug('收到命令', { line: line.substring(0, 100) + (line.length > 100 ? '...' : '') });
// 处理命令
const result = await processCommand(line);
// 确保响应包含ID
if (!result.id && line.id) {
result.id = line.id;
}
// 发送响应
const response = JSON.stringify(result);
process.stdout.write(response + '\n');
logger.debug('发送响应', {
id: result.id,
success: result.success,
responseLength: response.length
});
} catch (error) {
logger.error('处理命令时发生未捕获错误', {
error: error.message,
stack: error.stack
});
// 发送错误响应
const errorResponse = JSON.stringify({
success: false,
error: {
message: `服务器内部错误: ${error.message}`,
code: 'INTERNAL_ERROR'
}
});
process.stdout.write(errorResponse + '\n');
}
});
// 处理标准输入流关闭
rl.on('close', () => {
logger.info('标准输入流已关闭,服务器即将退出');
process.exit(0);
});
// 处理进程错误
process.on('uncaughtException', (error) => {
logger.error('未捕获异常', { error: error.message, stack: error.stack });
});
// 处理进程警告
process.on('warning', (warning) => {
logger.warn('进程警告', { warning: warning.message, stack: warning.stack });
});
// 处理进程被终止信号
['SIGINT', 'SIGTERM'].forEach(signal => {
process.on(signal, () => {
logger.info(`收到 ${signal} 信号,服务器即将退出`);
process.exit(0);
});
});
}
// 启动服务器
main();