@gabrielmaialva33/mcp-filesystem
Version:
MCP server for secure filesystem access
88 lines • 2.98 kB
JavaScript
import { exec as execCallback } from 'node:child_process';
import { promisify } from 'node:util';
import { z } from 'zod';
import { FileSystemError } from '../../errors/index.js';
import { metrics } from '../../metrics/index.js';
import { logger } from '../../logger/index.js';
const exec = promisify(execCallback);
const SAFE_COMMAND_REGEX = /^[a-zA-Z0-9_\-./\s]+$/;
const FORBIDDEN_COMMANDS = [
'rm -rf',
'rm -r',
'rmdir',
'dd',
'mkfs',
'format',
'wget',
'curl -O',
'curl --output',
'chmod 777',
'chmod -R 777',
'sudo',
'su',
];
export const ExecuteCommandArgsSchema = z.object({
command: z.string().describe('The command to execute'),
workingDir: z.string().optional().describe('Working directory for command execution'),
timeout: z
.number()
.int()
.positive()
.max(30000)
.default(5000)
.describe('Maximum execution time in milliseconds (max 30s)'),
captureOutput: z.boolean().default(true).describe('Whether to capture and return command output'),
});
function validateCommand(command) {
if (FORBIDDEN_COMMANDS.some((forbidden) => command.includes(forbidden))) {
throw new FileSystemError(`Command contains forbidden operations`, 'FORBIDDEN_COMMAND', undefined, { command });
}
if (!SAFE_COMMAND_REGEX.test(command)) {
throw new FileSystemError(`Command contains potentially unsafe characters`, 'UNSAFE_COMMAND', undefined, { command });
}
return true;
}
export async function executeCommand(args, _config) {
const endMetric = metrics.startOperation('execute_command');
try {
await logger.debug(`Executing command: ${args.command}`, { args });
validateCommand(args.command);
const options = {
cwd: args.workingDir || process.cwd(),
timeout: args.timeout,
encoding: 'utf-8',
};
try {
const { stdout, stderr } = await exec(args.command, options);
await logger.debug(`Command executed successfully: ${args.command}`, {
stdout: stdout.substring(0, 100) + (stdout.length > 100 ? '...' : ''),
});
endMetric();
return {
stdout,
stderr,
exitCode: 0,
};
}
catch (error) {
const stderr = error.stderr || '';
const stdout = error.stdout || '';
const exitCode = error.code || 1;
await logger.warn(`Command execution failed: ${args.command}`, {
exitCode,
stderr: stderr.substring(0, 100) + (stderr.length > 100 ? '...' : ''),
});
endMetric();
return {
stdout,
stderr,
exitCode,
};
}
}
catch (error) {
metrics.recordError('execute_command');
throw error;
}
}
//# sourceMappingURL=index.js.map