# Bastion

> Open-source MCP Gateway for sandboxed AI agent execution. Built in Rust with DDD architecture — Podman, Firecracker, gVisor, K8s backends.

- **Type:** MCP server
- **Install:** `agentstack add mcp-rubentxu-bastion`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Rubentxu](https://agentstack.voostack.com/s/rubentxu)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** Apache-2.0
- **Upstream author:** [Rubentxu](https://github.com/Rubentxu)
- **Source:** https://github.com/Rubentxu/Bastion

## Install

```sh
agentstack add mcp-rubentxu-bastion
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# 🏰 Bastion

**MCP Gateway for Sandboxed AI Agent Execution**

[](https://www.rust-lang.org)
[](LICENSE)
[](https://github.com/Rubentxu/Bastion/actions/workflows/ci.yml)
[](https://github.com/Rubentxu/Bastion/releases)

---

**Bastion** is an open-source [MCP](https://spec.modelcontextprotocol.io/) (Model Context Protocol) Gateway that enables AI agents to safely execute tools in isolated sandbox environments — containers, microVMs, or kernel-level sandboxes. Built in Rust with Domain-Driven Design (DDD) and Clean Architecture.

## 📖 Table of Contents

- [Why Bastion?](#-why-bastion)
- [Architecture](#-architecture)
- [Features](#-features)
- [Quick Start](#-quick-start)
- [Usage](#-usage)
  - [With OpenCode](#with-opencode)
  - [With Claude Code](#with-claude-code)
  - [CLI Options](#cli-options)
- [MCP Tools](#-mcp-tools)
- [Architecture Deep Dive](#-architecture-deep-dive)
  - [DDD Crate Structure](#ddd-crate-structure)
  - [Data Flow](#data-flow)
- [Roadmap](#-roadmap)
- [Development](#-development)
- [Contributing](#-contributing)
- [License](#-license)

## 🤔 Why Bastion?

AI agents need to run code, but running untrusted code directly on the host is dangerous. Existing MCP servers typically execute commands in the same process or machine — no isolation, no resource limits, no cleanup.

**Bastion solves this by providing an MCP-compatible gateway that acts as a secure intermediary:**

```
Agent (MCP Client)
    │
    │  tools/call("sandbox_run", {command: "npm test"})
    ▼
Bastion Gateway ──▶ Sandbox Container (Podman/Firecracker/gVisor)
    │                      │
    │  {exit_code: 0,       │  npm test
    │   stdout: "42 passed"}│  runs in isolation
    ▼                      ▼
```

- **Isolation**: Every command runs in its own container or microVM
- **Resource control**: CPU, memory, and time limits per sandbox
- **Clean slate**: No state leaks between executions
- **MCP native**: Works with any MCP-compatible client (OpenCode, Claude Code, Goose, etc.)
- **Provider abstraction**: Swap backends without changing agent code

## 🏗 Architecture

```
┌──────────────┐                         ┌──────────────────────────────────────┐
│  MCP Client  │──tools/call──▶┌─────┐   │ Worker (gRPC CLIENT)                 │
│ (OpenCode,   │                │     │   │  ┌────────┐  ┌────────┐  ┌────────┐ │
│  Claude Code,│◀──responses───│     │◀──┼──│Sandbox1│  │Sandbox2│  │SandboxN│ │
│  Goose...)   │               │ G   │   │  │┌──────┐│  │┌──────┐│  │┌──────┐│ │
└──────────────┘               │ A   │   │  ││worker││  ││worker││  ││worker││ │
                               │ T   │   │  ││(bin) ││  ││(bin) ││  ││(bin) ││ │
                               │ E   │   │  └┴──────┴┘  └┴──────┴┘  └┴──────┴┘ │
                               │ W   │   │     ▲ PodmanProvider                  │
                               │ A   │   │     │ bind-mounts binary              │
                               │ Y   │   │     │ :50052 outbound                 │
                               │     │   └─────┼─────────────────────────────────┘
                               │ :50052       │
                               │ gRPC Registry│
                               │ + MCP srv   │
                               └─────┼───────┘
                                     │
                                     ▼
                          ┌─────────────────────┐
                          │ ProviderFactory     │
                          │ ┌─────────────────┐ │
                          │ │ PodmanProvider   │ │
                          │ ├─────────────────┤ │
                          │ │ FirecrackerProvider │
                          │ └─────────────────┘ │
                          └─────────────────────┘
```

### Worker Protocol v2 (JNLP-inspired)

Workers connect **outbound** to the Gateway — no port mapping, no inbound firewall rules. The life cycle:

1. **Register** — Worker sends `sandbox_id`, protocol version, capabilities, and a random nonce
2. **ChallengeResponse** — Gateway responds with a challenge nonce; Worker proves identity via HMAC-SHA256(secret, worker_nonce || gateway_nonce). Secret never transits the wire.
3. **CommandStream** — Bidirectional streaming: Gateway sends commands, Worker streams stdout/stderr/exit/health back

Reliability: exponential backoff reconnect (1s→60s + jitter), 10s heartbeat ping/pong, 30s watchdog dead-worker cleanup, and circuit breaker (3 failures → 30s open).

## ✨ Features

| Feature | Status | Description |
|---------|--------|-------------|
| **Worker Protocol v2** | ✅ Stable | gRPC-based JNLP protocol: Register→HMAC auth→CommandStream; outbound workers |
| **Podman Backend** | ✅ Stable | Container-based isolation via bollard Docker API |
| **Firecracker Backend** | ✅ Implemented | microVM isolation via Firecracker REST API over Unix socket |
| **Streaming Execution** | ✅ Stable | Real-time stdout/stderr streaming during commands |
| **Hot Pool Manager** | ✅ Stable | Pre-warm containers for       Podman socket path [default: /run/user/1000/podman/podman.sock]
  --image       Default container image [default: debian:bookworm-slim]
  --config       Configuration file path [default: config/sandbox-gateway.toml]

Pool Options:
  --pool-enabled               Enable sandbox pooling
  --pool-min-idle           Min idle containers per template [default: 2]
  --pool-max-idle           Max idle containers per template [default: 5]
  --pool-max-total          Max total containers [default: 50]
  --pool-idle-timeout-ms   Idle eviction timeout [default: 600000]
  --pool-refill-interval-ms  Pool refill interval [default: 5000]
```

## 🔧 MCP Tools

Bastion exposes 12 MCP tools for sandbox management:

### Lifecycle

| Tool | Parameters | Returns |
|------|------------|---------|
| `sandbox_create` | `template`, `timeout_ms` | `sandbox_id`, `status`, `from_pool` |
| `sandbox_terminate` | `sandbox_id` | `status` (`terminated` or `pooled`) |
| `sandbox_info` | `sandbox_id` | `sandbox_id`, `status`, `template`, `created_at`, `expires_at` |
| `sandbox_list` | — | `count`, `sandboxes[]` |

### Execution

| Tool | Parameters | Returns |
|------|------------|---------|
| `sandbox_run` | `sandbox_id`, `command` | `exit_code`, `stdout`, `stderr`, `duration_ms` |
| `sandbox_run_stream` | `sandbox_id`, `command` | `exit_code`, `stdout`, `stderr`, `chunks_received` |

### File Operations

| Tool | Parameters | Returns |
|------|------------|---------|
| `sandbox_write` | `sandbox_id`, `path`, `content` | `status` |
| `sandbox_read` | `sandbox_id`, `path` | `content`, `encoding` |
| `sandbox_list_files` | `sandbox_id`, `path` | `count`, `entries[]` |

### Observability

| Tool | Parameters | Returns |
|------|------------|---------|
| `sandbox_health` | — | `status`, `version`, `checks[]` |
| `sandbox_metrics` | — | Prometheus-formatted metrics |
| `sandbox_pool_stats` | — | `enabled`, `active`, `idle`, `templates[]` |

## 🧬 Architecture Deep Dive

### DDD Crate Structure

| Crate | Layer | Responsibility |
|-------|-------|---------------|
| `bastion-domain` | Domain | Entities, value objects, traits (`SandboxProvider`, `CommandRouter`, `SandboxRepository`) |
| `bastion-application` | Application | Use cases (orchestration between domain and infrastructure) |
| `bastion-infrastructure` | Infrastructure | Adapters (`PodmanProvider`, `FirecrackerProvider`, `InMemoryRepo`, `PoolManager`, `Metrics`) |
| `bastion-gateway` | Presentation | MCP server via `rmcp`, gRPC `RegistryService` on `:50052`, composition root, CLI |
| `bastion-worker` | Worker | gRPC CLIENT connecting outbound to Gateway; runs inside sandbox (JNLP pattern) |

### Data Flow

```
┌──────────────┐     ┌─────────────────────────┐     ┌──────────────────┐
│  MCP Client  │────▶│  BastionGateway          │────▶│   Use Cases      │
│ (OpenCode,   │     │  (rmcp server + gRPC)    │     │ (Application)    │
│  Claude Code)│◀────│  12 tool handlers        │◀────│                  │
└──────────────┘     │  RegistryService :50052  │     └────────┬─────────┘
                     └───┬──────────┬───────────┘              │
                         │          │                          ▼
                         │ gRPC     │              ┌──────────────────┐
                         ▼          ▼              │ SandboxRepository │
              ┌─────────────┐ ┌────────────────┐   │   (InMemory)      │
              │ Worker      │ │ ProviderFactory │   └──────────────────┘
              │ (gRPC CLIENT)│ │  (Podman,       │
              │ in sandbox   │ │   Firecracker)  │
              └─────────────┘ └────────────────┘
                   ▲ bind-mount worker binary
                   │
            PodmanProvider
```

## 🗺 Roadmap

| Version | Milestone | Content |
|---------|-----------|---------|
| **v0.1.0** ✅ | MVP | Podman backend, 12 tools, hot pool, streaming, metrics |
| **v0.2.0** | Multi-backend | Pool Manager, Firecracker backend |
| **v0.3.0** | Multi-backend | gVisor backend, provider selection |
| **v0.4.0** | Streaming | MCP progress notifications, cancellation |
| **v0.5.0** | Pipelines | DSL-based multi-sandbox pipelines |
| **v0.6.0** | Database | PostgreSQL + SQLite sandbox backends |
| **v0.9.0** | Kubernetes | K8s Pod-based ephemeral sandboxes |
| **v1.0.0** | Stable | All features, stable API, crates.io release |

See [CHANGELOG.md](CHANGELOG.md) for detailed release notes.

## 💻 Development

```bash
# Build
cargo build --release

# Run all tests
cargo test --workspace

# Run integration tests (requires Podman)
cargo test --test podman_lifecycle -- --test-threads=1

# Lint
cargo clippy --workspace -- -D warnings

# Format
cargo fmt --all -- --check

# Generate docs
cargo doc --no-deps --document-private-items --open
```

### Project Structure

```
Bastion/
├── crates/
│   ├── bastion-domain/         # Domain model + ports
│   │   └── src/
│   │       ├── sandbox/        # Sandbox aggregate
│   │       ├── execution/      # Command + streaming types
│   │       ├── provider/       # SandboxProvider trait
│   │       └── shared/         # DomainError, Id types
│   ├── bastion-application/    # Use cases
│   │   └── src/
│   │       ├── sandbox/        # Create, terminate, list, info
│   │       ├── execution/      # Run, run_stream
│   │       └── file_ops/       # Read, write, list_files
│   ├── bastion-infrastructure/ # Adapters
│   │   └── src/
│   │       ├── provider/       # PodmanProvider, ProviderFactory
│   │       ├── pool/           # SandboxPoolManager
│   │       ├── persistence/    # InMemorySandboxRepository
│   │       ├── metrics/        # GatewayMetrics
│   │       └── config/         # Config loader
│   ├── bastion-gateway/        # MCP server
│   │   └── src/
│   │       ├── main.rs         # Composition root + CLI
│   │       └── server.rs       # 12 MCP tool handlers
│   └── bastion-worker/         # gRPC worker (outbound JNLP client)
│       └── src/
│           └── main.rs         # Connect→Register→ChallengeResponse→CommandStream
├── docs/assets/                # Documentation images
├── config/                     # Example configs
├── proto/                      # Protobuf definitions
└── proyectos/                  # Planning docs (Spanish)
```

## 🤝 Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on:

- Architecture and design principles
- Code style and conventions
- Commit message format
- Pull request checklist

## 📄 License

Apache-2.0 — see [LICENSE](LICENSE) for details.

---

**Built with Rust** 🦀 **·** **DDD** 🧬 **·** **MCP** 🔌

[🇪🇸 Leer en español](README.es.md)

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Rubentxu](https://github.com/Rubentxu)
- **Source:** [Rubentxu/Bastion](https://github.com/Rubentxu/Bastion)
- **License:** Apache-2.0

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-rubentxu-bastion
- Seller: https://agentstack.voostack.com/s/rubentxu
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
