An MCP server for executing commands across platforms
This server implements a single destructive command-execution tool with minimal documentation and no input validation. The tool definition is visible in server.py with a basic schema, but descriptions are sparse, parameter documentation is inadequate, and error handling is generic. The tool name 'execute_command' is generic (not following verb_noun pattern well) and the implementation lacks the safety guardrails, recovery guidance, and structured error responses expected of production tools. The DESTRUCTIVE risk classification makes the gaps particularly severe.
Execute a command and return the result
Tool name 'execute_command' is generic and does not convey risk or specificity. Should be 'run_shell_command' or similar to make destructiveness explicit. Current name could be confused with safer operations.
Tool description is only 'Execute a command and return the result', far too brief (32 chars, below 50-char minimum). Missing: when to use it, risk of irreversibility, command format requirements, return value structure, and prerequisites. LLMs cannot determine whether to call this vs safer alternatives.
Parameter 'command' lacks description entirely in schema. Parameter 'shell' has minimal description ('Whether to execute the command through a shell') but does not warn about the security implications of shell=true (command injection risk). Parameter 'cwd' description is generic.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | F | 33 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 27 | - | v1 |
No output schema documented. The code returns a dict with 'success', 'returncode', 'stdout', 'stderr', and optional 'error', but this structure is not formally declared. LLMs cannot plan downstream processing without knowing output fields.
Error handling is minimal and not actionable. Generic exception handling returns 'error' field with str(e), providing no guidance to the LLM on recovery. Example: 'Invalid command' does not tell the LLM whether to retry, ask the user, or abort.
No permission gating or scope declaration. Any client can execute arbitrary commands. Missing authorization checks, audit logging, and scope boundaries (e.g., 'Can execute commands in /safe/path only'). A compromised agent can run rm -rf / without friction.
No input validation or sanitization. The 'command' parameter accepts free-form strings. The code calls shlex.split() on non-Windows shells, but does not validate command name against a whitelist, does not restrict to safe directories, and does not guard against command injection via environment variables or cwd traversal.
No dry-run or confirmation mechanism. This tool can delete files, terminate processes, or modify system state irreversibly. LLMs make mistakes, there is no confirm_before_execute pattern to prevent catastrophic errors.
No timeout or rate limiting. External commands can hang indefinitely, blocking the agent. No rate limits prevent a looping agent from exhausting system resources.
Schema input parameter 'shell' defaults to false but documentation does not explain the implications. When shell=true on Unix, many commands work differently (glob expansion, pipes, redirects enabled). When shell=true on Windows, cmd.exe is invoked. LLMs need explicit guidance on when to use shell=true vs false.