A Docker-based code execution sandbox MCP server for safe Python execution
Project description
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.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file onit_sandbox-0.1.0.tar.gz.
File metadata
- Download URL: onit_sandbox-0.1.0.tar.gz
- Upload date:
- Size: 23.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
30dcc2a8de2e4b1253121ce2fa64166be39dc0f976d8cfc1feb7f2509569b96e
|
|
| MD5 |
de9757f6b1ceb2ddedb46f50ddd3af2d
|
|
| BLAKE2b-256 |
9a2ebb3ebbcfdc968793808024e3699acb400b9eb1258a47a478d5d3b5674787
|
Provenance
The following attestation bundles were made for onit_sandbox-0.1.0.tar.gz:
Publisher:
publish.yml on sibyl-oracles/onit-sandbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onit_sandbox-0.1.0.tar.gz -
Subject digest:
30dcc2a8de2e4b1253121ce2fa64166be39dc0f976d8cfc1feb7f2509569b96e - Sigstore transparency entry: 1102133293
- Sigstore integration time:
-
Permalink:
sibyl-oracles/onit-sandbox@8ad7c8973520c90947b7ac44518ecbee008a2739 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sibyl-oracles
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8ad7c8973520c90947b7ac44518ecbee008a2739 -
Trigger Event:
release
-
Statement type:
File details
Details for the file onit_sandbox-0.1.0-py3-none-any.whl.
File metadata
- Download URL: onit_sandbox-0.1.0-py3-none-any.whl
- Upload date:
- Size: 19.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24fd1c5bc555d9dc0d3bb7736775ae59f3ef5c0a54d40a2688e56228faf7a99a
|
|
| MD5 |
985169d61ea76ecd074c8a641bc7a10d
|
|
| BLAKE2b-256 |
6b99686dadaa854ebcd61933b676494d3778a6ffbbf0541e0763c203c458738d
|
Provenance
The following attestation bundles were made for onit_sandbox-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on sibyl-oracles/onit-sandbox
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onit_sandbox-0.1.0-py3-none-any.whl -
Subject digest:
24fd1c5bc555d9dc0d3bb7736775ae59f3ef5c0a54d40a2688e56228faf7a99a - Sigstore transparency entry: 1102133297
- Sigstore integration time:
-
Permalink:
sibyl-oracles/onit-sandbox@8ad7c8973520c90947b7ac44518ecbee008a2739 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/sibyl-oracles
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8ad7c8973520c90947b7ac44518ecbee008a2739 -
Trigger Event:
release
-
Statement type: