Kilntainers by Kiln AI Logo

Give Every Agent an Ephemeral Linux Sandbox β€” via MCP

Build and Test Test Count Badge PyPi Discord Newsletter

Kilntainers is an MCP server that gives LLM agents isolated Linux sandboxes for executing shell commands. - 🧰 **Multiple backends:** Containers (Docker, Podman), cloud-hosted micro-VMs ([Modal](https://modal.com), [E2B](https://e2b.dev)), and WebAssembly sandboxes (WASM BusyBox, or any WASM module). - 🏝️ **Isolated per agent:** Every agent gets its own dedicated sandbox β€” no shared state, no cross-contamination. - 🧹 **Ephemeral:** Sandboxes live for the duration of the MCP session, then are shut down and cleaned up automatically. - πŸ”’ **Secure by design:** The agent communicates *with* the sandbox over MCP β€” it doesn’t run *inside* it. No agent API keys, code, or prompts are exposed to the sandbox. - πŸ”Œ **Simple MCP interface:** A single MCP tool, `sandbox_exec`, lets your agent run any Linux command. - πŸ“ˆ **Scalable:** Scale from a few agents on your laptop to thousands running in parallel in the cloud. ## Why Kilntainers? Agents are already excellent at using terminals, and can save thousands of tokens by leveraging common Linux utilities like `grep`, `find`, `jq`, `awk`, etc. However giving an agent access to the host OS is a security nightmare, and running thousands of parallel agents on a service is painful. Kilntainers gives every agent its own isolated, ephemeral sandbox. ## Quick Start Install and run from CLI: ```bash # install uv tool install kilntainers # starts with defaults: stdio MCP server, Docker, and Debian-slim (see options below) kilntainers ``` Add to your MCP client (Claude, Cursor, etc.): ```json { "mcpServers": { "kilntainers": { "command": "kilntainers" } } } ``` ## How It Works ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” MCP β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ LLM Agent │◄───────►│ Kilntainers │◄────►│ Sandboxes β”‚ β”‚ (client) β”‚ β”‚ MCP Server β”‚ β”‚ - Docker/Podman β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ - Cloud VM (Modal,E2B) β”‚ β”‚ β”‚ β”‚ β”‚ β”‚ - WASM Sandbox β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` 1. An MCP client connects to Kilntainers 2. On the first `sandbox_exec` call, Kilntainers creates an isolated sandbox. Each connection gets its own independent sandbox. 3. Commands run inside the sandbox; stdout, stderr, and exit code are returned 4. When the session ends, the sandbox is destroyed and resources are cleaned up. **Security:** The agent communicates *with* the sandbox over MCP β€” it doesn't run *inside* it. This is intentional: agents often need secrets (API keys, system prompts, code), and those should never be exposed inside a sandbox where a prompt injection could exfiltrate them. **Agent Isolation & Sandbox Lifecycle:** Each MCP connection starts its own isolated sandbox. In streaming HTTP mode, a single MCP server can host many sandboxes in parallel, and `exec` calls are routed to the sandbox associated with that connection. In stdio mode, the server runs a single sandbox per process. When a connection closes, its sandbox is shut down and deleted. ## Backend Examples See the [CLI Reference](#cli-reference) for all arguments. ### Docker and Podman (default) Local containers via Docker or Podman. Any OCI image works. ```bash kilntainers # Docker + debian-slim (defaults) kilntainers --image alpine --engine podman # Podman + Alpine kilntainers --image node:22 --network # Node.js with networking ``` ### Cloud Containers & VMs #### Modal.com Hosted containers with sub-second startup via [Modal.com](https://modal.com). Scales to thousands of parallel sandboxes. Supports GPUs. ```bash kilntainers --backend modal kilntainers --backend modal --gpu A10G --region us-east # GPU-accelerated ``` Authenticate via `modal setup` CLI or `--modal-token-id` / `--modal-token-secret` flags. #### E2B Cloud hosted micro-VM sandboxes from [E2B](https://e2b.dev). ```bash kilntainers --backend e2b # Default Debian image kilntainers --backend e2b --e2b-api-key ABCD --e2b-template my-custom-alpine # Custom image ``` Authenticate with `--e2b-api-key` CLI arg, or `E2B_API_KEY` environment variable. ### WASM Go BusyBox (Experimental) Runs [go-busybox](https://github.com/rcarmo/go-busybox) in a WebAssembly sandbox. Not a full Linux environment, but provides common utilities (`grep`, `awk`, `sed`, `ls`, `wc`, `sort`, etc.) in a very lightweight and secure sandbox. ```bash uv tool install kilntainers[wasm] # WASM support is an optional dependency (+15MB) kilntainers --backend go_busybox ``` ### WASM Runner Run a custom WASM module as the sandbox backend. Provides agents a set tools compiled to WebAssembly, and an isolated filesystem. ```bash uv tool install kilntainers[wasm] # WASM support is an optional dependency (+15MB) kilntainers --backend wasm --wasm-path ./my_tool.wasm ``` ## Installation ```bash uv tool install kilntainers # recommended uv tool install kilntainers[wasm] # optional, include WASM backends (+15MB) pip install kilntainers # also works with pip ``` Requires Python 3.13+. Docker backend requires Docker or Podman. The Modal and E2B backends require accounts to those services. ## CLI Reference ``` usage: kilntainers [-h] [--backend {docker,go_busybox,modal,wasm}] [--transport {stdio,http}] [...] MCP server providing isolated Linux sandboxes for LLM agent shell execution. options: -h, --help show this help message and exit core options: --backend {docker,e2b,go_busybox,modal,wasm} Backend to use (default: docker). Available: docker, e2b, go_busybox, modal, wasm --transport {stdio,http} MCP transport (default: stdio) --host HOST HTTP bind address (default: 127.0.0.1, HTTP mode only) --port PORT HTTP listen port (default: 8435, HTTP mode only) --timeout TIMEOUT Default exec timeout in seconds (default: 120) --output-limit OUTPUT_LIMIT Max combined stdout+stderr bytes per exec (default: 2097152 = 2 MiB) --session-timeout SESSION_TIMEOUT Idle session timeout in seconds (default: 300, HTTP mode only) --shell SHELL Shell binary for command mode (e.g., /bin/bash, ash). Default: /bin/bash. --network Enable network access in sandboxes (default: disabled) tool description: --tool-instruction-override TOOL_INSTRUCTION_OVERRIDE Replace the entire sandbox_exec tool description --extended-tool-instruction EXTENDED_TOOL_INSTRUCTION Append to the backend's default tool description docker backend options: --engine ENGINE Container CLI binary (default: docker). Supports podman. --docker-host DOCKER_HOST Docker daemon socket/address, passed as -H to the Docker CLI (e.g., "ssh://user@remote-host", "tcp://host:2375") --image IMAGE Docker image (default: debian:bookworm-slim) --cpu CPU Docker CPU limit (e.g., "1.5") --memory MEMORY Docker memory limit (e.g., "512m") --docker-run-flag DOCKER_RUN_FLAGS Additional flag passed to docker run. Repeatable. (e.g., --docker-run-flag "--pids-limit=256") e2b backend options: --e2b-api-key E2B_API_KEY E2B API key (overrides E2B_API_KEY environment variable) --e2b-template E2B_TEMPLATE E2B template name or ID (default: base) --e2b-sandbox-timeout E2B_SANDBOX_TIMEOUT Sandbox lifetime timeout in seconds (default: 3600) --e2b-metadata E2B_METADATA Metadata key=value pairs (can be used multiple times) --e2b-env E2B_ENV Environment variable key=value pairs (can be used multiple times) modal backend options: --modal-token-id MODAL_TOKEN_ID Modal token ID (overrides environment/default auth) --modal-token-secret MODAL_TOKEN_SECRET Modal token secret (overrides environment/default auth) --modal-app-name MODAL_APP_NAME Modal app name (default: kilntainers) --modal-cpu MODAL_CPU CPU cores (fractional, default: 1.0) --modal-memory MODAL_MEMORY Memory in MiB (default: 512) --gpu GPU GPU type (e.g., "A10G", "H100") --region REGION Geographic region (e.g., "us-east") --sandbox-timeout SANDBOX_TIMEOUT Sandbox lifetime timeout in seconds (default: 3600, max 86400) wasm backend options: --wasm-path WASM_PATH Path to the .wasm file to execute (required for wasm backend) --wasm-max-memory WASM_MAX_MEMORY Max WASM memory in MiB (default: 256) --wasm-fuel WASM_FUEL WASM instruction fuel limit (default: unlimited) ```