mcp-sandbox
Execute Julia scripts in an isolated sandbox container
Execute LaTeX (pdflatex) documents in an isolated sandbox container
Execute GNU Octave scripts in an isolated sandbox container
Execute Python scripts with scientific libraries (numpy, matplotlib, scipy, pandas, sympy, scikit-learn) in an isolated sandbox container
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-sandboxPlot a sine wave using Python and matplotlib"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-sandbox
MCP server for isolated scientific script execution. Run R, Python, GMT, GRASS GIS, LaTeX, Octave, Julia, and more in disposable containers — fully stateless, no host filesystem access.
Tools
Tool | Description |
| Execute a script in an isolated sandbox container |
| List available scientific runtimes |
Related MCP server: HOPX MCP Server
Supported Runtimes
Runtime | Tools |
| R + ggplot2, dplyr, tidyr, jsonlite |
| Python 3 + numpy, scipy, pandas, matplotlib, sympy, scikit-learn, geopandas, pyproj, rasterio, obspy |
| Generic Mapping Tools |
| GRASS GIS — headless; each run gets a throwaway location |
| pdflatex (texlive) |
| GNU Octave |
| Julia |
| Gnuplot |
| Bash scripts |
Design
Each run spawns a fresh container — fully stateless, no reuse
Container deleted after execution (
--rm)Network access enabled
Memory limit: 2GB, CPU limit: 2 cores
Input files injected at
/sandbox/input/(base64)Output files collected from
/sandbox/output/, returned by reference: a capability URL plus metadata (name, bytes, SHA-256, MIME, expiry). Small text outputs (< 4 KB) are still inlined. See "Output handling" below.
Install
The sandbox runs containers rootless, as a dedicated sandbox user. The
image and the running service must live in that user's podman store. This
is the single most important thing to get right — see Troubleshooting.
1. Create the service user
useradd -r -m -d /var/lib/mcp-sandbox -s /bin/bash sandbox
echo "sandbox:100000:65536" >> /etc/subuid
echo "sandbox:100000:65536" >> /etc/subgid
# rootless podman needs a runtime dir (/run/user/<uid>) present at boot:
loginctl enable-linger sandbox2. Build the image — as the sandbox user
Build into the sandbox user's rootless store. Not your login user's,
not root's — the server only ever reads sandbox's store:
sudo -u sandbox -H podman build -t mcp-sandbox:latest -f Containerfile .Already built the image elsewhere? Don't rebuild — transfer it across the store boundary:
podman save mcp-sandbox:latest | sudo -u sandbox -H podman load3. Install the server
python3 -m venv venv
venv/bin/pip install -e .Running as a service
Run the server as sandbox so it reads that user's image store. Minimal
unit (adjust the checkout path and entrypoint to your install):
# /etc/systemd/system/mcp-sandbox.service
[Unit]
Description=mcp-sandbox MCP server
After=network.target
[Service]
User=sandbox
ExecStart=/var/lib/mcp-sandbox/mcp-sandbox/venv/bin/mcp-sandbox
Restart=on-failure
[Install]
WantedBy=multi-user.targetAdding dependencies
The image is the single source of truth for what a runtime can do. Because every
run is a fresh --rm container, a runtime pip install inside a sandbox does
not persist — it re-downloads and rebuilds on every invocation, and on
current Fedora it hits PEP 668 (externally-managed-environment) anyway. So:
Missing package? Add the
python3-*(orR-*, etc.) RPM to theContainerfileand rebuild the image — don't pip-install at runtime. Prefer Fedora RPMs; they keep the image reproducible and versioned in git.No Fedora RPM for it? Add a build-time
RUN pip install …layer to theContainerfile, baked into the image — never a runtime install in the sandbox.
Rebuild after any change (as the sandbox user — see Install/Troubleshooting):
sudo -u sandbox -H podman build -t mcp-sandbox:latest -f Containerfile .Output handling
Files written to /sandbox/output/ are returned by reference, not inlined
as base64. After a run, the server stages each output under a fresh unguessable
token and returns a compact metadata record in place of the bytes:
{
"name": "figure.png",
"bytes": 29901,
"sha256": "…",
"mime": "image/png",
"url": "https://host.example/sandbox-out/<token>/figure.png",
"expires_in": 3600
}Capability URL. Each file is staged at
/<token>/<name>, where<token>is ~256 bits from a CSPRNG (secrets.token_urlsafe(32)). Possessing the URL is the authorization to fetch it — there is no separate credential.Small text is still inlined. Text outputs below 4 KB come back inline; a round-trip to read three lines isn't worth it. Everything else is referenced.
Bounded lifetime. Staged files live for a TTL (default 60 min), after which the GC timer deletes them and the URL 404s — this bounds the exposure window of any leaked URL.
Integrity. The
sha256lets a consumer verify the bytes, or confirm a file's identity without fetching it.
Serving the staged outputs
nginx serves the staging directory read-only, with listing, logging, and auth off (the token is the authentication):
location /sandbox-out/ {
alias /var/cache/mcp-sandbox/outputs/;
auth_basic off; # the capability token is the authorization
autoindex off; # non-enumerable: no directory listing
access_log off; # keep tokens out of logs
add_header X-Robots-Tag "noindex" always;
}On SELinux, the staging dir must carry httpd_sys_content_t, applied before
it is populated:
semanage fcontext -a -t httpd_sys_content_t "/var/cache/mcp-sandbox/outputs(/.*)?"
restorecon -RFv /var/cache/mcp-sandbox/outputsExpiry is a systemd .timer firing every 15 min that deletes token directories
older than the TTL.
Configuration
HOST=127.0.0.1
PORT=8815
SANDBOX_IMAGE=mcp-sandbox:latest
DEFAULT_TIMEOUT=60
MAX_TIMEOUT=300
# Output-by-reference — REPLACE names with the actual ones from the code:
SANDBOX_PUBLIC_URL=https://host.example # base for capability links
OUTPUT_DIR=/var/cache/mcp-sandbox/outputs # staging directory
OUTPUT_TTL=3600 # seconds; keep in sync with GC timerTroubleshooting
Rebuilt the image but the server still runs the old one?
You almost certainly built into the wrong podman store. Containers run
rootless as sandbox, which reads its own store under
/var/lib/mcp-sandbox/.local/share/containers. An image built as your login
user or as root lands in a different store the server never reads — so the
build "succeeds" and changes nothing.
Confirm what the service actually sees, and rebuild/load into that store:
sudo -u sandbox -H podman images mcp-sandbox
sudo -u sandbox -H podman build -t mcp-sandbox:latest -f Containerfile .
# or: podman save mcp-sandbox:latest | sudo -u sandbox -H podman loadNo MCP restart is needed afterwards — each run is a fresh --rm container
that resolves mcp-sandbox:latest from the sandbox store at launch.
Restart the service only when you change the server code or RUNTIMES.
License
Apache-2.0
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/lemenkov/mcp-sandbox'
If you have feedback or need assistance with the MCP directory API, please join our Discord server