### Docker Container Environment Setup Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/configuration.md Set up the MCP Shell Server within a Docker container using a Python base image. This example installs the server, configures environment variables, and sets the entrypoint. ```dockerfile FROM python:3.11-slim RUN pip install mcp-shell-server ENV ALLOW_COMMANDS="cat,ls,pwd,grep,head,tail,wc" ENV ALLOW_PATTERNS="python[0-9.]+" ENV MCP_SHELL_DEFAULT_TIMEOUT_SECONDS=30 ENV MCP_SHELL_MAX_TIMEOUT_SECONDS=300 ENV MCP_SHELL_OUTPUT_LIMIT_BYTES=5242880 ENTRYPOINT ["mcp-shell-server"] ``` -------------------------------- ### Relative Path Resolution Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/directory_manager.md Illustrates how relative directories in client requests are resolved against the server process's current working directory. This example assumes the server is started in '/home/user/project'. ```bash # Server is started with process CWD = /home/user/project cd /home/user/project mcp-shell-server # Client makes request with directory="data" # Resolved to: /home/user/project/data (not /home/client/data) ``` -------------------------------- ### Minimal Installation Configuration Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/configuration.md Set up a highly restrictive environment by limiting allowed commands and output size. This configuration is suitable for minimal installations where security is paramount. ```bash export ALLOW_COMMANDS="ls,cat,pwd" export MCP_SHELL_DEFAULT_TIMEOUT_SECONDS=5 export MCP_SHELL_OUTPUT_LIMIT_BYTES=512000 # 512 KiB ``` -------------------------------- ### Install Dependencies with Test Requirements Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Install the project dependencies, including those required for testing, using pip. ```bash pip install -e ".[test]" ``` -------------------------------- ### Basic Setup for Claude Desktop Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/configuration.md Configure environment variables for basic setup, including allowed commands and timeouts. Ensure these are set in your shell profile (~/.bash_profile or ~/.zshrc) before running the server. ```bash # ~/.bash_profile or ~/.zshrc export ALLOW_COMMANDS="ls,cat,pwd,grep,wc,echo,find,touch,rm" export MCP_SHELL_DEFAULT_TIMEOUT_SECONDS=30 export MCP_SHELL_MAX_TIMEOUT_SECONDS=120 uvx mcp-shell-server ``` -------------------------------- ### Redirection Dictionary Type Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/types.md Shows the structure of a dictionary used to configure input and output redirections for a command. This example represents `command < input.txt > output.txt`. ```python redirects = { "stdin": "input.txt", "stdout": "output.txt", "stdout_append": False } # Represents: command < input.txt > output.txt ``` -------------------------------- ### Instantiate CommandPreProcessor Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_preprocessor.md Initialize the CommandPreProcessor class. No parameters or specific setup are required. ```python from mcp_shell_server.command_preprocessor import CommandPreProcessor preprocessor = CommandPreProcessor() ``` -------------------------------- ### Start Process Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Starts a new process asynchronously. This method is an alias for `create_process` and allows specifying the command and an optional timeout. ```python async def start_process( self, cmd: List[str], timeout: Optional[int] = None ) -> asyncio.subprocess.Process: # ... implementation details ... pass ``` -------------------------------- ### Install MCP Shell Server via Smithery CLI Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Use this command to automatically install the Shell Server for Claude Desktop using the Smithery CLI. ```bash npx -y @smithery/cli install mcp-shell-server --client claude ``` -------------------------------- ### Pipeline Command List Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/types.md Illustrates how to represent a shell pipeline using the List[List[str]] type. This example shows a cat, grep, and wc command pipeline. ```python # Represents: cat file.txt | grep pattern | wc -l commands = [ ["cat", "file.txt"], ["grep", "pattern"], ["wc", "-l"] ] ``` -------------------------------- ### start_process() Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Starts a new process asynchronously. This is an alias for `create_process`. ```APIDOC ## start_process() ### Description Starts a new process asynchronously (alias for `create_process`). ### Method Signature `async def start_process(self, cmd: List[str], timeout: Optional[int] = None) -> asyncio.subprocess.Process` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | cmd | List[str] | Yes | — | Command to execute | | timeout | int | No | None | Timeout for process start | ### Returns `asyncio.subprocess.Process` object representing the started process. ``` -------------------------------- ### File Handles Dictionary Type Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/types.md Illustrates the structure of the dictionary returned after setting up file redirections, including file descriptors and pre-read data. This example shows the expected output format. ```python handles = await io_handler.setup_redirects( redirects={ "stdin": "input.txt", "stdout": "output.txt", "stdout_append": False }, directory="/tmp" ) # Returns: # { # "stdin": asyncio.subprocess.PIPE, # "stdin_data": "content of input.txt", # "stdout": , # "stderr": asyncio.subprocess.PIPE # } ``` -------------------------------- ### Setup Redirects Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Opens file handles for input/output redirections based on provided metadata. It validates that redirection targets are contained within the specified directory. ```python async def setup_redirects( self, redirects: Dict[str, Union[None, str, bool]], directory: Optional[str] = None, ) -> Dict[str, Union[IO[Any], int, str, None]]: ``` -------------------------------- ### Install MCP Shell Server via pip Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md This command installs the mcp-shell-server package using pip for manual installation. ```bash pip install mcp-shell-server ``` -------------------------------- ### Start Process Asynchronously Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Starts a new process asynchronously, serving as an alias for `create_process`. It takes the command list and an optional timeout value. ```python async def start_process_async( self, cmd: List[str], timeout: Optional[int] = None ) -> asyncio.subprocess.Process: # ... implementation details ... pass ``` -------------------------------- ### Start MCP Shell Server Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Launches the MCP server on stdio. This is the main entry point for the server process. ```python from mcp_shell_server import main ``` ```python import asyncio from mcp_shell_server import main asyncio.run(main()) ``` -------------------------------- ### start_process_async() Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Starts a new process asynchronously. This is an alias for `create_process`. ```APIDOC ## start_process_async() ### Description Starts a new process asynchronously (alias for `create_process`). ### Method Signature `async def start_process_async(self, cmd: List[str], timeout: Optional[int] = None) -> asyncio.subprocess.Process` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | cmd | List[str] | Yes | — | Command to execute | | timeout | int | No | None | Timeout for process start | ### Returns `asyncio.subprocess.Process` object representing the started process. ``` -------------------------------- ### Start MCP Shell Server with Allowed Commands Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Starts the MCP Shell Server, specifying allowed commands via the ALLOW_COMMANDS environment variable. The alias ALLOWED_COMMANDS can also be used. ```bash ALLOW_COMMANDS="ls,cat,echo" uvx mcp-shell-server ``` ```bash # Or using the alias ALLOWED_COMMANDS="ls,cat,echo" uvx mcp-shell-server ``` -------------------------------- ### Setup IO Redirections Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/io_redirection_handler.md Opens file handles for input and output redirections. It resolves paths, handles file opening modes, and prepares file contents for stdin. Raises ValueError for invalid paths. ```python import asyncio from mcp_shell_server.io_redirection_handler import IORedirectionHandler async def main(): handler = IORedirectionHandler() # Set up input and output redirections handles = await handler.setup_redirections( redirects={ "stdin": "input.txt", "stdout": "output.txt", "stdout_append": False }, directory="/tmp" ) # handles["stdin"]: asyncio.subprocess.PIPE # handles["stdin_data"]: "contents of /tmp/input.txt" # handles["stdout"]: # handles["stderr"]: asyncio.subprocess.PIPE asyncio.run(main()) ``` -------------------------------- ### Result Dictionary Type Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/types.md Demonstrates how to execute a command and access its results, including error checking, output retrieval, and execution time. ```python result = await executor.execute( command=["ls", "-l"], directory="/tmp" ) # Accessing fields: if result["error"]: print(f"Failed: {result['error']}") else: print(f"Output:\n{result['stdout']}") print(f"Exit code: {result['status']}") print(f"Duration: {result['execution_time']}s") ``` -------------------------------- ### MCP Shell Server: Using ALLOW_PATTERNS Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md This example shows how to use ALLOW_PATTERNS to specify regular expressions for command name matching. ```bash ALLOW_PATTERNS="python[0-9.]*,node" # Command-name patterns only ``` -------------------------------- ### Python Regex Fullmatch Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_validator.md Demonstrates how Python regex patterns are compiled and matched using fullmatch() semantics for command validation. ```python pattern.fullmatch(command_name) ``` -------------------------------- ### Execute Shell Command with Redirection Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/README.md This example demonstrates how to execute a command that involves input and output redirection. The command string should include redirection operators like '<' and '>'. ```python result = await executor.execute( command=["grep", "pattern", "<", "input.txt", ">", "output.txt"], directory="/data" ) ``` -------------------------------- ### ShellExecutor Example Usage Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Demonstrates how to use the `ShellExecutor` to run various commands, including simple commands, commands with stdin, commands with redirection, pipelines, and commands with custom environment variables. ```python import asyncio from mcp_shell_server.shell_executor import ShellExecutor async def main(): executor = ShellExecutor() # Simple command result = await executor.execute( command=["ls", "-la"], directory="/tmp", timeout=10 ) if result["error"]: print(f"Error: {result['error']}") else: print(f"Output:\n{result['stdout']}") print(f"Exit code: {result['status']}") print(f"Duration: {result['execution_time']:.3f}s") # Command with stdin result = await executor.execute( command=["grep", "pattern"], directory="/tmp", stdin="line1\npattern\nline3\n" ) # Command with redirection result = await executor.execute( command=["cat", "input.txt", ">", "output.txt"], directory="/tmp" ) # Pipeline result = await executor.execute( command=["cat", "file.txt", "|", "grep", "pattern", "|", "wc", "-l"], directory="/data" ) # With custom environment variables result = await executor.execute( command=["printenv"], directory="/tmp", envs={"CUSTOM_VAR": "value"} # Only if in MCP_SHELL_CHILD_ENV_ALLOWLIST ) asyncio.run(main()) ``` -------------------------------- ### Audit Event Dictionary Type Example (JSON) Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/types.md Provides an example of an audit log entry in JSON format, detailing metadata for a command invocation, including execution status and resource usage. ```json { "timestamp": 1719756800.123, "command": "grep", "argv": ["grep", "-n", "pattern"], "directory": "/tmp", "redirections": {"stdin": true, "stdout": false, "stdout_append": false}, "env": {}, "timeout": 30, "output_limit": 1048576, "stdout_bytes": 145, "stderr_bytes": 0, "return_code": 0, "duration": 0.042, "result_type": "success" } ``` -------------------------------- ### Development Environment Configuration Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/configuration.md Configure for development with multiple tools, allowing specific commands, patterns, and a broader range of environment variables. This setup is useful when working with various development tools and languages. ```bash export ALLOW_COMMANDS="ls,cat,pwd,find,grep" export ALLOW_PATTERNS="python[0-9.]*,node[0-9.]*" export MCP_SHELL_DEFAULT_TIMEOUT_SECONDS=60 export MCP_SHELL_MAX_TIMEOUT_SECONDS=300 export MCP_SHELL_CHILD_ENV_ALLOWLIST="LANG,LC_ALL,HOME,USER" ``` -------------------------------- ### MCP Shell Server Configuration Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/README.md Configure allowed commands, patterns, timeouts, output limits, and environment variables for the MCP Shell Server. Start the server using the 'mcp-shell-server' command. ```bash # Allowlist commands export ALLOW_COMMANDS="ls,cat,pwd,grep,wc" # Or use regex patterns export ALLOW_PATTERNS="python[0-9.]*,node[0-9.]*" # Set timeouts export MCP_SHELL_DEFAULT_TIMEOUT_SECONDS=30 export MCP_SHELL_MAX_TIMEOUT_SECONDS=300 # Set output cap export MCP_SHELL_OUTPUT_LIMIT_BYTES=1048576 # Allow additional environment variables export MCP_SHELL_CHILD_ENV_ALLOWLIST="LANG,LC_ALL" # Start server mcp-shell-server ``` -------------------------------- ### MCP Shell Execute Request Example Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/endpoints.md This JSON-RPC request demonstrates how a client calls the `shell_execute` tool to run a command. It specifies the command, arguments, and a custom timeout. Ensure the command and arguments comply with the server's configured `ALLOW_COMMANDS` and `ALLOW_PATTERNS`. ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "shell_execute", "arguments": { "command": ["ls", "-la"], "directory": "/tmp", "timeout": 10 } } } ``` -------------------------------- ### Audit Log Record for Rejection Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/errors.md An example of an audit log entry when a command execution is rejected. Includes the rejection reason. ```json { "result_type": "rejected", "rejection_reason": "Command not allowed: rm", "error_type": null } ``` -------------------------------- ### Examples of Blocked Redirection Operations Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/io_redirection_handler.md Demonstrates various scenarios that are rejected by the IORedirectionHandler due to security policies, including absolute paths, parent directory traversal, symlink escapes, and cross-filesystem operations. ```python # All of these would be rejected: # Absolute path handler._resolve_redirection_path("/etc/passwd", "/tmp") # Parent traversal handler._resolve_redirection_path("../../secret.txt", "/tmp/subdir") # Symlink escape (if /tmp/link -> /var/log) handler._resolve_redirection_path("link", "/tmp") # Different filesystem root (Windows) handler._resolve_redirection_path("C:/Windows/System32", "D:/User") ``` -------------------------------- ### Custom PATH Configuration Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/configuration.md Configure with a custom PATH for accessing specific tools and allowlisting essential environment variables like PATH and HOME. This is useful when your development tools are installed in non-standard locations. ```bash export ALLOW_COMMANDS="mycommand,ls" export MCP_SHELL_SAFE_PATH="/opt/mytools/bin:/usr/local/bin:/usr/bin:/bin" export MCP_SHELL_CHILD_ENV_ALLOWLIST="PATH,HOME" ``` -------------------------------- ### Get Allowed Commands Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_validator.md Parses and returns allowed command names from environment variables. Returns a set of strings for efficient lookup. ```python def _get_allowed_commands(self) -> set[str] ``` -------------------------------- ### setup_redirects Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/io_redirection_handler.md Opens file handles for contained redirections, resolving paths and setting up appropriate modes for stdin, stdout, and stderr. ```APIDOC ## setup_redirects() ### Description Opens file handles for contained redirections. It resolves paths, reads stdin data if applicable, and returns file objects or pipes for stdout and stderr. ### Method Signature ```python async def setup_redirects( self, redirects: Dict[str, Union[None, str, bool]], directory: Optional[str] = None, ) -> Dict[str, Union[IO[Any], int, str, None]] ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body * **redirects** (Dict) - Redirect metadata from `process_redirections()` * **directory** (Optional[str]) - Working directory for path containment validation ### Returns `Dict[str, Union[IO[Any], int, str, None]]` with keys: - `stdin`: File descriptor or PIPE - `stdin_data`: (if input redirection) Pre-read file contents as string - `stdout`: File object or PIPE or file descriptor - `stderr`: PIPE constant ### Raises `ValueError` if: - Redirection path is absolute - Redirection path contains `..` (parent traversal) - Redirection path escapes the working directory - File cannot be opened ### Behavior 1. For stdin redirection: - Resolves path to absolute using `_resolve_redirection_path()` - Opens file for reading - Reads contents into `stdin_data` - Returns PIPE for stdin handle 2. For stdout redirection: - Resolves path to absolute using `_resolve_redirection_path()` - Opens file for writing (mode `w`) or appending (mode `a`) - Returns file object as stdout handle 3. For stderr: - Always returns PIPE ### Request Example ```python import asyncio from mcp_shell_server.io_redirection_handler import IORedirectionHandler async def main(): handler = IORedirectionHandler() handles = await handler.setup_redirects( redirects={ "stdin": "input.txt", "stdout": "output.txt", "stdout_append": False }, directory="/tmp" ) # handles["stdin"]: asyncio.subprocess.PIPE # handles["stdin_data"]: "contents of /tmp/input.txt" # handles["stdout"]: # handles["stderr"]: asyncio.subprocess.PIPE asyncio.run(main()) ``` ``` -------------------------------- ### Initialize IORedirectionHandler Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/io_redirection_handler.md Instantiate the IORedirectionHandler. No parameters or initialization are required. ```python from mcp_shell_server.io_redirection_handler import IORedirectionHandler handler = IORedirectionHandler() ``` -------------------------------- ### ShellExecutor Return Value: Timeout Error Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Example of the return dictionary when a command execution times out. ```python { "error": "Command timed out after 30 seconds", "status": -1, "stdout": "", "stderr": "Command timed out after 30 seconds", "execution_time": 30.0, "directory": "/tmp" } ``` -------------------------------- ### ShellExecutor.execute Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Executes a command after validation, preprocessing, and redirection setup. This is the primary public method for running shell commands. ```APIDOC ## ShellExecutor.execute ### Description Executes a command after validation, preprocessing, and redirection setup. This is the primary public method that orchestrates the full execution pipeline, including directory validation, command preprocessing, pipeline detection, redirection parsing, command validation, process creation, execution, and audit logging. ### Method Signature ```python async def execute( self, command: List[str], directory: str, stdin: Optional[str] = None, timeout: Optional[int] = None, envs: Optional[Dict[str, str]] = None, output_limit: Optional[int] = None, ) -> Dict[str, Any] ``` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | command | List[str] | Yes | — | Command and arguments as separate array elements | | directory | str | Yes | — | Absolute working directory (must exist) | | stdin | str | No | None | Standard input to send to the process | | timeout | int | No | None | Execution timeout in seconds; uses default if omitted | | envs | Dict[str, str] | No | None | Per-call environment variable overrides | | output_limit | int | No | None | Byte cap for stdout/stderr; uses default if omitted | ### Return Value Returns `Dict[str, Any]` with the following structure: ```json { "error": None, # or error message string "stdout": "command output", "stderr": "error output or empty", "status": 0, # exit code "returncode": 0, # alias for status "execution_time": 0.123, # seconds "directory": "/tmp" # working directory used } ``` **Return values by outcome:** **Success (exit code 0):** ```json { "error": null, "stdout": "output", "stderr": "", "status": 0, "returncode": 0, "execution_time": 0.05, "directory": "/tmp" } ``` **Success (non-zero exit code):** ```json { "error": null, "stdout": "some output", "stderr": "some errors", "status": 1, "returncode": 1, "execution_time": 0.08, "directory": "/tmp" } ``` **Error (validation failure):** ```json { "error": "Command not allowed: rm", "status": 1, "stdout": "", "stderr": "Command not allowed: rm", "execution_time": 0.001, "directory": "/tmp" } ``` **Error (timeout):** ```json { "error": "Command timed out after 30 seconds", "status": -1, "stdout": "", "stderr": "Command timed out after 30 seconds", "execution_time": 30.0, "directory": "/tmp" } ``` ### Raises No exceptions are raised by `execute()`. All errors are returned in the result dict. However, internal methods may raise: - `ValueError`: For validation failures during setup - `asyncio.TimeoutError`: (caught and handled) During execution - `OutputLimitExceeded`: (caught and handled) When output exceeds limit ### Execution Stages 1. **Directory validation** → validates directory exists and is accessible 2. **Preprocessing** → separates pipe operators and cleans empty strings 3. **Pipeline detection** → if pipes present, routes to `_execute_pipeline()` 4. **Command parsing** → extracts redirections and validates no shell operators 5. **Redirection setup** → opens files for stdin/stdout/stderr 6. **Command validation** → checks allowlist and default security policy 7. **Process creation** → creates subprocess via ProcessManager 8. **Execution** → runs process with timeout and output limit 9. **Audit logging** → records result (success, rejection, timeout, error) 10. **Cleanup** → closes file handles and kills leftover processes ### Example ```python import asyncio from mcp_shell_server.shell_executor import ShellExecutor async def main(): executor = ShellExecutor() # Simple command result = await executor.execute( command=["ls", "-la"], directory="/tmp", timeout=10 ) if result["error"]: print(f"Error: {result['error']}") else: print(f"Output:\n{result['stdout']}") print(f"Exit code: {result['status']}") print(f"Duration: {result['execution_time']:.3f}s") # Command with stdin result = await executor.execute( command=["grep", "pattern"], directory="/tmp", stdin="line1\npattern\nline3\n" ) # Command with redirection result = await executor.execute( command=["cat", "input.txt", ">", "output.txt"], directory="/tmp" ) # Pipeline result = await executor.execute( command=["cat", "file.txt", "|", "grep", "pattern", "|", "wc", "-l"], directory="/data" ) # With custom environment variables result = await executor.execute( command=["printenv"], directory="/tmp", envs={"CUSTOM_VAR": "value"} # Only if in MCP_SHELL_CHILD_ENV_ALLOWLIST ) asyncio.run(main()) ``` ``` -------------------------------- ### Audit Log Record for Timeout Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/errors.md An example of an audit log entry when a command execution times out. Includes the error type. ```json { "result_type": "timeout", "error_type": "TimeoutError" } ``` -------------------------------- ### Get Allowed Commands Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Retrieves a list of command names that are permitted for execution. These are sourced from the ALLOW_COMMANDS or ALLOWED_COMMANDS environment variables. ```python def get_allowed_commands(self) -> list[str]: pass ``` -------------------------------- ### Get Allowed Patterns Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_validator.md Parses and compiles regex patterns from environment variables. Returns a list of compiled regex patterns. ```python def _get_allowed_patterns(self) -> List[re.Pattern] ``` -------------------------------- ### Command Preprocessing Flow Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_preprocessor.md Demonstrates the typical sequence of operations for preprocessing a raw command, including separating pipes, cleaning empty strings, and then either splitting by pipes or parsing redirections. ```python from mcp_shell_server.command_preprocessor import CommandPreProcessor preprocessor = CommandPreProcessor() # 1. Preprocess to separate attached pipes raw_command = ["cat|grep", "pattern"] preprocessed = preprocessor.preprocess_command(raw_command) # Result: ["cat", "grep", "|", "pattern"] (or similar) # 2. Clean empty strings cleaned = preprocessor.clean_command(preprocessed) # Result: ["cat", "grep", "|", "pattern"] # 3. Check for pipes if "|" in cleaned: # 4a. If pipes, split into segments segments = preprocessor.split_pipe_commands(cleaned) # Result: [["cat"], ["grep", "pattern"]] else: # 4b. If no pipes, parse redirections cmd, redirects = preprocessor.parse_command(cleaned) # Result: (["cat", "grep", "pattern"], {...}) ``` -------------------------------- ### ShellExecutor Return Value: Validation Failure Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Example of the return dictionary when the `execute` method encounters a validation failure, such as an disallowed command. ```python { "error": "Command not allowed: rm", "status": 1, "stdout": "", "stderr": "Command not allowed: rm", "execution_time": 0.001, "directory": "/tmp" } ``` -------------------------------- ### MCP Shell Server: Basic ALLOW_COMMANDS format Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Demonstrates the basic format for specifying allowed commands using the ALLOW_COMMANDS environment variable. ```bash ALLOW_COMMANDS="ls,cat,echo" # Basic format ``` -------------------------------- ### ShellExecutor Return Value: Success (Exit Code 0) Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Example of the return dictionary when a command executes successfully with an exit code of 0. ```python { "error": None, "stdout": "output", "stderr": "", "status": 0, "returncode": 0, "execution_time": 0.05, "directory": "/tmp" } ``` -------------------------------- ### Execute Command with Relative Directory Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/directory_manager.md Demonstrates executing a command with a relative directory. The server resolves the relative path to an absolute path and validates its existence before execution. ```python import asyncio import os from mcp_shell_server.shell_executor import ShellExecutor async def main(): # Server is in /home/user os.chdir("/home/user") executor = ShellExecutor() # Request with relative directory result = await executor.execute( command=["ls", "-la"], directory="projects" # Relative to /home/user ) # Internally: # 1. resolve_effective_directory("projects") -> /home/user/projects # 2. validate_directory("/home/user/projects") -> validates it exists # 3. Commands execute with cwd=/home/user/projects if not result["error"]: print(f"Directory used: {result['directory']}") # Prints: Directory used: /home/user/projects asyncio.run(main()) ``` -------------------------------- ### Get Allowed Patterns Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Retrieves a list of regular expression patterns used for matching command names. This helps in understanding how commands are validated. ```python def get_allowed_patterns(self) -> list[str]: pass ``` ```python handler = ExecuteToolHandler() patterns = handler.get_allowed_patterns() print(patterns) # ['python[0-9.]*', 'node', ...] ``` -------------------------------- ### Audit Log Record for Output Cap Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/errors.md An example of an audit log entry when the output limit is exceeded during command execution. Includes the error type. ```json { "result_type": "output_cap", "error_type": "OutputLimitExceeded" } ``` -------------------------------- ### Create a Subprocess Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Creates a subprocess with specified command, arguments, working directory, and stdout handling. Ensure the directory exists and the command is valid. ```python import asyncio from mcp_shell_server.process_manager import ProcessManager async def main(): pm = ProcessManager() # Create process process = await pm.create_process( argv=["ls", "-la"], directory="/tmp", stdout_handle=asyncio.subprocess.PIPE ) # Use the process stdout, stderr = await process.communicate() print(f"Exit code: {process.returncode}") asyncio.run(main()) ``` -------------------------------- ### Execute Command with Redirection Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/endpoints.md Use this for commands involving input/output redirection operators like '<', '>', or '>>'. Paths must be relative to the working directory. ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "shell_execute", "arguments": { "command": ["grep", "pattern", "<", "input.txt", ">", "output.txt"], "directory": "/tmp", "timeout": 15 } } } ``` -------------------------------- ### Get Allowed Commands Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Retrieves a sorted list of command names that are currently permitted for execution. This is useful for validating user input or displaying available commands. ```python def get_allowed_commands(self) -> list[str]: pass ``` ```python handler = ExecuteToolHandler() allowed = handler.get_allowed_commands() print(allowed) # ['ls', 'cat', 'pwd', ...] ``` -------------------------------- ### ShellExecutor Return Value: Success (Non-Zero Exit Code) Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Example of the return dictionary when a command executes but returns a non-zero exit code, indicating a non-critical failure. ```python { "error": None, "stdout": "some output", "stderr": "some errors", "status": 1, "returncode": 1, "execution_time": 0.08, "directory": "/tmp" } ``` -------------------------------- ### Instantiate DirectoryManager Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/directory_manager.md Instantiates the DirectoryManager class. No parameters are required for initialization. ```python from mcp_shell_server.directory_manager import DirectoryManager manager = DirectoryManager() ``` -------------------------------- ### Get Tool Description Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Fetches the MCP Tool schema, which includes the tool's name, description, and input schema. This is essential for understanding the tool's capabilities and requirements. ```python def get_tool_description(self) -> Tool: pass ``` ```python handler = ExecuteToolHandler() tool = handler.get_tool_description() print(tool.name) # 'shell_execute' print(tool.description) # Includes allowed commands and limits ``` -------------------------------- ### Handle Empty Commands with Split Pipe Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_preprocessor.md Demonstrates how the split_pipe_commands function handles an empty first segment when a pipe is the first character. Also shows the output of parse_command with an empty input list. ```python preprocessor.split_pipe_commands(["|", "cat"]) # Returns: [[], ["cat"]] (empty first segment) preprocessor.parse_command([]) # Returns: ([], {"stdin": None, "stdout": None, "stdout_append": False}) ``` -------------------------------- ### Configure MCP Shell Server for Claude Desktop (Local) Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md This JSON configuration is for the local version of the MCP Shell Server in Claude Desktop. It differs in the command and arguments used to run the shell server. ```shell code ~/Library/Application\ Support/Claude/claude_desktop_config.json ``` ```json { "mcpServers": { "shell": { "command": "uv", "args": [ "--directory", ".", "run", "mcp-shell-server" ], "env": { "ALLOW_COMMANDS": "ls,cat,pwd,grep,wc,touch,find" } }, } } ``` -------------------------------- ### create_process Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Creates a subprocess using argv-based execution with specified parameters for directory, stdin, stdout, environment, and timeout. ```APIDOC ## create_process() ### Description Creates a subprocess using argv-based execution. ### Method `async def create_process(self, argv: Union[str, Sequence[str]], directory: Optional[str], stdin: Optional[str] = None, stdout_handle: Any = asyncio.subprocess.PIPE, envs: Optional[Dict[str, str]] = None, timeout: Optional[int] = None) -> asyncio.subprocess.Process` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None #### Parameters - **argv** (Union[str, Sequence[str]]) - Required - Command and arguments - **directory** (Optional[str]) - Required - Working directory or None - **stdin** (str) - Optional - Unused (for signature compatibility) - **stdout_handle** (Any) - Optional - Stdout file descriptor or PIPE (default: `asyncio.subprocess.PIPE`) - **envs** (Dict[str, str]) - Optional - Per-call environment overrides - **timeout** (int) - Optional - Unused (for signature compatibility) ### Returns `asyncio.subprocess.Process` with stdin, stdout, stderr configured. ### Raises `ValueError` if argv is empty or process creation fails. ### Example ```python import asyncio from mcp_shell_server.process_manager import ProcessManager async def main(): pm = ProcessManager() process = await pm.create_process( argv=["ls", "-la"], directory="/tmp", stdout_handle=asyncio.subprocess.PIPE ) stdout, stderr = await process.communicate() print(f"Exit code: {process.returncode}") asyncio.run(main()) ``` ``` -------------------------------- ### Get Absolute Path Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Converts a given path to an absolute path. It uses a provided base directory to resolve relative paths. If no base directory is given, it may use a default. ```python def get_absolute_path( self, path: str, base_directory: Optional[str] = None ) -> str: ``` -------------------------------- ### Clone MCP Shell Server Repository Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Use this command to clone the repository. Navigate into the cloned directory afterwards. ```bash git clone https://github.com/yourusername/mcp-shell-server.git cd mcp-shell-server ``` -------------------------------- ### Command Execution with Stdin Input Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Provide standard input to a command during execution. This is useful for commands that expect input, like 'cat'. ```json { "command": ["cat"], "stdin": "Hello, World!" } ``` -------------------------------- ### Create Subprocess Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Creates a subprocess with specified command, working directory, and optional environment overrides. Ensure argv is not empty and directory is valid. ```python async def create_process( self, argv: Union[str, Sequence[str]], directory: Optional[str], stdin: Optional[str] = None, stdout_handle: Any = asyncio.subprocess.PIPE, envs: Optional[Dict[str, str]] = None, timeout: Optional[int] = None, ) -> asyncio.subprocess.Process ``` -------------------------------- ### Get Absolute Path Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/directory_manager.md Converts a relative path to an absolute path. Use this when you need a full, unambiguous path, especially when dealing with paths relative to a base directory or the current working directory. ```python import os from mcp_shell_server.directory_manager import DirectoryManager manager = DirectoryManager() # Absolute path -> returned as-is path = manager.get_absolute_path("/tmp/file.txt") # Returns: /tmp/file.txt # Relative path with base directory path = manager.get_absolute_path("file.txt", "/tmp") # Returns: /tmp/file.txt # Relative path with base directory (nested) path = manager.get_absolute_path("subdir/file.txt", "/tmp") # Returns: /tmp/subdir/file.txt # Relative path without base directory -> uses CWD os.chdir("/home/user") path = manager.get_absolute_path("file.txt") # Returns: /home/user/file.txt # Relative path with None base -> uses CWD os.chdir("/home/user") path = manager.get_absolute_path("file.txt", None) # Returns: /home/user/file.txt ``` -------------------------------- ### Initialize ShellExecutor Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/shell_executor.md Instantiate the ShellExecutor class. You can use the default process manager or inject a custom one for testing purposes. ```python from mcp_shell_server.shell_executor import ShellExecutor # Use default process manager executor = ShellExecutor() # Or inject a custom process manager for testing from mcp_shell_server.process_manager import ProcessManager custom_pm = ProcessManager() executor = ShellExecutor(process_manager=custom_pm) ``` -------------------------------- ### Command Execution with Directory and Timeout Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Combine directory specification with a timeout for command execution. This allows precise control over command scope and duration. ```json { "command": ["grep", "-r", "pattern"], "directory": "/path/to/search", "timeout": 60 } ``` -------------------------------- ### Get Allowed Commands from Environment Variables Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_validator.md Retrieve a list of allowed command names by reading and parsing the ALLOW_COMMANDS and ALLOWED_COMMANDS environment variables. Handles comma-separated values, whitespace, empty strings, and deduplication. ```python import os from mcp_shell_server.command_validator import CommandValidator os.environ["ALLOW_COMMANDS"] = "ls,cat,pwd" os.environ["ALLOWED_COMMANDS"] = "grep,echo" validator = CommandValidator() allowed = validator.get_allowed_commands() # Returns: ['ls', 'cat', 'pwd', 'grep', 'echo'] ``` -------------------------------- ### Initialize ProcessManager Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/process_manager.md Initializes the ProcessManager, setting up signal handlers for graceful shutdown of managed processes on POSIX systems. ```python from mcp_shell_server.process_manager import ProcessManager pm = ProcessManager() ``` -------------------------------- ### Execute Command with Shell Execute Tool Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Executes a command with arguments, optional stdin, working directory, and timeout. Ensure the command is whitelisted for security. ```python import asyncio from mcp_shell_server.server import ExecuteToolHandler handler = ExecuteToolHandler() # Execute a simple command result = await handler.run_tool({ "command": ["ls", "-la"], "directory": "/tmp", "timeout": 10 }) ``` ```python import asyncio from mcp_shell_server.server import ExecuteToolHandler handler = ExecuteToolHandler() # Execute with stdin result = await handler.run_tool({ "command": ["grep", "pattern"], "stdin": "line1\nline2\nline3\n", "directory": "/tmp" }) ``` -------------------------------- ### Initialize ExecuteToolHandler Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/API.md Initializes the handler with a ShellExecutor. Configuration is read from environment variables, with defaults provided for timeout and output limits. ```python def __init__(self) -> None: pass ``` -------------------------------- ### Initialize CommandValidator Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_validator.md Instantiate the CommandValidator class. No parameters are needed as configuration is read from environment variables during validation. ```python from mcp_shell_server.command_validator import CommandValidator validator = CommandValidator() ``` -------------------------------- ### Basic Command Execution in Server CWD Source: https://github.com/tumf/mcp-shell-server/blob/main/README.md Execute a command in the server process's current working directory. The 'directory' argument is optional. ```json { "command": ["ls", "-l"] } ``` -------------------------------- ### Preprocess Command with Separated Pipes and Special Operators Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/api-reference/command_preprocessor.md Demonstrates how preprocess_command handles commands with already separated pipe operators and special operators like '&&' and '||'. These are typically left unchanged. ```python from mcp_shell_server.command_preprocessor import CommandPreProcessor preprocessor = CommandPreProcessor() # Separated pipes result = preprocessor.preprocess_command(["cat", "file.txt", "|", "grep", "pattern"]) # Returns: ["cat", "file.txt", "|", "grep", "pattern"] (unchanged) # Special operators result = preprocessor.preprocess_command(["cmd1", "&&", "cmd2", "||", "cmd3"]) # Returns: ["cmd1", "&&", "cmd2", "||", "cmd3"] (unchanged) ``` -------------------------------- ### Handle Failed Process Creation Source: https://github.com/tumf/mcp-shell-server/blob/main/_autodocs/errors.md This error is a wrapper around failures from asyncio.create_subprocess_exec(). Common causes include command not found, permission issues, resource limits, or shell environment problems. ```python # Example illustrating the context, not direct code execution # ProcessManager.create_process(command='non_existent_command') ```