sudo-mcp

command module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 2, 2026 License: MIT Imports: 10 Imported by: 0

README

sudo-mcp

An MCP server that lets a coding agent run sudo commands without piping a password through the model.

Disclaimer: this tool has no command denylist. Whatever command the agent passes, sudo will run it. Add your own guardrails (sudoers Cmnd_Alias, wrapper script, sandbox) if you want any.

The problem

Claude Code's Bash tool redirects stdin to /dev/null, so any sudo invocation that needs a password fails immediately with a terminal is required to read the password. The usual workarounds are bad: NOPASSWD: ALL in sudoers gives the agent permanent passive root; running sudo claude gives the entire session permanent root; pasting the password into chat exposes it to the model context, the transcript, and any future training set.

What this does

sudo-mcp is a single static Go binary that exposes one MCP tool, sudo_run(argv, reason, timeout_seconds?, cwd?). When the agent calls it:

  1. The server sets SUDO_ASKPASS to its own path and exec's sudo -A -- argv....
  2. sudo invokes the askpass helper. The same binary handles that role too, dispatched on SUDO_MCP_ROLE=askpass.
  3. The askpass role pops a native OS dialog (osascript on macOS, ssh-askpass/ksshaskpass/zenity/kdialog on Linux) showing the reason so the user knows what they are authorizing.
  4. The user types the password into the dialog. It goes to sudo's stdin only.
  5. The server captures stdout, stderr, and exit code, returns them as the tool result.

The password never touches the MCP transport, the model context, the conversation transcript, or ~/.bash_history. The agent learns the command's exit code and output, nothing else.

Install

Requires sudo. macOS works out of the box. On Linux you need at least one of ssh-askpass, ksshaskpass, zenity, or kdialog.

Grab the archive for your OS/arch from the latest release: https://github.com/0xMH/sudo-mcp/releases/latest

# macOS arm64 example; substitute the asset for your platform
curl -L -o sudo-mcp.tar.gz https://github.com/0xMH/sudo-mcp/releases/latest/download/sudo-mcp_0.3.0_darwin_arm64.tar.gz
tar -xzf sudo-mcp.tar.gz
install -m 0755 sudo-mcp ~/.local/bin/sudo-mcp

Verify the SHA-256 against checksums.txt from the same release before running.

From source

Requires Go 1.22+.

go install github.com/0xMH/sudo-mcp@latest

The binary lands in $(go env GOBIN) (typically ~/go/bin/sudo-mcp). Make sure that directory is on your $PATH, or use the absolute path when registering.

Wire into Claude Code

Register the server at user scope so it is available in every project:

claude mcp add sudo-mcp --scope user -- ~/go/bin/sudo-mcp

Verify:

claude mcp list

You should see sudo-mcp: ~/go/bin/sudo-mcp - ✓ Connected.

To make the agent actually prefer sudo_run over typing sudo into Bash, deny Bash(sudo *) in ~/.claude/settings.json:

{
  "permissions": {
    "deny": ["Bash(sudo *)", "Bash(sudo)"],
    "allow": ["mcp__sudo-mcp__sudo_run"]
  }
}

Tool reference

sudo_run takes:

  • argv (string array, required): command and arguments. Pass as a list, not a shell string. Example: ["apt", "install", "-y", "htop"]. The server exec's directly with no shell, so injection through arg concatenation is structurally impossible.
  • reason (string, required): one-line justification rendered in the password dialog so the user sees what they are authorizing before typing the password.
  • timeout_seconds (int, optional, default 120, max 3600): hard kill if sudo hangs longer than this.
  • cwd (string, optional): working directory for the command.

Returns a text block with the exit code, stdout, and stderr. Output is truncated at 256 KiB per stream.

Security properties

  • The password is entered into a native OS dialog. The dialog is rendered by the user's window server, not the agent. The agent cannot read it, screenshot it, or replay it.
  • The MCP transport carries argv, reason, exit code, stdout, stderr. It never carries credentials.
  • argv is a list, never a shell string. There is no bash -c involved, so no quoting bugs and no injection through reason interpolation.
  • Sudo's timestamp cache is left at its system default (typically 5 minutes on macOS). Calls inside that window skip the dialog. Drop -A and add -k in main.go if you want a fresh prompt every time.
  • The server only exposes one tool. There is no shell access, no arbitrary subprocess execution outside of sudo.

License

MIT. See LICENSE.

Documentation

Overview

sudo-mcp is an MCP server that runs sudo commands via a native OS password dialog. The same binary doubles as the SUDO_ASKPASS helper: when invoked with SUDO_MCP_ROLE=askpass (sudo execs the path in SUDO_ASKPASS, we set it to our own path), it pops the dialog and writes the password to stdout. Passwords go from the dialog to sudo's stdin only — never through the MCP transport, never into the model context.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL