execute_remote_command
Remotely execute shell commands across multiple operating systems, ensuring compatibility with Windows and Unix platforms, while specifying the working directory for execution.
Instructions
Execute a command on the host machine
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | Command to execute | |
| cwd | No | Working directory for command execution |
Implementation Reference
- src/index.ts:171-236 (handler)Main handler for the 'execute_remote_command' tool within the CallToolRequestSchema request handler. Validates input, sanitizes and normalizes the command, executes it, and formats the output or error response.this.server.setRequestHandler(CallToolRequestSchema, async (request) => { if (request.params.name !== 'execute_remote_command') { throw new McpError( ErrorCode.MethodNotFound, `Unknown tool: ${request.params.name}` ); } if (!isValidExecArgs(request.params.arguments)) { throw new McpError( ErrorCode.InvalidParams, 'Invalid command execution arguments' ); } try { // Sanitize and normalize the command const sanitizedCmd = sanitizeCommand(request.params.arguments.command); const normalizedCmd = normalizeCommand(sanitizedCmd); const { stdout, stderr } = await this.executeCommand( normalizedCmd, request.params.arguments.cwd ); // Combine stdout and stderr in the response const output = []; if (stdout.trim()) { output.push(stdout.trim()); } if (stderr.trim()) { output.push('STDERR:', stderr.trim()); } return { content: [ { type: 'text', text: output.join('\n') || 'Command completed successfully (no output)', }, ], }; } catch (error: any) { // Enhanced error handling with more details const errorMessage = [ 'Command execution error:', `Command: ${request.params.arguments.command}`, `Error: ${error?.message || 'Unknown error'}` ]; console.error('Command failed:', error); // Debug log return { content: [ { type: 'text', text: errorMessage.join('\n'), }, ], isError: true, }; } }); }
- src/index.ts:148-169 (registration)Registers the 'execute_remote_command' tool in the ListToolsRequestSchema handler, providing name, description, and input schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'execute_remote_command', description: 'Execute a command on the host machine', inputSchema: { type: 'object', properties: { command: { type: 'string', description: 'Command to execute', }, cwd: { type: 'string', description: 'Working directory for command execution', }, }, required: ['command'], }, }, ], }));
- src/index.ts:153-166 (schema)Input schema definition for the 'execute_remote_command' tool, specifying parameters and requirements.inputSchema: { type: 'object', properties: { command: { type: 'string', description: 'Command to execute', }, cwd: { type: 'string', description: 'Working directory for command execution', }, }, required: ['command'], },
- src/index.ts:84-145 (helper)Helper function to execute the shell command, supporting pipes with execPromise or spawn, with timeout and cross-platform compatibility.private executeCommand(command: string, cwd?: string): Promise<{ stdout: string; stderr: string }> { return new Promise((resolve, reject) => { let timeout: NodeJS.Timeout | null = null; // Set timeout timeout = setTimeout(() => { reject(new Error(`Command timed out after ${COMMAND_TIMEOUT/1000} seconds`)); }, COMMAND_TIMEOUT); // Use exec for commands with pipes, spawn for simple commands if (command.includes('|')) { execPromise(command, { cwd, shell: isWindows ? 'cmd.exe' : '/bin/sh', timeout: COMMAND_TIMEOUT, windowsHide: true }).then(({ stdout, stderr }) => { if (timeout) clearTimeout(timeout); resolve({ stdout, stderr }); }).catch((error) => { if (timeout) clearTimeout(timeout); reject(error); }); } else { const shell = isWindows ? 'cmd.exe' : '/bin/sh'; const args = isWindows ? ['/c', command] : ['-c', command]; console.error(`Executing command: ${command} (${shell} ${args.join(' ')})`); // Debug log const child = spawn(shell, args, { cwd, shell: true, windowsHide: true }); let stdout = ''; let stderr = ''; child.stdout.on('data', (data) => { stdout += data.toString(); }); child.stderr.on('data', (data) => { stderr += data.toString(); }); child.on('error', (error) => { if (timeout) clearTimeout(timeout); reject(error); }); child.on('close', (code) => { if (timeout) clearTimeout(timeout); if (code === 0 || stdout.length > 0) { // Consider command successful if there's output even with non-zero exit code resolve({ stdout, stderr }); } else { reject(new Error(`Command failed with exit code ${code}${stderr ? ': ' + stderr : ''}`)); } }); } }); }
- src/index.ts:30-42 (helper)Helper to sanitize the command by removing null bytes and dangerous operators like ; and || to prevent injection.const sanitizeCommand = (command: string): string => { // Remove any null bytes that could be used for command injection command = command.replace(/\0/g, ''); // Only remove malicious command chaining while preserving pipes if (isWindows) { command = command.replace(/\|\|/g, ''); // Remove OR operator but keep pipes } else { command = command.replace(/;/g, '').replace(/\|\|/g, ''); // Remove semicolon and OR operator } return command; };