Skip to main content
Glama
blazickjp

Shell MCP Server

execute_command

Execute shell commands in a specified directory using bash or sh shells to automate system tasks and manage files securely.

Instructions

Execute a shell command in a specified directory using a specified shell

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
commandYesThe shell command to execute
shellYesShell to use for execution. Available: ['bash', 'sh']
cwdYesWorking directory for command execution

Implementation Reference

  • MCP call_tool handler that checks the tool name is 'execute_command', extracts parameters, calls the execution function, and returns the result as text content.
    @server.call_tool()
    async def call_tool(name: str, arguments: Dict[str, Any]) -> List[types.TextContent]:
        """
        Handle tool calls for shell command execution.
        
        Args:
            name (str): The name of the tool to call (must be 'execute_command')
            arguments (Dict[str, Any]): Tool arguments including 'command', 'shell', and 'cwd'
            
        Returns:
            List[types.TextContent]: The command execution results or error message
        """
        if name != "execute_command":
            return [types.TextContent(type="text", text=f"Error: Unknown tool {name}")]
    
        command = arguments["command"]
        shell = arguments["shell"]
        cwd = arguments["cwd"]
    
        try:
            result = await run_shell_command(shell, command, cwd)
            return [types.TextContent(type="text", text=str(result))]
        except Exception as e:
            return [types.TextContent(type="text", text=f"Error: {str(e)}")]
  • Core helper function that performs the actual shell command execution with path validation, shell support, timeout handling, and cross-platform compatibility.
    async def run_shell_command(shell: str, command: str, cwd: str) -> Dict[str, Any]:
        """
        Execute a shell command safely and return its output.
        
        Args:
            shell (str): Name of the shell to use
            command (str): The command to execute
            cwd (str): Working directory for command execution
            
        Returns:
            Dict[str, Any]: Command execution results including stdout, stderr, and exit code
        """
        if not settings.is_path_allowed(cwd):
            raise ValueError(f"Directory '{cwd}' is not in the allowed directories list")
        
        if shell not in settings.ALLOWED_SHELLS:
            raise ValueError(f"Shell '{shell}' is not allowed. Available shells: {list(settings.ALLOWED_SHELLS.keys())}")
        
        shell_path = settings.ALLOWED_SHELLS[shell]
        
        try:
            if sys.platform == 'win32':
                shell_cmd = [shell_path, '/c', command] if shell == 'cmd' else [shell_path, '-Command', command]
            else:
                shell_cmd = [shell_path, '-c', command]
    
            process = await asyncio.create_subprocess_exec(
                *shell_cmd,
                stdout=asyncio.subprocess.PIPE,
                stderr=asyncio.subprocess.PIPE,
                cwd=cwd
            )
    
            try:
                stdout, stderr = await asyncio.wait_for(
                    process.communicate(), 
                    timeout=settings.COMMAND_TIMEOUT
                )
                
                return {
                    "stdout": stdout.decode() if stdout else "",
                    "stderr": stderr.decode() if stderr else "",
                    "exit_code": process.returncode,
                    "command": command,
                    "shell": shell,
                    "cwd": cwd
                }
    
            except asyncio.TimeoutError:
                try:
                    process.kill()
                    await process.wait()
                except ProcessLookupError:
                    pass
                raise TimeoutError(f"Command execution timed out after {settings.COMMAND_TIMEOUT} seconds")
    
        except TimeoutError:
            raise
        except Exception as e:
            return {
                "stdout": "",
                "stderr": str(e),
                "exit_code": -1,
                "command": command,
                "shell": shell,
                "cwd": cwd
            }
  • Registers the 'execute_command' tool by listing it with @server.list_tools() decorator, including name, description, and input schema.
    @server.list_tools()
    async def list_tools() -> List[types.Tool]:
        """List available shell tools."""
        return [
            types.Tool(
                name="execute_command",
                description="Execute a shell command in a specified directory using a specified shell",
                inputSchema={
                    "type": "object",
                    "properties": {
                        "command": {
                            "type": "string",
                            "description": "The shell command to execute",
                        },
                        "shell": {
                            "type": "string",
                            "description": f"Shell to use for execution. Available: {list(settings.ALLOWED_SHELLS.keys())}",
                        },
                        "cwd": {
                            "type": "string",
                            "description": "Working directory for command execution",
                        },
                    },
                    "required": ["command", "shell", "cwd"],
                },
            )
        ]
  • Defines the input schema for the 'execute_command' tool, specifying required parameters: command, shell, cwd.
        "type": "object",
        "properties": {
            "command": {
                "type": "string",
                "description": "The shell command to execute",
            },
            "shell": {
                "type": "string",
                "description": f"Shell to use for execution. Available: {list(settings.ALLOWED_SHELLS.keys())}",
            },
            "cwd": {
                "type": "string",
                "description": "Working directory for command execution",
            },
        },
        "required": ["command", "shell", "cwd"],
    },
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. While 'execute a shell command' implies a potentially risky operation, the description lacks critical details such as security implications, error handling, output format, or execution limits. It fails to address what happens if the command fails or how results are returned.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that directly states the tool's purpose without any unnecessary words. It is front-loaded and appropriately sized for its function, with zero waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of executing shell commands (a high-risk operation with no annotations and no output schema), the description is insufficient. It lacks details on behavioral traits, error handling, security warnings, and output expectations, making it incomplete for safe and effective use by an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, meaning the input schema already documents all parameters thoroughly. The description adds no additional meaning beyond what the schema provides, such as examples or edge cases. However, it does not contradict the schema, so it meets the baseline for high coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('execute a shell command') and resources involved ('in a specified directory using a specified shell'). It uses precise verbs and distinguishes what this tool does without ambiguity, even though there are no sibling tools to differentiate from.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, prerequisites, or any context for its application. It simply states what the tool does without indicating appropriate scenarios or constraints.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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/blazickjp/shell-mcp-server'

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