mcp-shell-sudo
The server lets an MCP client execute local shell commands and remote SSH commands as explicit argv arrays, with optional sudo, working-directory confinement, and executable allowlisting.
Run arbitrary local commands such as
["ls", "-la"]or["git", "status"]viashell_execute.Provide stdin, set a working directory, and set a timeout for each command.
Execute commands with local
sudousing a configured password or non-interactivesudo -n.Run commands on remote hosts via
ssh_executeusing OpenSSH aliases, with optional SSH port, TTY, timeout, and remote sudo.Feed stdin to remote commands and request remote elevation with
sudo: true.Use
shell_executewith the simple compatibility form["ssh", "host", "sudo", "command", ...].Restrict available executables with
ALLOW_COMMANDS(e.g.,git,ls,cat), validated for both local and remote commands.Confine local filesystem writes to a
WORK_DIRusing Bubblewrap, which also disables sudo and SSH to preserve isolation.Inspect effective non-secret configuration (allowlist, sudo-password presence, confinement status, SSH availability) through
shell_config.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-shell-sudorun git status in the current directory"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-shell-sudo
Warning: Use this MCP with caution. If sudo credentials are configured, it can execute privileged commands both on the host machine and on SSH-connected remote systems.
MCP server for Linux written in Python that executes local and remote SSH commands using explicit argv arrays, supports non-interactive local and remote sudo, provides an optional executable allowlist through ALLOW_COMMANDS, and can confine local filesystem writes to WORK_DIR using Bubblewrap.
Requirements
Linux.
Python 3.11+.
uvrecommended.MCP Python SDK 2.0.0.
sudoif elevated commands will be executed.OpenSSH client (
ssh) if remote execution will be used.SSH login authentication configured through
~/.ssh/config, a key, or an SSH agent for non-interactive remote access.bubblewrapifWORK_DIRis configured.
On Debian/Ubuntu:
sudo apt update
sudo apt install -y bubblewrapRelated MCP server: Dynamic Shell Command MCP Server
Environment Variables
PASSWORD_SUDO
Password used for local sudo. It is also the fallback password for remote sudo when PASSWORD_SUDO_SSH is not configured.
Empty or unset: local
sudousessudo -n. Remotesudoalso usessudo -nunlessPASSWORD_SUDO_SSHis configured.Set: local
sudousessudo -S, and the password is provided through stdin, never through argv or logs. Remotesudoreuses this value only whenPASSWORD_SUDO_SSHis absent.
Example:
"PASSWORD_SUDO": "my-password"The supported form is:
["sudo", "id"]Custom sudo flags such as sudo -u postgres ... are not accepted. This prevents the policy layer from having to interpret the full sudo command grammar.
PASSWORD_SUDO_SSH
Optional password override used only for sudo on remote hosts executed through ssh_execute.
"PASSWORD_SUDO_SSH": "remote-sudo-password"Password selection for remote sudo is:
PASSWORD_SUDO_SSHwhen configured.Otherwise
PASSWORD_SUDO.If neither is configured, remote sudo uses
sudo -nand fails instead of waiting for an interactive password prompt.
This variable is not an SSH login password. ssh_execute does not inject SSH login credentials. SSH authentication must already work non-interactively through OpenSSH configuration, a key, or an SSH agent.
WORK_DIR
Optional working directory.
Empty or unset: the MCP server may work from any existing directory specified in the tool call.
Set: the server enters strict mode.
directorymust resolve insideWORK_DIR, and every process runs inside a Bubblewrap mount namespace where/is read-only,WORK_DIRis mounted read-write, and/tmpand/runare temporary.
Using cwd alone would not be sufficient to guarantee this isolation. A process could still write to /etc, /home/..., or follow symlinks outside the project. For this reason, the server fails at startup if WORK_DIR is configured but bwrap is unavailable.
In this mode, local sudo and all SSH execution are rejected. Host-level privilege escalation would break the local write-confinement guarantee, and local Bubblewrap confinement cannot restrict changes made on a remote host.
ALLOW_COMMANDS
Comma-separated list of executable names.
"ALLOW_COMMANDS": "git,ls,cat,grep,python,node,pnpm"Empty or unset: all executables are allowed.
Set: only exact executable names from the list are allowed, and they must be invoked by name rather than through paths such as
/usr/bin/git.If a local command starts with
sudo, the actual executable followingsudois validated.For
ssh_execute, bothsshand the remote target executable must be present in the allowlist.Direct arbitrary
sshcalls throughshell_executeare rejected while an allowlist is active; usessh_executeso the remote executable can also be validated. The simple compatibility form["ssh", "host", "sudo", "command", ...]is recognized and validated.
The allowlist applies to executables, not arguments. Allowing bash, python, node, env, or another tool capable of executing processes significantly expands what the MCP client can do.
Installation
Option 1 — Install directly from GitHub (recommended for users)
If you only want to use the MCP and do not need a local source checkout, install it directly
from the repository with uv:
uv tool install git+https://github.com/eaangrino/mcp-shell-sudo.gitThis installs mcp-shell-sudo in an isolated uv tool environment. You do not need to
clone the repository manually.
Verify that the executable is available:
command -v mcp-shell-sudoIf the uv tool bin directory is not yet in your PATH, run:
uv tool update-shellThe executable is typically available as ~/.local/bin/mcp-shell-sudo.
Option 2 — Clone the repository (development or local changes)
Clone the project when you want to inspect, modify, or contribute to the source code:
git clone https://github.com/eaangrino/mcp-shell-sudo.git
cd mcp-shell-sudo
uv syncInstall development dependencies with:
uv sync --extra devTo expose the executable while keeping the local source editable:
uv tool install --force --editable .Manual Execution
uv run mcp-shell-sudoThe transport is stdio. Logging is never written to stdout in order to avoid corrupting JSON-RPC messages; logs are written to stderr instead.
MCP Configuration
Example with unrestricted commands and sudo enabled:
{
"mcpServers": {
"shell": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/mcp-shell-sudo",
"run",
"mcp-shell-sudo"
],
"env": {
"PASSWORD_SUDO": "YOUR_PASSWORD",
"WORK_DIR": "",
"ALLOW_COMMANDS": ""
}
}
}
}Example using the installed executable with separate local and remote sudo passwords:
{
"mcpServers": {
"mcp-shell-sudo": {
"command": "/home/user/.local/bin/mcp-shell-sudo",
"env": {
"PASSWORD_SUDO": "LOCAL_SUDO_PASSWORD",
"PASSWORD_SUDO_SSH": "REMOTE_SUDO_PASSWORD"
}
}
}
}If local and remote sudo use the same password, omit PASSWORD_SUDO_SSH; PASSWORD_SUDO is reused automatically for remote sudo.
Example confined to a specific project:
{
"mcpServers": {
"shell-project": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/mcp-shell-sudo",
"run",
"mcp-shell-sudo"
],
"env": {
"PASSWORD_SUDO": "",
"WORK_DIR": "/home/user/projects/app",
"ALLOW_COMMANDS": "git,ls,cat,grep,find,python,node,pnpm"
}
}
}
}shell_execute Tool
Basic input:
{
"command": ["ls", "-la"]
}With a working directory:
{
"command": ["git", "status"],
"directory": "backend"
}With stdin:
{
"command": ["cat"],
"stdin": "hello\n"
}With sudo:
{
"command": ["sudo", "id"]
}Response:
{
"stdout": "uid=0(root) gid=0(root) groups=0(root)\n",
"stderr": "",
"status": 0,
"execution_time": 0.031,
"timed_out": false,
"output_limited": false
}ssh_execute Tool
Use ssh_execute when the command must run on another machine. The command array must contain the remote executable and arguments without sudo; request elevation with sudo: true.
Basic remote execution:
{
"host": "server-alias",
"command": ["id"]
}Remote sudo:
{
"host": "server-alias",
"command": ["systemctl", "status", "docker", "--no-pager"],
"sudo": true
}Optional SSH port and TTY:
{
"host": "my-server",
"command": ["id"],
"sudo": true,
"port": 2222,
"tty": true,
"timeout": 120
}For non-default usernames, identity files, or other SSH options, configure an OpenSSH alias first:
Host my-server
HostName example.com
User user
IdentityFile ~/.ssh/my-server
Port 2222Then pass only the alias in host.
host: an OpenSSH destination or alias. Authentication must already work non-interactively using~/.ssh/config, a default SSH key, or an SSH agent. An alias is recommended when a specific user, non-default identity file, or other SSH options are required.command: remote argv excludingsudo.sudo: when true, runs the remote command assudo -S -p '' -- ...when a remote sudo password is configured, otherwise assudo -n -- ....stdin: optional data delivered to the remote command after the sudo password.port: optional TCP port from 1 to 65535. It controls the SSH connection port; it does not provide authentication credentials.tty: usesssh -tt; enable it only if the remote sudo policy requires a TTY. It does not makessh_executehandle an interactive SSH login password prompt.timeout: 60 seconds by default, capped at 600 seconds.
SSH login authentication is handled entirely by the local OpenSSH client. ssh_execute does not inject an SSH login password and does not currently accept an explicit identity-file parameter equivalent to ssh -i. If a non-default private key is required, configure it with IdentityFile in ~/.ssh/config or load it into an SSH agent.
For compatibility, shell_execute also recognizes the common simple form:
{
"command": ["ssh", "server-alias", "sudo", "id"]
}For explicit remote execution or more complex SSH requirements, prefer ssh_execute.
shell_config Tool
Returns the effective non-secret configuration.
It never returns PASSWORD_SUDO or PASSWORD_SUDO_SSH. It reports only non-secret state such as whether local/remote sudo password injection is configured, whether ssh is available, whether WORK_DIR confinement is active, and the effective allowlist.
Implemented Security Measures
Uses
create_subprocess_exec; it does not useshell=True.commandis passed as an explicit argv array.Local and remote sudo passwords never appear in process argv or the child process environment; configured secrets are also redacted from stdout/stderr before results are returned.
If no applicable sudo password is configured,
sudo -nprevents the process from hanging while waiting for an interactive password prompt.SSH login authentication remains delegated to OpenSSH configuration, keys, and agents; the MCP server does not handle SSH login passwords.
SSH_AUTH_SOCKis forwarded when present so OpenSSH can use the current SSH agent.Remote argv elements are quoted with
shlexsemantics before being passed to OpenSSH.ALLOW_COMMANDSvalidates the local executable after a simplesudoinvocation and, forssh_execute, validates bothsshand the remote target executable.Uses a fixed and reduced
PATHto avoid resolving executables from.or arbitrary inherited paths.Uses a reduced child environment instead of inheriting the entire MCP server environment.
Per-call timeout: 60 seconds by default, with a maximum of 600 seconds.
Output limit: 2 MiB per stream. If the limit is exceeded, the entire process group is terminated.
Processes run in a new session, and the entire process group is terminated on timeout.
WORK_DIRuses Bubblewrap and fails closed if isolation cannot be provided. SSH execution and sudo are disabled whileWORK_DIRis active where confinement cannot be guaranteed.
Important Limitations
ALLOW_COMMANDS=""means arbitrary command execution with the permissions of the user running the MCP server. If a sudo password is also configured, the MCP client can request root actions locally and, throughssh_execute, on SSH hosts for which authentication is already available. Use this configuration only with a client and model you control.An executable allowlist does not semantically validate command arguments.
python,node,bash,sh,perl, and similar tools are effectively equivalent to allowing arbitrary code execution.WORK_DIRis a local filesystem confinement mechanism, not a VM or network sandbox. Because it cannot constrain remote filesystem changes, SSH execution is intentionally disabled wheneverWORK_DIRis configured.Remote execution can modify another machine with the permissions of the SSH account or root when
sudo: truesucceeds. OpenSSH host verification and trust remain governed by the user's SSH configuration andknown_hosts.PASSWORD_SUDOandPASSWORD_SUDO_SSHstored in the MCP client configuration remain secrets stored in that file. Restrict the file permissions withchmod 600and never commit it to version control.
Tests
uv run --extra dev pytest
uv run --extra dev ruff check .Available Tools
2 toolsshell_configA
Return the effective non-secret shell policy configuration.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description serves as the only behavioral disclosure. It implies a read-only operation ('Return') but does not explicitly state that it has no side effects or that it is safe. It does clarify that secrets are excluded, which is a useful constraint. However, it does not mention any authentication or permission requirements, which could be relevant.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, concise sentence that front-loads the action ('Return') and specifies the resource. There is no wasted verbiage.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that there are no parameters, the description sufficiently conveys the tool's function. The existence of an output schema covers return details, so the description need not elaborate. It does not mention usage context, but that is already addressed in usage_guidelines; for a simple config retrieval, this is complete enough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero parameters, so the description is not required to explain parameter syntax. The phrase 'non-secret' adds context about the output scope but does not relate to parameters. For a parameterless tool, this is adequate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Return') and a clear resource ('effective non-secret shell policy configuration'). It distinguishes itself from the sibling tool by nature (configuration retrieval vs. execution), though it does not explicitly name the alternative. The purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is given for when to use this tool versus the sibling shell_execute. An agent must infer that this is for reading configuration, not executing commands. The description does not mention any prerequisites, alternatives, or context for selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shell_executeA
Execute one command as an argv array.
Args: command: Executable and arguments, for example ["ls", "-la"] or ["sudo", "systemctl", "status", "ssh"]. Shell syntax is not interpreted. stdin: Optional text sent to the command's standard input. directory: Optional working directory. With WORK_DIR configured, this path must resolve inside WORK_DIR. Without WORK_DIR, any existing directory may be used. timeout: Execution timeout in seconds. Values above 600 seconds are capped at 600.
Returns: stdout, stderr, exit status, execution time, timeout flag, and output-limit flag.
| Name | Required | Description | Default |
|---|---|---|---|
| stdin | No | ||
| command | Yes | ||
| timeout | No | ||
| directory | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of disclosing behavioral traits. It mentions that shell syntax is not interpreted, that the timeout is capped at 600 seconds, and that directory paths must resolve inside WORK_DIR if configured. However, it does not warn about the potentially destructive nature of executing arbitrary commands or the side effects of the executed process, which is a notable omission for a command execution tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a clear one-line summary, a detailed 'Args' section, and a 'Returns' section. It is appropriately detailed for a tool with multiple parameters but remains readable. The example for the command parameter adds clarity without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description covers the essential invocation details: command format, directory constraints, timeout cap, and the return fields (stdout, stderr, exit status, etc.). It does not explain prerequisites such as the meaning of WORK_DIR, but this is likely a global configuration rather than tool-specific. Given the presence of an output schema (though not shown), the return-field listing is sufficient. Overall, it provides enough for an agent to call the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides no descriptions for any of the four parameters (schema coverage 0%), so the description must fully compensate. It does so thoroughly by explaining each parameter: the command array with examples, optional stdin, directory restrictions relative to WORK_DIR, and timeout cap. This adds substantial meaning beyond the schema's type definitions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource: 'Execute one command as an argv array.' It clearly distinguishes from the sibling tool 'shell_config' by implying execution vs. configuration, and provides a concrete example to clarify the argv format.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear guidance on how to invoke the tool, including the requirement to pass an argv array rather than shell syntax, and clarifies timeout and directory constraints. However, it does not explicitly state when to prefer this tool over shell_config, though the purpose difference is evident from the name and description.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
2 tool updates
v0.1.0- First observed
shell_config - First observed
shell_execute
TDQS
The two tools have completely distinct purposes: one executes commands and the other returns configuration. There is no overlap or potential for misselection between them.
Both tools follow the same snake_case verb_noun pattern (shell_execute, shell_config). The naming is clear, predictable, and consistent.
With only two tools, this server feels thin, but the narrow scope (shell execution and configuration) justifies the limited surface. It is at the lower edge of what is reasonable, as stated in the calibration.
The tool surface covers the core functionality of executing shell commands and retrieving configuration. There is no obvious missing operation for the stated purpose; the only minor gap might be a way to list allowed commands or test, but that is not essential.
Maintenance
Related MCP Connectors
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Scoped, audited SSH exec, sessions, and SFTP on your saved servers without exposing credentials
Remote MCP for Android CLI agent build gate, structured receipts, audit logs, and reviewer-ready evi
Secure tunneling, reverse proxy and remote access for local applications.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to securely execute shell commands on local machines through an SSH interface with session management, command execution, and sudo support.1-
- AlicenseNot gradedqualityCmaintenanceEnables secure execution of shell commands through a dynamic approval system that prompts for user authorization on first use, with persistent command storage and comprehensive audit logging.Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables AI models to safely execute pre-defined Linux shell commands with a whitelist mechanism, restricting execution to allowed commands only.1-
- AlicenseNot gradedqualityAmaintenanceProvides a secure, token-authenticated command execution tool over MCP Streamable HTTP, with a default-deny allowlist and shell metacharacter rejection.16Apache 2.0
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/eaangrino/mcp-shell-sudo'
If you have feedback or need assistance with the MCP directory API, please join our Discord server