ButterBox is a personal VM for agents, exposed over MCP and built with github.com/modelcontextprotocol/go-sdk. It ships as an Ubuntu-based container image with common toolchains and CLI tools pre-installed — an always-on machine your agent can drive, isolated from where the agent itself runs, with a home directory that persists across sessions.
It exposes a streamable HTTP endpoint and provides 3 tools by default:
ReadFileWriteFileExecCommand
It also provides an MCP prompt:
exec_task— instructions for completing a task on the VM; optionaltaskargument appends the concrete task to carry out
It is designed to run well inside Docker, with environment variables for the listen address, workspace root, and bearer token authentication.
The container image is based on ubuntu:24.04, runs as the non-root user butterbox (with passwordless sudo, so sudo apt-get install works), and ships with:
- Node.js 22 (NodeSource) + npm, global installs go to
~/.npm-global - Python 3.12 + pip + venv (
PIP_BREAK_SYSTEM_PACKAGES=1, sopip installworks out of the box) - Go 1.26 toolchain (
GOPATH=~/go,~/go/binonPATH) - Common CLI tools:
git,curl,wget,jq,ripgrep,unzip,zip,build-essential,openssh-client,vim,kubectl - Cloud tools:
aws(AWS CLI v2),gcloud(Google Cloud CLI),rclone,logcli(Grafana Loki) - Dev platform CLIs:
gh(GitHub),glab(GitLab),gog,td(Todoist) gws— Google Workspace CLI (Drive, Gmail, Calendar, Sheets, and more)
go run .Default endpoints:
- MCP endpoint:
http://127.0.0.1:8080/mcp - health:
http://127.0.0.1:8080/healthz
Example:
MCP_ADDR=:8080 \
SANDBOX_ROOT=/workspace \
MCP_AUTH_TOKEN=secret-token \
go run .docker build -t butter-box .
docker run --rm -p 8080:8080 \
-e MCP_AUTH_TOKEN=secret-token \
-e SANDBOX_ROOT=/workspace \
-v "$PWD:/workspace" \
butter-boxExample compose.yaml:
services:
butter-box:
image: ghcr.io/orvice/butter-box:main
ports:
- "8080:8080"
environment:
MCP_ADDR: ":8080"
MCP_HTTP_PATH: "/mcp"
MCP_AUTH_TOKEN: "secret-token"
SANDBOX_ROOT: "/workspace"
SANDBOX_SHELL: "/bin/bash"
volumes:
- /tmp/sandbox-workspace:/workspace
# Persist the butterbox user's home dir: CLI auth state (e.g. gws
# OAuth tokens), npm/pip/go user installs, shell history, etc.
- butterbox-home:/home/butterbox
restart: unless-stopped
volumes:
butterbox-home:Start it with:
docker compose up -dMCP_ADDR: HTTP listen address, default:8080MCP_HTTP_PATH: MCP HTTP path, default/mcpMCP_AUTH_TOKEN: when set, requiresAuthorization: Bearer <token>SANDBOX_ROOT: workspace root for file access and command execution, default current directorySANDBOX_SHELL: shell used by theExecCommandtool, defaultbashMCP_STATELESS: enable stateless streamable HTTP mode, defaultfalseMCP_JSON_RESPONSE: preferapplication/jsonresponses, defaultfalse
Example client configuration for a streamable HTTP MCP server with bearer auth:
{
"mcpServers": {
"butter-box": {
"type": "http",
"url": "http://127.0.0.1:8080/mcp",
"headers": {
"Authorization": "Bearer secret-token"
}
}
}
}If your MCP client uses a different schema, keep the same core values:
- endpoint:
http://127.0.0.1:8080/mcp - auth header:
Authorization: Bearer <token>
Request payload:
{
"path": "relative/or/absolute/path"
}Request payload:
{
"path": "tmp/hello.txt",
"content": "hello world",
"createDirs": true
}Request payload:
{
"command": "pwd && ls -la",
"cwd": ".",
"timeoutSeconds": 30,
"env": {
"FOO": "bar"
}
}The result includes:
cwdexitCodestdoutstderr
- All file paths are constrained to
SANDBOX_ROOTto prevent path escape. - The
ExecCommandtool working directory is also constrained toSANDBOX_ROOT. - Command output is truncated to avoid returning excessively large responses.