UNPKG

@gabrielmaialva33/mcp-filesystem

Version:
88 lines 2.98 kB
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