execute_command
Run shell commands securely within Windows Subsystem for Linux (WSL) by specifying the command, working directory, and timeout, with built-in validation and protection against vulnerabilities like shell injection.
Instructions
Execute a command in WSL
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Command to execute | |
| timeout | No | Timeout in milliseconds | |
| working_dir | No | Working directory for command execution |
Implementation Reference
- src/command-executor.ts:60-119 (handler)Low-level handler that sanitizes input, spawns WSL process via child_process.spawn, captures stdout/stderr/exit code, and handles timeout.public async execute_command( command: string, working_dir?: string, timeout?: number, ): Promise<CommandResponse> { return new Promise((resolve, reject) => { const sanitized_command = this.sanitize_command(command); const validated_dir = this.validate_working_dir(working_dir); const validated_timeout = this.validate_timeout(timeout); const cd_command = validated_dir ? `cd "${validated_dir}" && ` : ''; const full_command = `${cd_command}${sanitized_command}`; const wsl_process = spawn(wsl_config.executable, [ '--exec', wsl_config.shell, '-c', full_command, ]); let stdout = ''; let stderr = ''; wsl_process.stdout.on('data', (data) => { stdout += data.toString(); }); wsl_process.stderr.on('data', (data) => { stderr += data.toString(); }); let timeout_id: NodeJS.Timeout | undefined; if (validated_timeout) { timeout_id = setTimeout(() => { wsl_process.kill(); reject(new CommandTimeoutError(validated_timeout)); }, validated_timeout); } wsl_process.on('close', (code) => { if (timeout_id) { clearTimeout(timeout_id); } resolve({ stdout, stderr, exit_code: code, command: sanitized_command, working_dir: validated_dir, }); }); wsl_process.on('error', (error) => { if (timeout_id) { clearTimeout(timeout_id); } reject(error); }); }); }
- src/index.ts:325-395 (registration)MCP server tool registration for 'execute_command', including schema, annotations, and the handler function.this.server.tool( { name: 'execute_command', description: 'Execute a command in WSL (use read-only tools when possible)', schema: v.object({ command: v.pipe( v.string(), v.description('Command to execute'), ), working_dir: v.optional( v.pipe( v.string(), v.description('Working directory'), ), ), timeout: v.optional( v.pipe( v.number(), v.description('Timeout (ms)'), ), ), }), annotations: { readOnlyHint: false, destructiveHint: true, }, }, async ({ command, working_dir, timeout }) => { try { const result = await this.execute_wsl_command( command, working_dir, timeout, ); if (result.requires_confirmation) { return { content: [ { type: 'text' as const, text: result.stderr, }, ], }; } return { content: [ { type: 'text' as const, text: this.format_output(result), }, ], }; } catch (error) { return { content: [ { type: 'text' as const, text: `Error executing command: ${ error instanceof Error ? error.message : String(error) }`, }, ], isError: true, }; } }, );
- src/index.ts:66-104 (helper)Helper method in WslServer that implements safety checks for dangerous commands, requiring confirmation via separate tool if needed, before delegating to CommandExecutor.private async execute_wsl_command( command: string, working_dir?: string, timeout?: number, ): Promise<CommandResponse> { return new Promise((resolve, reject) => { const requires_confirmation = this.command_executor.is_dangerous_command(command); if (requires_confirmation) { // Generate a unique confirmation ID const confirmation_id = Math.random() .toString(36) .substring(7); this.pending_confirmations.set(confirmation_id, { command, working_dir, timeout, resolve, reject, }); // Return early with confirmation request resolve({ stdout: '', stderr: `Command "${command}" requires confirmation. Use confirm_command with ID: ${confirmation_id}`, exit_code: null, command, requires_confirmation: true, }); return; } this.command_executor .execute_command(command, working_dir, timeout) .then(resolve) .catch(reject); }); }
- src/command-executor.ts:52-58 (helper)Helper method to detect potentially dangerous commands based on predefined list.public is_dangerous_command(command: string): boolean { return dangerous_commands.some( (dangerous) => command.toLowerCase().includes(dangerous.toLowerCase()) || command.match(new RegExp(`\\b${dangerous}\\b`, 'i')), ); }