onit-sandbox
A Docker-based code execution sandbox MCP server for safe Python execution. Gives LLM agents an isolated environment where they can install packages, run code, and produce artifacts — without touching the host system.
Why onit-sandbox?
Traditional bash-based MCP tools block package managers and restrict operations. onit-sandbox lifts those restrictions safely by running everything inside per-session Docker containers with resource limits and network isolation.
- Install any package —
pip install numpy matplotlib torchjust works - Run full projects — execute scripts, run tests, build simulations
- Stay secure — containers are resource-limited, network-isolated, and non-root
Architecture
┌──────────────────────────────────────┐
│ LLM Agent (chat loop) │
│ ┌────────────────────────────────┐ │
│ │ SandboxMCPServer │ │
│ │ install_packages │ │
│ │ run_code │ │
│ │ sandbox_status │ │
│ └──────────┬─────────────────────┘ │
│ │ Docker CLI │
│ ┌──────────▼─────────────────────┐ │
│ │ Docker Container (per-session) │ │
│ │ - python:3.12-slim base │ │
│ │ - Full pip access │ │
│ │ - Workspace bind-mounted │ │
│ │ - CPU/mem/network limits │ │
│ │ - Auto-cleanup on stop │ │
│ └────────────────────────────────┘ │
└──────────────────────────────────────┘
Installation
From PyPI
pip install onit-sandbox
From source
git clone https://github.com/sibyl-oracles/onit-sandbox.git
cd onit-sandbox
pip install -e .
Prerequisites
- Python 3.10+
- Docker — install from docker.com
Docker Image
The sandbox runs code inside a custom Docker image pre-loaded with common scientific packages.
Pull from GitHub Container Registry
docker pull ghcr.io/sibyl-oracles/onit-sandbox:latest
Then set the image name so the server uses it:
export SANDBOX_IMAGE=ghcr.io/sibyl-oracles/onit-sandbox:latest
Build locally
cd docker
chmod +x build.sh
./build.sh
This builds onit-sandbox:latest locally. The image includes:
| Package | Description |
|---|---|
| numpy | Numerical computing |
| matplotlib | Plotting and visualization |
| scipy | Scientific computing |
| pandas | Data manipulation |
| scikit-learn | Machine learning |
| sympy | Symbolic mathematics |
| pytest | Testing framework |
Fallback
If no custom image is found, the server falls back to python:3.12-slim automatically. Packages can still be installed at runtime via install_packages.
Quick Start
# Start the MCP server (background)
onit-sandbox start
# Start in foreground (useful for debugging)
onit-sandbox start --foreground
# Check status
onit-sandbox status
# Stop the server
onit-sandbox stop
The server runs on http://0.0.0.0:18205/sse by default.
MCP Tools
install_packages
Install Python packages inside the sandbox via pip. Network is temporarily enabled for PyPI access, then disabled again.
{
"packages": "numpy matplotlib scipy",
"session_id": "my-session"
}
run_code
Execute shell commands inside the sandbox. Files written by write_file are available in the working directory. Output is captured and returned (truncated to 10 KB).
{
"command": "python simulation.py",
"timeout": 120,
"session_id": "my-session"
}
sandbox_status
Check sandbox state — container health, Python version, installed packages, disk usage, uptime, and GPU availability.
{
"session_id": "my-session"
}
Configuration
CLI Options
onit-sandbox start [OPTIONS]
--host Host to bind to (default: 0.0.0.0)
--port Port to bind to (default: 18205)
--transport sse or stdio (default: sse)
--foreground Run in foreground
--verbose Enable verbose logging
--data-path Workspace data directory (default: /tmp/onit/data)
Environment Variables
| Variable | Default | Description |
|---|---|---|
SANDBOX_IMAGE |
onit-sandbox:latest |
Docker image to use |
FALLBACK_IMAGE |
python:3.12-slim |
Fallback if sandbox image unavailable |
SANDBOX_MEMORY_LIMIT |
512m |
Container memory limit |
SANDBOX_CPU_QUOTA |
100000 |
CPU quota (100000 = 1 CPU) |
SANDBOX_PIDS_LIMIT |
100 |
Max processes in container |
SANDBOX_DEFAULT_TIMEOUT |
60 |
Default command timeout (seconds) |
SANDBOX_INSTALL_TIMEOUT |
300 |
Package install timeout (seconds) |
YAML Configuration
# configs/default.yaml
server:
name: SandboxMCPServer
host: 0.0.0.0
port: 18205
transport: sse
docker:
sandbox_image: onit-sandbox:latest
memory_limit: 512m
cpu_quota: 100000
pids_limit: 100
network_disabled_default: true
Integration with OnIt
Add to your OnIt configs/default.yaml:
mcp_servers:
- name: SandboxMCPServer
description: Python code execution sandbox with package installation
url: http://127.0.0.1:18205/sse
enabled: true
Programmatic Usage
from onit_sandbox.mcp_server import run, cleanup_sandbox
# Start the server
run(transport="sse", host="0.0.0.0", port=18205)
# Cleanup a session's container
cleanup_sandbox(session_id="my-session")
Security
Isolation Features
| Layer | Protection |
|---|---|
| Filesystem | Container isolation — only mounted workspace is accessible |
| User | Non-root execution as sandbox (UID 1000) |
| Resources | Memory (512 MB), CPU (1 core), PIDs (100) |
| Network | Disabled by default — enabled only during install_packages |
| Lifecycle | Containers auto-removed on stop (--rm flag) |
| GPU | Optional NVIDIA GPU passthrough when available |
What's Blocked
- Direct host filesystem access (only mounted workspace)
- Root access inside container
- Network access during code execution
- Unlimited resource consumption
What's Allowed
- Full PyPI access during
install_packages - Read/write to mounted workspace
- Python execution with any installed packages
- Shell commands within resource limits
Development
Setup
# Clone and install with dev dependencies
git clone https://github.com/sibyl-oracles/onit-sandbox.git
cd onit-sandbox
pip install -e ".[dev]"
# Or use the setup script (creates venv, builds Docker image)
chmod +x setup.sh
./setup.sh
Running Tests
# All tests
pytest tests/ -v
# Skip Docker-dependent tests
pytest tests/ -v -k "not Docker"
Code Quality
black src/ tests/ # Format
ruff check src/ tests/ # Lint
mypy src/ # Type check
Publishing a Release
- Update the version in pyproject.toml
- Create a GitHub release with a tag matching the version (e.g.,
v0.1.0) - The publish workflow automatically builds and uploads to PyPI
- The docker workflow automatically builds and pushes the container image to GHCR
Troubleshooting
| Problem | Solution |
|---|---|
| Docker not available | Install Docker and start the daemon (sudo systemctl start docker on Linux, or open Docker Desktop on macOS) |
| Sandbox image not found | Build locally with cd docker && ./build.sh or pull from GHCR |
| Permission denied on workspace | chmod -R 777 /path/to/workspace |
| Command timeout | Increase timeout: run_code(command="...", timeout=300) |
| Port already in use | Use --port flag: onit-sandbox start --port 18206 |
License
Apache License 2.0 — see LICENSE for details.
Metadata
Release files for onit-sandbox 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| onit_sandbox-0.1.0.tar.gz | 23.3 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| onit_sandbox-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 42.6 kB
Release files / onit_sandbox-0.1.0.tar.gz
| Download URL | onit_sandbox-0.1.0.tar.gz |
|---|---|
| Size | 23.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
30dcc2a8de2e4b1253121ce2fa64166be39dc0f976d8cfc1feb7f2509569b96e
|
|
BLAKE2b-256 checksum How to use checksums |
9a2ebb3ebbcfdc968793808024e3699acb400b9eb1258a47a478d5d3b5674787
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 14, 2026.
Transparency logRelease files / onit_sandbox-0.1.0-py3-none-any.whl
| Download URL | onit_sandbox-0.1.0-py3-none-any.whl |
|---|---|
| Size | 19.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
24fd1c5bc555d9dc0d3bb7736775ae59f3ef5c0a54d40a2688e56228faf7a99a
|
|
BLAKE2b-256 checksum How to use checksums |
6b99686dadaa854ebcd61933b676494d3778a6ffbbf0541e0763c203c458738d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 14, 2026.
Transparency logSecurity for onit-sandbox 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for onit_sandbox-0.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Mar 14, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.