Shuttle
by enwaiax
README.md
<div align="center">
# π Shuttle
**Secure SSH gateway for AI assistants**
[](https://lobehub.com/mcp/enwaiax-shuttle)
[](https://github.com/enwaiax/shuttle/actions/workflows/test.yml)
[](https://codecov.io/gh/enwaiax/shuttle)
[](https://pypi.org/project/shuttle-mcp)
[](https://pepy.tech/project/shuttle-mcp)
[](https://python.org)
[](https://enwaiax.github.io/shuttle/)
[](LICENSE)
Shuttle lets AI assistants (Claude Code, Cursor, etc.) securely execute commands on your remote SSH servers β with connection pooling, session isolation, command safety rules, and a web audit panel.
[Getting Started](#getting-started) Β· [MCP Tools](#mcp-tools) Β· [Web Panel](#web-panel) Β· [Security Rules](#security-rules) Β· [Docs](https://enwaiax.github.io/shuttle/) Β· [δΈζζζ‘£](README_CN.md)
</div>
______________________________________________________________________
## Why Shuttle?
When AI coding assistants need to operate remote servers (run tests on GPU machines, deploy to staging, check logs), they need a secure bridge. Shuttle provides:
- **π 4-Level Command Security** β Block dangerous commands, require confirmation for risky ones, warn on installs, allow the rest
- **π Connection Pooling** β Reuse SSH connections across commands, no repeated handshakes
- **π¦ Session Isolation** β Each AI conversation gets its own working directory context
- **π Web Audit Panel** β See every command the AI ran, per node, with full stdout/stderr
- **π‘οΈ Per-Node Rules** β Different security policies for prod vs dev servers
- **β‘ Jump Host Support** β Connect through bastion/jump servers
## Getting Started
### 1. Install
```bash
# Recommended: install CLI once (tools bin on PATH)
uv tool install shuttle-mcp
shuttle --help
# Or run without installing (stdio / one-off)
uvx shuttle-mcp --help
# Older PyPI wheels without the `shuttle-mcp` script:
# uvx --from shuttle-mcp shuttle --help
```
### 2. Add your first node
```bash
shuttle node add
# Follow the prompts: name, host, username, password/key
```
### 3. Connect to your AI assistant
**Claude Code / Cursor (stdio mode):**
```json
// .mcp.json
{
"mcpServers": {
"shuttle": {
"command": "uvx",
"args": ["shuttle-mcp"]
}
}
}
```
**Service mode (with Web UI):**
```bash
# Start the service
shuttle serve
# Then configure your AI client with the URL
```
```json
// .mcp.json
{
"mcpServers": {
"shuttle": {
"url": "http://localhost:9876/mcp/"
}
}
}
```
That's it. Your AI assistant can now execute commands on your remote servers.
## Two Running Modes
| Mode | Command | MCP Transport | Web UI | Use Case |
| ----------- | --------------- | --------------- | ------------------------ | -------------------------------------- |
| **CLI** | `shuttle` | stdio | β | Quick use, AI client manages lifecycle |
| **Service** | `shuttle serve` | streamable-http | β
http://localhost:9876 | Audit logs, manage rules, cloud deploy |
Both modes share the same SQLite database β commands logged in CLI mode are visible in the Web UI when you switch to service mode.
## MCP Tools
AI assistants get these tools automatically:
| Tool | Description |
| ---------------- | ------------------------------------------------------ |
| `ssh_run` | Run a command on a remote node (sessions auto-managed) |
| `ssh_upload` | Upload a file via SFTP |
| `ssh_download` | Download a file via SFTP |
| `ssh_list_nodes` | List all configured nodes |
| `ssh_add_node` | Add a new SSH node |
### Example conversation
```
You: Check the GPU usage on my training server
AI: β ssh_run(node="gpu-server", command="nvidia-smi")
AI: Your GPU server has 7x A100-80GB, all idle at 0% utilization.
You: Start a training run
AI: β ssh_run(node="gpu-server", command="cd /workspace && python train.py")
AI: Training started. Epoch 1/10... (working directory preserved automatically)
```
## Security Rules
Commands are evaluated against a 4-level security system:
| Level | Behavior | Example |
| -------------- | ---------------------------- | ----------------------------- |
| π΄ **block** | Rejected immediately | `rm -rf /`, `mkfs`, fork bomb |
| π‘ **confirm** | Requires user confirmation | `sudo`, `rm -rf`, `shutdown` |
| π **warn** | Executes with warning logged | `apt install`, `pip install` |
| π’ **allow** | Executes normally | Everything else |
Default rules are seeded on first startup. Customize via Web UI or directly in the database.
### Per-Node Overrides
Different servers can have different rules:
```
Global: sudo .* β confirm
GPU Server: sudo .* β allow (trusted environment)
Prod Server: DROP TABLE β block (extra protection)
```
## Web Panel
Start with `shuttle serve`, open `http://localhost:9876`:
- **Overview** β Node cards with status, quick stats
- **Activity** β Per-node command log (console-style, with stdout/stderr)
- **Security Rules** β Manage global defaults and per-node overrides
- **Settings** β Connection pool and cleanup configuration
The Web UI requires a bearer token (displayed when you run `shuttle serve`).
## CLI Reference
```bash
# MCP Server
shuttle # Start MCP server (stdio mode)
shuttle serve # Start service mode (MCP + Web)
shuttle serve --port 8080 # Custom port
shuttle serve --host 0.0.0.0 # Bind to all interfaces
# Node Management
shuttle node add # Add node interactively
shuttle node list # List all nodes
shuttle node test <name> # Test SSH connection
shuttle node edit <name> # Edit a node
shuttle node remove <name> # Remove a node
# Configuration
shuttle config show # Display current config
```
## Configuration
All settings can be overridden with environment variables (prefix `SHUTTLE_`):
| Variable | Default | Description |
| --------------------------- | ------------------------------------------- | --------------------------------- |
| `SHUTTLE_DB_URL` | `sqlite+aiosqlite:///~/.shuttle/shuttle.db` | Database URL |
| `SHUTTLE_WEB_PORT` | `9876` | Web panel port |
| `SHUTTLE_POOL_MAX_TOTAL` | `50` | Max total SSH connections |
| `SHUTTLE_POOL_MAX_PER_NODE` | `5` | Max connections per node |
| `SHUTTLE_POOL_IDLE_TIMEOUT` | `300` | Idle connection timeout (seconds) |
### Using PostgreSQL
```bash
SHUTTLE_DB_URL=postgresql+asyncpg://user:pass@host:5432/shuttle shuttle serve
```
Requires: `uv pip install asyncpg` (install into the same environment that runs Shuttle)
## Development
```bash
# Clone and install
git clone https://github.com/enwaiax/shuttle.git
cd shuttle
uv sync
# Run tests
uv run pytest tests/ -v
# Lint
uv run ruff check src/ tests/
# Frontend dev (hot reload)
cd web && npm install && npm run dev
# Backend: uv run shuttle serve (in another terminal)
```
## Architecture
```
Developer β AI Assistant β Shuttle (MCP) β SSH β Remote Servers
β
βββββββββββ΄βββββββββββ
β Core Engine β
β β ConnectionPool β
β β SessionManager β
β β CommandGuard β
β β SQLAlchemy ORM β
ββββββββββββββββββββββ
```
**Service mode:** Single ASGI app serving both MCP (at `/mcp/`) and Web UI (at `/`) on the same port.
## License
[MIT](LICENSE)
______________________________________________________________________
<div align="center">
<sub>Built for developers who let AI do the SSH-ing.</sub>
</div>
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessWithin a week