bladerunner-mcp
MCP server that lets an AI session operate your remote machines over SSH.
⚠️ These tools run real commands on real servers with your credentials. Running your MCP client in auto-approve ("YOLO") mode means the model can execute anything on your machines without you seeing it first. Keep manual approval on for this server, use least-privilege SSH accounts, and have backups/snapshots for anything you point it at. See Security.
You pip install bladerunner-mcp, describe your hosts (e.g. a Hetzner box) in a
YAML config with credentials, and the server exposes MCP tools to run commands,
track long-running processes and transfer files on those hosts. The model only
ever sees host aliases — secrets never enter the conversation.
Scope: POSIX remote hosts only (sh, nohup, tail, head, wc must be
present on the target). Windows hosts are not supported.
Tools
| Tool | Description |
|---|---|
list_hosts |
List configured host aliases (no secrets) |
run_command |
Run a shell command on a host, return stdout/stderr/exit code (capped at 64 KiB per stream) |
read_output |
Page through the full output of a truncated run_command or a background process |
start_process |
Start a long-running command in the background (nohup), return pid + work_dir |
check_process |
Report process status (running/succeeded/failed/unknown), exit code and log tails |
kill_process |
Kill a background process |
put_file |
Upload a local path to a host via rsync |
get_file |
Download a remote path from a host via rsync |
Large outputs: run_command keeps the full output on the host (in a work_dir
under /tmp/bladerunner_mcp/) whenever it exceeds the 64 KiB cap and returns
truncated: true — page through it with read_output(host, work_dir, offset=...).
Installation
pip install bladerunner-mcp
Configuration
Copy bladerunner_mcp.example.yaml to
~/.bladerunner_mcp.yaml (or set BLADERUNNER_MCP_CONFIG to its path):
hosts:
hetzner-prod:
host: 203.0.113.10
user: root
port: 22
key_path: ~/.ssh/id_ed25519
# key_passphrase: "..." # for passphrase-protected keys (commands only)
strict_host_key: true # verify against system known_hosts (default: false)
allow_dangerous: false # keep the safety filters on (default)
# protected_paths: [/etc, /var/lib] # override the default protected list
# allowed_remote_paths: [/srv/app, /var/log/app] # opt-in transfer allowlist
# allowed_local_paths: [~/deploys]
Register with a client
Claude Code:
claude mcp add bladerunner -- bladerunner-mcp
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"bladerunner": {
"command": "bladerunner-mcp",
"env": { "BLADERUNNER_MCP_CONFIG": "/Users/me/.bladerunner_mcp.yaml" }
}
}
}
Security
- Do not run your MCP client in auto-approve ("YOLO") mode with this server.
Every
run_command/start_processcall is a real shell on a real machine; keep per-call approval on so you see each command before it runs. - Protected-path filter (commands) — mutating operations (
rm,mv,chmod,chown,shred,truncate,chattr,sed -i,tee, output redirects, andcp/rsync/install/lnwriting into them) on system paths (/,/etc,/boot,/bin,/sbin,/usr,/lib*,/dev,/sys,/proc,/root,/var/lib) are rejected; reads of the same paths and mutations elsewhere pass. Catastrophic non-path patterns (mkfs,dd of=/dev/...,shutdown/reboot, fork bombs,DROP TABLE/DATABASE) are also rejected. Override with per-hostprotected_paths. This is a seatbelt against accidents, not a security boundary: shell is not statically analyzable. Disable per host withallow_dangerous: true. - Path validation (transfers) —
put_file/get_filepaths are expanded and normalized (..resolved) and then enforced for real: protected system prefixes are denied on the remote side, and~/.ssh,~/.gnupg,~/Library/Keychainsplus system dirs on the local side (both directions — exfiltrating local keys is as bad as overwriting them). Optional per-hostallowed_remote_paths/allowed_local_pathsrestrict transfers to listed prefixes. Remote symlinks are not resolved (known limit). - Least privilege — point the server at dedicated SSH accounts with the
minimum rights the task needs, not at
root, and keep backups/snapshots of anything it can touch. - Host keys — by default unknown host keys are auto-accepted (convenient,
MITM-unsafe). Set
strict_host_key: trueper host to verify against your systemknown_hosts(applies to both paramiko and rsync). - Auth — prefer SSH keys; passphrase-protected keys work for command
tools via
key_passphrase(transfers need an agent-loaded or plain key). Password auth works (rsync falls back tosshpass, which exposes the password in the local process list) and the password sits in plaintext YAML; treat it as legacy-host escape hatch only. - Secrets stay local — the model sees host aliases only; keys and passwords never enter the conversation. Executed commands are logged to stderr for audit.
Design
- One short file (bladerunner_mcp/server.py) built on
MCPServerfrom the officialmcpPython SDK. - Command execution via paramiko; background processes follow the
nohup + PID + exit-code-file pattern proven in
blade_runner's
SSHBackend(the AI session itself plays the role of the polling monitor, so the full FSM is not embedded). - File transfer via rsync_ssh_client
(
put/getover rsync+SSH, sshpass fallback for password auth).
Development
pip install -e ".[dev]"
pytest # unit tests (mocked paramiko/rsync)
RUN_E2E=1 pytest tests/e2e # e2e against a docker compose sshd container
ruff check . && mypy bladerunner_mcp
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file bladerunner_mcp-0.5.0.tar.gz.
File metadata
- Download URL: bladerunner_mcp-0.5.0.tar.gz
- Upload date:
- Size: 22.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
349613d5645f86c1e22674f67105c7ac46e0016819267963bb4543ea5c7df2f5
|
|
| MD5 |
9b4563117a2542df1aa99af8136c5152
|
|
| BLAKE2b-256 |
e51c019cd9c068ffd8af535a4c68e26038fb9eed387eef5289b99a9c079d79c8
|
File details
Details for the file bladerunner_mcp-0.5.0-py3-none-any.whl.
File metadata
- Download URL: bladerunner_mcp-0.5.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ce18e3213a8fb30b4f37ca73dc263963887d72e75af50159cf3ae06fddce7d64
|
|
| MD5 |
6167582658d7f7bb3a5b4205d01fd501
|
|
| BLAKE2b-256 |
a822deca0f0e66c956d6fd0e42ff85ca3d7d326bf12bad217eed7d61d7351db3
|