Skip to main content
Glama
jaydeepgami56

Sandbox Compute Broker

README.md
# Sandbox Compute Broker

> **Sandbox Compute Broker lets an AI agent run compute tasks in a secure sandbox and see the
> results as an interactive UI — brokering every exchange so the interface and the
> execution environment stay safely isolated from each other.**

The broker is free and open source (Apache-2.0). Your costs are **hardware and ops**, not
API bills — there are no cloud accounts or API keys in the default path.

---

## What it does

When an agent needs to *do* something computational (analyse a CSV, generate a report, run
a script), it calls one of the broker's tools. The broker:

1. **Runs the request in a sandbox** — an isolated environment for untrusted code.
2. **Reuses the session** — follow-up calls hit the *same* sandbox so loaded datasets stay loaded.
3. **Handles files** — `/workspace` is private scratch; `/outputs` is surfaced only when
   the agent explicitly calls `present_output`.
4. **Renders a UI when it helps** — via MCP Apps, so results appear as an interactive
   dashboard instead of a wall of text. UI is *optional*.

```
agent → host → broker (OURS) → sandbox
                  ↑ owns both sandbox connection + ui:// resource
```

---

## Prerequisites

| Provider | What you need | Isolation |
|---|---|---|
| **microsandbox** *(default)* | KVM on Linux · Apple Silicon on macOS · WHP on Windows | microVM (libkrun) |
| **Docker** *(fallback)* | Docker Engine running; `docker build -t mcp-sandbox:latest sandbox-image/` | OCI container (+gVisor if `runsc` installed) |
| **Local** | Nothing | subprocess — **test scaffolding only, not a security boundary** |

The broker auto-selects: tries microsandbox first, falls back to Docker, bails with an
actionable error if neither is available. Override with `BROKER_PROVIDER=microsandbox|docker|local`.

---

## Quickstart (under 15 minutes)

```bash
# 1. Clone + install
git clone https://github.com/your-org/sandbox-compute-broker
cd sandbox-compute-broker
npm install

# 2a. If using microsandbox (default — needs virtualization support):
#     No extra steps; the SDK spawns microVMs as child processes.

# 2b. If using Docker (fallback):
docker build -t mcp-sandbox:latest sandbox-image/

# 3. Verify everything works
npx tsc -p tsconfig.json --noEmit        # type-check
npx vitest run                           # unit tests (59 pass, no daemon needed)

# 4. Run the dashboard server
BROKER_PROVIDER=local npm run dev        # local subprocess, for rapid iteration
# or:
npm run dashboard                        # auto-selects best available provider
```

**Add to Claude Desktop** (`%APPDATA%\Claude\claude_desktop_config.json` on Windows,
`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "sandbox-compute-broker": {
      "command": "npx",
      "args": ["tsx", "examples/dashboard/server.ts"]
    }
  }
}
```

Then restart Claude Desktop and ask it to call the `data_dashboard` tool.

---

## Tools exposed

| Tool | UI? | What it does |
|---|---|---|
| `run_code` | No | Run code in the session sandbox; return stdout/stderr/exitCode. |
| `run_command` | No | Run an arbitrary command in the session sandbox. |
| `present_output` | No | Promote a `/workspace` file to `/outputs`; return `resource://` URI. |
| `data_dashboard` | **Yes** | Run an analysis step + render an interactive App. Callbacks reuse the same sandbox. |

Output resources are read via `resources/read` — bytes never base64-inlined into a tool result.

---

## Provider swap

```bash
BROKER_PROVIDER=docker npx tsx examples/dashboard/server.ts
BROKER_PROVIDER=microsandbox npx tsx examples/dashboard/server.ts
```

Zero App or tool changes required — the `SandboxProvider` interface is the portability
contract (see `SPEC.md`).

---

## Project layout

```
src/
  providers/
    base.ts          SandboxProvider interface + types (SPEC §1)
    local.ts         LocalSandboxProvider — subprocess, test scaffolding only
    microsandbox.ts  MicrosandboxProvider — microVM via libkrun (primary)
    docker.ts        DockerSandboxProvider — OCI container + gVisor (fallback)
    index.ts         selectProvider() + forceFromEnv()
  session.ts         SessionManager — reuse, TTL, idle reap, caps, reconnect
  store.ts           SessionStore interface — InMemorySessionStore + Redis stub
  files.ts           FileLifecycle — workspace/outputs, resource:// refs
  policy.ts          Policy — allow-list, egress, secrets, audit log
  broker.ts          MCP server — tool + ui:// registration
ui/analytics-dashboard/
  app.ts             In-iframe App (calls data_dashboard back)
  shell.html         HTML shell
  build.ts           esbuild bundler (produces single inline <script>)
sandbox-image/
  Dockerfile         Pinned OCI image (python + analysis libs)
examples/
  phase0-spike/      Session-identity spike (see SPEC.md §3)
  dashboard/         Phase 2 flagship: data dashboard over stdio
tests/
  *.test.ts          59 tests — providers, session, files, policy, broker, limits
SPEC.md              Frozen v0 provider interface + file-lifecycle contract
PLAN.md              Design doc (v5)
STATUS.md            Phase-by-phase implementation status
```

---

## Architecture

The four layers (PLAN.md §7):

```
[1] MCP App (iframe)           ← @modelcontextprotocol/ext-apps    (optional)
        ↕ postMessage / JSON-RPC
    Host (Claude Desktop, …)
        ↕ MCP transport (stdio / streamable HTTP)
[2] MCP Broker                 ← src/broker.ts                      (OURS)
[3] Core                       ← session · files · policy           (OURS)
        ↕ provider SDK
[4] Sandbox                    ← microsandbox microVM / Docker OCI
```

The App can **never** reach the sandbox directly (iframe isolation). Every byte flows
through the broker.

---

## Security model

- **Isolation level** is declared by `capabilities().isolationLevel` so the deployer always
  knows what boundary they have (`subprocess | container | container+gvisor | microvm`).
- **`/workspace`** is never auto-exposed. The only path to the user is `present_output`.
- **Egress** is blocked by default (`disableNetwork()` / `--network=none`). The Policy layer
  manages an allow-list.
- **Secrets** are injected at call time; never baked into images, code, or logs. The Policy
  layer redacts any configured secret values from stdout/stderr before they reach the audit
  log or the host.
- **Audit log**: one JSON line per execution (`{ts, tool, provider, isolationLevel, sandboxId,
  exitCode, durationMs, bytesOut, policyDecisions[]}`), OWASP agentic-risk mapped.

See `docs/threat-model.md` for the full per-edge-case analysis.

---

## Overlap with microsandbox-mcp

[microsandbox-mcp](https://github.com/microsandbox/microsandbox) is microsandbox's own
compute-only MCP server. **Ours is different:**

- MCP Apps UI loop (interactive dashboards with App-iframe callbacks).
- Provider portability: swap microsandbox ↔ Docker with one env var; the `SPEC.md`
  interface lets you write third-party adapters.
- `FileLifecycle` (explicit output promotion, `resource://` refs, no base64 in tool results).
- Governance: per-tool allow-list, egress control, secret redaction, OWASP-mapped audit log.

---

## License

Apache-2.0. AGPL adapters (Daytona) are isolated in separate packages.
# SandboxCompute