# Agent setup

Runbay **is** an MCP server. There's no sidecar to install and no config file to write by
hand — the app itself speaks the Model Context Protocol, and every running container automatically
becomes a set of tools your coding agent can call.

This guide covers one-click registration, exactly what your agent sees, and a 60-second sandbox demo.

## Register the MCP server (one click)

1. Open **Settings ▸ MCP Server** and enable the server.
2. Pick your client: **Claude Code**, **Claude Desktop**, or **Cursor**.
3. Click **Register**.

That writes a single `runbay` entry into the client's config and touches nothing else:

| Client         | Config file                                                                 |
|----------------|-----------------------------------------------------------------------------|
| Claude Code    | `~/.claude.json`                                                            |
| Claude Desktop | `~/Library/Application Support/Claude/claude_desktop_config.json`           |
| Cursor         | `~/.cursor/mcp.json`                                                        |

The edit is a byte-level JSON splice that preserves every unrelated key. A malformed config is
**refused, never clobbered** — if the file won't parse, the app tells you instead of overwriting it.

The server listens locally only: a Unix socket at `/tmp/runbay-mcp.sock`, or localhost TCP
on port `8765`. There is no TLS yet, so keep it to your machine. All three MCP servers are
rate-limited (100 requests/minute, 1000/hour per client) and validate every input at the boundary.

## What your agent sees, automatically

### Tools, per running container

For **every** running container:

- `logs__<name>` — tail recent logs
- `stats__<name>` — a live CPU / RAM / network snapshot
- `exec__<name>` — run a command from a **read-only allow-list** (injection vectors rejected)

For **database** containers (postgres, mysql, mariadb, mongodb), additionally:

- `db_query__<name>` — run a **validated, read-only** query (mutating statements are rejected)

Names are sanitized to the MCP charset — a container named `my.db` exposes `db_query__my_db`. Start
or stop a container and the tool list updates itself via `notifications/tools/list_changed`, so the
agent always sees the current reality.

### Resources

- `container://<name>/logs` — the last N log lines (text/plain)
- `container://<name>/stats` — the current stats snapshot (application/json)
- `container://events/recent` — a ring buffer of recent lifecycle events (application/json)

Started / stopped / appeared / removed events are synthesized from the same snapshot diff that drives
the tool list and pushed as MCP notifications, with `resources/list_changed` when the set changes.

### Sandbox tools

Seven permission-gated tools manage disposable agent VMs:

`sandbox_list` · `sandbox_create` · `sandbox_run` · `sandbox_stop` · `sandbox_start` ·
`sandbox_reset` · `sandbox_delete`

Write and destructive operations surface a permission prompt in the app before they run.

## Try a sandbox in 60 seconds

This is the money demo: let a coding agent work in a VM that can't touch your machine.

```text
You (in Claude Code):  Spin up a fresh sandbox with the claude-code preset and tell me when it's ready.

Agent → sandbox_create { "profile": "claude-code" }
        (Runbay shows a permission prompt → you approve)
        (installs Node + @anthropic-ai/claude-code inside a new container machine VM)
Agent:  Sandbox "sbx-quiet-harbor" is up, isolated (--home-mount none).
        Your $HOME, SSH keys, and cloud tokens are invisible to it.

You:    Clone my repo into it and run the tests.

Agent → sandbox_run { "name": "sbx-quiet-harbor", "command": "git clone … && npm test" }
Agent:  42 passing, 1 failing. The failure is in auth.test.js — want me to open it?

You:    Nope, throw the sandbox away.

Agent → sandbox_delete { "name": "sbx-quiet-harbor" }
Agent:  Gone. Nothing was written to your host.
```

Prefer the UI? **Sandboxes ▸ New** does the same thing with an isolation picker, live
setup-progress streaming, an in-app terminal into the VM, and repo copy-in via `container cp`.

### Sandbox presets

| Preset        | Installs                                             |
|---------------|------------------------------------------------------|
| `blank`       | Nothing — a clean base VM                            |
| `node`        | Node.js toolchain                                    |
| `python`      | Python toolchain                                     |
| `swift`       | Swift toolchain                                      |
| `claude-code` | Node + `@anthropic-ai/claude-code`                   |

Isolation defaults to **Isolated (`--home-mount none`)**. The `ro` and `rw` options expose your home
directory and say so in red — read the honest model in the [sandboxes doc](sandboxes.md).

## Guardrails

- **Permission UI** for every write or destructive operation.
- **Input validation** at every MCP boundary (container names, exec commands, queries).
- **Rate limiting** on all three servers (100/min, 1000/hr per client).
- **Read-only by policy** for `exec__` (allow-list) and `db_query__` (mutations rejected).

For the strategic "why," see the [FAQ](faq.md). To go deeper on the container platform itself, start
with [getting started](getting-started.md).
