Loading repository data…
Loading repository data…
samerfarida / repository
Secure SSH access for AI agents via MCP. Execute commands across your server fleet with policy enforcement, network controls, and comprehensive audit logging.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
Imagine this: Your AI assistant (Claude, ChatGPT, etc.) can access your servers, but you're terrified of what it might do. rm -rf /? Delete your databases? Change firewall rules?
Now imagine this: Your AI has governed, auditable access to your infrastructure. It can check logs, restart services, and manage your fleet, but only if your security policies allow it.
That's exactly what MCP SSH Orchestrator provides: the power of AI-driven server management with deny-by-default access control, IP allowlists, host key verification, and comprehensive audit logging backed by declarative YAML policy-as-code (config/servers.yml, config/credentials.yml, config/policy.yml).
rm -rf, dd, file deletionsYou say: "Claude, my Proxmox host is running slow. Can you check disk usage and memory on all my VMs?"
df -h and free -m on Proxmox hostsproxmoxYou say: "We're seeing 500 errors. Check nginx logs across all production web servers and show me the last 100 error lines."
tail -n 100 /var/log/nginx/error.log runs on all web-prod serversYou say: "Update system packages on all staging servers, but show me what would change first before running the upgrade."
ssh_plan to preview apt list --upgradable across staging tagged hostsapt update && apt upgrade -y is allowed on staging# Optional: bootstrap everything with the compose helper script
# (runs from the repo root or from your target config directory)
./compose/setup.sh enduser
# Or download it separately
curl -fsSLO https://raw.githubusercontent.com/samerfarida/mcp-ssh-orchestrator/main/compose/setup.sh
chmod +x setup.sh
./setup.sh enduser
If you prefer to lay things out manually, follow the steps below.
# Pull the latest release
docker pull ghcr.io/samerfarida/mcp-ssh-orchestrator:latest
# Create directories for config, keys, and secrets
mkdir -p ~/mcp-ssh/{config,keys,secrets}
# Copy example configs to get started quickly
cp examples/example-servers.yml ~/mcp-ssh/config/servers.yml
cp examples/example-credentials.yml ~/mcp-ssh/config/credentials.yml
cp examples/example-policy.yml ~/mcp-ssh/config/policy.yml
# Add your SSH key (replace with your private key file)
cp ~/.ssh/id_ed25519 ~/mcp-ssh/keys/
chmod 0400 ~/mcp-ssh/keys/id_ed25519
# (Optional) Pin trusted hosts and prepare secret files
cp ~/.ssh/known_hosts ~/mcp-ssh/keys/known_hosts
# Option 1: Individual secret files (Docker secrets compatible)
cat > ~/mcp-ssh/secrets/prod_db_password.txt <<'EOF'
CHANGE-ME
EOF
chmod 600 ~/mcp-ssh/secrets/prod_db_password.txt
# Option 2: Consolidated .env file (recommended for easier management)
cat > ~/mcp-ssh/secrets/.env <<'EOF'
# SSH Passwords
prod_db_password=CHANGE-ME
lab_password=CHANGE-ME-TOO
# SSH Key Passphrases
prod_key_passphrase=CHANGE-ME-PASSPHRASE
EOF
chmod 600 ~/mcp-ssh/secrets/.env
# Note: .env file supports KEY=value format, comments, and quoted values
# See docs/wiki/06.2-credentials.yml.md for details
docker run -d --name mcp-ssh-orchestrator \
-v ~/mcp-ssh/config:/app/config:ro \
-v ~/mcp-ssh/keys:/app/keys:ro \
-v ~/mcp-ssh/secrets:/app/secrets:ro \
ghcr.io/samerfarida/mcp-ssh-orchestrator:latest
Restart later with docker start mcp-ssh-orchestrator. Prefer disposable containers? Use docker run -i --rm ... instead.
~/.cursor/mcp.json{
"mcpServers": {
"mcp-ssh-orchestrator": {
"command": "docker",
"args": ["start", "-a", "mcp-ssh-orchestrator"],
"env": {"PYTHONUNBUFFERED": "1"}
}
}
}
~/Library/Application Support/Claude/claude_desktop_config.json{
"mcpServers": {
"ssh-orchestrator": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/Users/YOUR_USERNAME/mcp-ssh/config:/app/config:ro",
"-v", "/Users/YOUR_USERNAME/mcp-ssh/keys:/app/keys:ro",
"-v", "/Users/YOUR_USERNAME/mcp-ssh/secrets:/app/secrets:ro",
"ghcr.io/samerfarida/mcp-ssh-orchestrator:latest"
]
}
}
}
(Windows path: %APPDATA%\\Claude\\claude_desktop_config.json.)
More examples (Docker Desktop, multi-environment, SDK usage) live in the Integrations guide.
# List configured hosts through the MCP server
echo '{"jsonrpc":"2.0","method":"tools/call","params":{"name":"ssh_list_hosts","arguments":{}},"id":1}' | \
docker run -i --rm \
-v ~/mcp-ssh/config:/app/config:ro \
-v ~/mcp-ssh/keys:/app/keys:ro \
-v ~/mcp-ssh/secrets:/app/secrets:ro \
ghcr.io/samerfarida/mcp-ssh-orchestrator:latest
Cursor/Claude should now show the orchestrator as connected. Jump to the Usage Cookbook for guided scenarios.
Policy-as-code workflow: config/servers.yml, config/credentials.yml, and config/policy.yml are parsed on startup, enforced during every ssh_* tool invocation, and mirrored in the structured audit logs so the same declarative files you review in Git gate what your AI can execute.
graph TB
subgraph "Layer 1: Transport Security"
L1A[stdio Communication]
L1B[Container Isolation]
end
subgraph "Layer 2: Network Security"
L2A[IP Allowlists]
L2B[Host Key Verification]
end
subgraph "Layer 3: Policy Security"
L3A[Deny-by-Default]
L3B[Pattern Matching]
end
subgraph "Layer 4: Application Security"
L4A[Non-Root Execution]
L4B[Resource Limits]
end
L1A --> L2A
L1B --> L2B
L2A --> L3A
L2B --> L3B
L3A --> L4A
L3B --> L4B
style L1A fill:#e1f5ff
style L1B fill:#e1f5ff
style L2A fill:#d4edda
style L2B fill:#d4edda
style L3A fill:#fff3cd
style L3B fill:#fff3cd
style L4A fill:#f8d7da
style L4B fill:#f8d7da
# Dangerous commands automatically denied
deny_substrings:
# Destructive operations
- "rm -rf /"
- ":(){ :|:& };:"
- "mkfs "
- "dd if=/dev/zero"
- "shutdown -h"
- "reboot"
- "userdel "
- "passwd "
# Lateral movement / egress tools
- "ssh "
- "