Skip to main content
Glama

shell_exec

Execute shell commands with detailed error handling and output capture, optionally specifying a working directory, to safely manage tasks on the host system.

Instructions

Executes commands in the specified shell with detailed error handling and output capture

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
commandYesThe shell command to execute in the configured shell environment
workingDirNoOptional working directory to execute the command in (must be under $HOME for security)

Implementation Reference

  • Executes the provided shell command using the configured shell and zx library. Validates working directory security, handles stdout/stderr output, logs activity, and returns structured content with error status.
    async ({ command, workingDir: cmdWorkingDir }) => { try { logger.info(`Executing command: ${command}`); // Use command-specific working directory or fall back to global setting const execWorkingDir = cmdWorkingDir || workingDir; if (execWorkingDir && !isUnderHome(execWorkingDir)) { logger.error( `Working directory must be under $HOME: ${execWorkingDir}`, ); return { content: [ { type: "text", text: `Error: Working directory must be under $HOME: ${execWorkingDir}`, }, ], isError: true, }; } try { // Execute command using zx // Pass the command to the shell with -c option if (execWorkingDir) { $.cwd = execWorkingDir; } const result = await $`${shell} -c ${command}`; if (result.stderr) { logger.info(`Command warning: ${result.stderr}`); } // Return successful execution result return { content: [ { type: "text", text: result.stdout || "(Command executed successfully but produced no output)", }, ], }; } catch (execError) { // Command execution error (non-zero exit code) const error = execError as ProcessOutput; logger.error( `Command execution error: ${error.stderr || error.message}`, ); return { content: [ { type: "text", text: error.stderr || error.stdout || error.message, }, ], isError: true, }; } } catch (error) { // Other error handling logger.error("Unexpected error:", error); return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }, );
  • Zod schema defining the input parameters for shell_exec: required 'command' string and conditional 'workingDir' string (optional if global workingDir set).
    { command: z .string() .min(1) .describe( "The shell command to execute in the configured shell environment", ), workingDir: workingDir ? z .string() .optional() .describe( "Optional working directory to execute the command in (must be under $HOME for security)", ) : z .string() .describe( "Working directory to execute the command in (must be under $HOME for security)", ), },
  • Registers the 'shell_exec' tool on the MCP server, providing name, description, input schema using Zod, and the execution handler function.
    server.tool( "shell_exec", "Executes commands in the specified shell with detailed error handling and output capture", { command: z .string() .min(1) .describe( "The shell command to execute in the configured shell environment", ), workingDir: workingDir ? z .string() .optional() .describe( "Optional working directory to execute the command in (must be under $HOME for security)", ) : z .string() .describe( "Working directory to execute the command in (must be under $HOME for security)", ), }, async ({ command, workingDir: cmdWorkingDir }) => { try { logger.info(`Executing command: ${command}`); // Use command-specific working directory or fall back to global setting const execWorkingDir = cmdWorkingDir || workingDir; if (execWorkingDir && !isUnderHome(execWorkingDir)) { logger.error( `Working directory must be under $HOME: ${execWorkingDir}`, ); return { content: [ { type: "text", text: `Error: Working directory must be under $HOME: ${execWorkingDir}`, }, ], isError: true, }; } try { // Execute command using zx // Pass the command to the shell with -c option if (execWorkingDir) { $.cwd = execWorkingDir; } const result = await $`${shell} -c ${command}`; if (result.stderr) { logger.info(`Command warning: ${result.stderr}`); } // Return successful execution result return { content: [ { type: "text", text: result.stdout || "(Command executed successfully but produced no output)", }, ], }; } catch (execError) { // Command execution error (non-zero exit code) const error = execError as ProcessOutput; logger.error( `Command execution error: ${error.stderr || error.message}`, ); return { content: [ { type: "text", text: error.stderr || error.stdout || error.message, }, ], isError: true, }; } } catch (error) { // Other error handling logger.error("Unexpected error:", error); return { content: [ { type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}`, }, ], isError: true, }; } }, );
  • Utility function to verify if a given directory path is safely under the user's home directory, used for security in shell_exec working directory validation.
    export const isUnderHome = (dirPath: string): boolean => { const homePath = os.homedir(); const absoluteDirPath = path.resolve(dirPath); const absoluteHomePath = path.resolve(homePath); const relativePath = path.relative(absoluteHomePath, absoluteDirPath); return !relativePath.startsWith("..") && !path.isAbsolute(relativePath); };
  • Determines the shell to use for command execution, prioritizing env SHELL, CLI --shell option, or OS default (/bin/bash or cmd.exe). Exported as default and used in shell_exec.
    const getShell = (): string => { if (process.env.SHELL) { return process.env.SHELL; } const shellProgram = new Command(); shellProgram .name("mcp-shell") .description("MCP Shell Server - A server for executing shell commands") .version("0.1.0") .option("-s, --shell <shell>", "Specify the path to the shell to use"); shellProgram.parse(process.argv); const options = shellProgram.opts(); if (options.shell) { return options.shell; } // Set default shell based on OS return os.platform() === "win32" ? "cmd.exe" : "/bin/bash"; };

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mkusaka/mcp-shell-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server