
Parselbox
io.github.thesanjeetc由 GitHub 账号 thesanjeetc 发布v0.1.1更新于 Oct 24, 2026
Secure Python sandbox — MCP servers, APIs, shells and host functions as native Python objects.
概览
Parselbox 是一个本地 Python 沙箱 MCP 服务器,让助手运行代码,并把 MCP 服务器、API 和 shell 当作原生 Python 对象调用。
- 可以做什么
- 在有状态、磁盘持久的工作区中执行 Python 代码,并提供虚拟 bash shell
- 把其他 MCP 服务器的工具作为 Python 命名空间调用,另含 REST、GraphQL 与 shell 桥接
- 通过 help、search、inspect、preview 按需发现可用能力
- 运行后台任务、并行分发和交互式 shell 会话
- 通过输入文件、只读或读写挂载以及持久输出目录读写文件
- 加载 Python 与 npm 包、WASI 二进制,并内联渲染 HTML 或提供小型 Web 应用
- 适用场景
- 适合需要在一个脚本里编排多个工具或 MCP 服务器、而不是串联大量独立工具调用的场景,也适合需要带文件、包和受控网络访问的沙箱 Python 运行时来做数据处理和图表。
- 运行要求
- 通过 uvx 以 stdio 在本地运行(PyPI 包 parselbox)。主机需安装 Deno 作为沙箱运行时。网络默认关闭,需显式开启或加入允许列表;挂载、输出目录、包以及内存和超时限制通过命令行参数或 API 选项设置。
安装
在 SourceWeft 中
- 打开 控制台中的 Parselbox,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
[Parselbox SDK] [Parselbox SDK]
Code. Filesystem. Context. Tools.
What if agents had one tool to rule them all?
[License] [PyPI - Version] [CI]
Parselbox is an embeddable Python runtime where AI agents call tools as code — MCP servers, APIs, and shells become native Python objects. Disk-backed workspace, packages, and networking built in; a single-process execution layer powered by Deno and Pyodide.
https://github.com/user-attachments/assets/d4e43d16-3aa3-4e29-83c7-a1d3885b8045
[!TIP] Drop the Parselbox MCP alongside existing MCP server configurations. Agents instantly get a Python runtime, MCP tools as code, support for skills and a disk-backed workspace.
Why Parselbox?
Parselbox packages programmatic tool calling as a local, open-source execution layer. Drop it into an existing MCP configuration with uvx, or embed the Python API into any agent stack.
Beyond code execution, Parselbox provides a stateful, disk-backed workspace with packages, controlled networking, background tasks and progressive discovery.
Deno + Pyodide provide a single-process runtime with explicit filesystem and network permissions — no containers or microVMs required. It also enables JavaScript/npm interoperability, WASM/WASI integration and generative UI through MCP Apps.
Why an execution layer?
Most agent stacks expose each capability as a separate tool. As integrations grow, tool schemas consume more context. The model must also carry intermediate results, transform data and route values between calls.
An execution layer moves orchestration out of the context window and into code. Capabilities are discovered on demand, then composed with full control flow. A single execution can coordinate multiple tools while variables, state and files remain inside the runtime.
The result is less context bloat, fewer model-to-tool round trips and complex workflows expressed as code rather than chains of individual calls.
Features
🔒 Secure Isolation
No containers, no VMs — just a single, lightweight Deno + Pyodide process (~160 MB). Deno permissions, memory caps, timeouts, network allowlists. Snapshot caching and crash recovery.
🛠️ Tools as Code
MCP servers, REST + OpenAPI, GraphQL, shell, functions and classes — all native Python objects. Stateful across calls. Pydantic auto-conversion. Credentials stay on the host.
🐍 Polyglot Runtime
Full CPython with js() interop — use JS packages as native Python. require() for npm, local TypeScript, and .wasm modules. Virtual bash() for shell. Auto-install packages on import.
📦 WASM Tools
require() any .wasm — library exports become Python methods, WASI programs become callable commands; drop one in bin/ to run it from bash() too. In-process, inherits the sandbox's mounts and permissions, installs nothing on the host.
⚡ Background Tasks
Append .task() to any call — parallel fan-out with asyncio.gather, check progress, tail logs, drive interactive sessions with send(), await later.
📁 Filesystem Integration
Disk-backed workspace — host mounts (ro/rw), input files at /files/, outputs persisted to real directories. New and modified files are detected and returned per call.
🔍 Progressive Disclosure
help(), search(), inspect(), preview() — agents discover only what they need, when they need it.
🎨 Generative UI
display() renders HTML inline in the chat (MCP Apps), with Tailwind + daisyUI injected. Or serve a full app — built-in HTTP server with static files, live reload, file upload, and @api routes that compose across tools.
Contents
Quick Start
Parselbox uses Deno for the secure sandbox runtime.
1. Install Deno
2. Install Parselbox
Parselbox API
Wire any tool into the sandbox — MCP servers, REST/GraphQL, shells, host objects — and the agent calls them as native Python, composing them with real control flow over a disk-backed workspace and both the Python and npm package ecosystems.
Example:
Parselbox MCP
The Parselbox CLI runs a standalone MCP server — every sandbox option is available as a flag.
STDIO
[!TIP] The "loopback" trick:
- Add the Parselbox MCP alongside your existing MCP servers.
- Point
--mcpat that same config file.- On startup, Parselbox connects to the other servers, exposes their tools inside the sandbox, and starts its own MCP server.
Don't worry — Parselbox detects and avoids connecting to itself. No infinite loops of doom.
Example:
HTTP
Full Example
Parselbox Agents
User Guide
1. Tools as Code
The context bridge exposes host Python objects inside the sandbox:
context— functions and namespaces as callable tools. Execution pauses, runs on host, returns result.globals— static values (strings, numbers, dicts) copied into the sandbox.mcp— MCP server config (dict or path). Appears as callable namespaces inside sandbox.
Plain classes are auto-wrapped — every public method becomes a callable tool; methods starting with _ stay private:
Subclass Bridge for nested namespaces (auto-crawled); annotate a parameter with a Pydantic model and passed dicts convert to it automatically:
Parselbox ships bridges for REST, GraphQL, and shell:
Runnable: bridges.py
2. Background Tasks
Every context and MCP call also has a .task() form that runs on the host without blocking the sandbox — for parallel fan-out, long-running jobs, and interactive sessions:
MCP tools stream their progress and log notifications into the task's logfile. A custom Bridge method emits the same way with self.log(), and reads whatever the sandbox queued via send() with self.recv():
Interactive sessions — ShellBridge.shell() keeps stdin open, so a task can drive a live process with send():
An optional first command launches any REPL as the session — e.g. sh.shell.task("python3 -i").
Runnable: tasks.py
3. Filesystem Integration
Parselbox runs on Pyodide's virtual filesystem, with the working directory, input files, mounts, and packages backed by real host directories — access gated by Deno's permission controls at startup.
[!NOTE]
/workspaceis always backed by a real host directory —output_dir(persistent) or an ephemeral temp dir (wiped on close) — enabling Deno streaming,resolvePath(), andrequire()for local modules.- Cross the boundary with
sandbox.read_file(path)(strfor text,bytesfor binary) andsandbox.write_file(path, content); a persistentoutput_diris also readable directly.- Mounts with
target="skills"are reported bysbx.info()and discoverable viabash("ls /mnt/skills/").
Example:
Reach the same files from a shell with bash():
Runnable: filesystem.py · bash.py
4. Packages & Networking
Packages
Pyodide supports pure-Python packages and many C-extension packages, which must be pre-built for Pyodide — numpy, pandas, and more ship included.
[!NOTE] Package installs write straight to disk — a temp dir by default (wiped on exit). Set
package_dirto persist them across sessions, so the next boot is instant with no re-download.
Networking
After initial package loading, network is blocked by default. Access is configured with Deno's permission controls via --allow-net / --deny-net. All HTTP from sandboxed code (requests, httpx, fetch) routes through Deno's fetch().
[!NOTE] The CLI
--networkflag is a boolean toggle only. Domain allowlists are available via the Python API.
Proxy & Credential Injection
Pyodide is not a security boundary — sandboxed code can read env vars via js('Deno.env.get("KEY")'), so never pass real credentials in env. Instead, run a credential-injecting proxy on the host and lock the sandbox to it:
Most SDKs take a base_url override. For SDK-agnostic interception, set HTTP_PROXY/HTTPS_PROXY/DENO_CERT instead and route everything through a MITM proxy — Deno's fetch() honours them at the process level.
Runnable: basics.py
5. JavaScript Interop
Parselbox runs Python inside Deno's V8 engine via Pyodide, so Python and JavaScript share the same process memory — interop is seamless.
js() — Execute JavaScript from Python
Each js() call runs in a fresh, stateless scope. Python callables are auto-proxied and cleaned up after the call. Binary converts too — Uint8Array/ArrayBuffer results become Python bytes, and bytes arguments become Uint8Arrays.
require() — Import npm Packages, Local Modules and WASM
Deno Streaming (Large Files)
For files too large to fit in memory, use Deno streams via resolvePath():
Python callbacks work inside streaming pipelines — Deno reads, JS parses, Python classifies each line.
Writing and Importing Modules
You can even compile a language to WebAssembly in-sandbox, then require() the output.
bash() — Shell Commands
A pure-JavaScript bash (just-bash) over the same workspace. Pipes and coreutils work, and curl is backed by fetch. Each call is isolated (cd/export don't persist); filesystem changes do.
Runnable: javascript.py · bash.py
6. WASM Tools
Pyodide can only load packages built for it — so pandoc, ruby or shellcheck are out of reach, and there is no apt-get in a single-process sandbox. Parselbox closes that gap with WASI: any program compiled to WebAssembly becomes a tool, with no host install.
A missing capability is just a file.
Two kinds of .wasm
require() inspects the module and picks the right shape:
A command returns {"exit": int, "stdout": bytes, "stderr": str, "missing": [...]} — missing lists any syscalls the binary asked for that aren't implemented, so gaps surface as data rather than a crash.
[!IMPORTANT] Emscripten builds are not WASI builds. Much of npm's "wasm" (
sql.js,ffmpeg.wasm,tesseract.js) is compiled with Emscripten and needs its own JavaScript glue — import those as npm packages (require("sql.js")), not as bare.wasmfiles. Both routes work;require()tells you which one a binary needs.
stdin—strorbytes;stdoutalways comes back asbytes.preopens— grant extra guest directories, e.g.preopens={"/usr": "vendor/usr"}for a binary that expects its own tree.argv0— some binaries dispatch on their program name (lld becomeswasm-ldbusybox-style).
Binaries as bash() commands
A WASI command binary (a .wasm exporting _start) in a mount's bin/ directory becomes a shell command, usable alongside bash()'s JavaScript coreutils. Binaries are discovered per call, so a tool written mid-session works immediately.
Mount a bin/ folder read-only to ship a fixed toolset the agent can use but not modify — nothing installed on the host — or have it fetch a .wasm into bin/ at runtime, which works even when the sandbox's network is restricted to a single allowlisted host.
You can even build one from source in-process — fetch a WASI clang + wasm-ld into bin/, compile C to .wasm, then require() the result. No host toolchain, nothing installed.
[!NOTE]
- Auto-detected as WASI
preview1orwasi_unstable(preview0). Not supported: sockets, real sleeps, preview2 components.- Compiled modules are cached per path (invalidated on rebuild), so a 50MB binary compiles once per session.
Runnable: pandoc.py — fetch a WASI binary · compile_c.py — compile C → wasm in-sandbox
7. Progressive Disclosure
The sbx toolkit lets agents discover capabilities on demand instead of loading everything into context up front. Available as sbx.* inside the sandbox.
The sandbox also exposes a help() builtin for per-object introspection:
Example:
Runnable: toolkit.py
8. Generative UI
Agents can surface results two ways: inline in the conversation with display(), or as a full web app with serve.
Inline widgets — display()
Any HTML an agent passes to display() renders as a widget beneath its result, in hosts that support MCP Apps.
Tailwind and daisyUI are injected automatically, so plain markup is styled without a build step, and pbx.call("/api/route", body) inside the HTML reaches @api handlers when serve is on. display() also accepts a path to an HTML file in the workspace. One view per execution — the last call wins.
On by default. run_mcp(ui=False) turns it off, which stops advertising display() to the agent and drops the renderer from the tool. The rendered HTML is always on result.view regardless:
Web apps — serve
The serve option starts a Deno HTTP server inside the sandbox — agents build full web apps on the fly.
Static Files: Any files written to the Pyodide working directory are automatically served:
Served at their own paths, with / resolving to index.html; uploaded and input files live under /files/*.
API Handlers: Define endpoints using FastAPI-style decorators:
Routes are prefixed with /api/ automatically. Verbs: @api.get/post/put/patch/delete.
Handlers can call MCP tools, context functions, and any sandbox code:
Built-in Endpoints:
Runnable: display.py · serve.py
9. Sandbox Hooks
Hooks intercept sandbox lifecycle events — log executions, approve tool calls, enforce policies. Pass them via the hooks parameter.
ElicitHook — a built-in hook that uses MCP elicitation for human-in-the-loop approval. Enable via --elicit (CLI) or run_mcp(elicit=True) (API). Only fires if the MCP client advertises elicitation capability — otherwise it's a no-op.
Runnable: hooks.py
Configuration Reference
Parselbox has the following configuration options:
Architecture
Parselbox runs agent code in one Deno process with Pyodide (CPython in WebAssembly) — no containers, no VMs. The permission-jailed sandbox works in an isolated temp workspace, with no network and no host access beyond the mounts you grant; the host holds the credentials. Every tool call is a round-trip between them:
Tools look like native Python inside the sandbox, but they execute on the host — so credentials never enter the sandbox.
Security
Parselbox's boundary is Deno's permission system — the sandbox starts with nothing and gets only what you configure.
- Filesystem — isolated temp workspace (wiped on exit); read/write only to paths you pass (
files,mountsasro/rw,output_dir). Package-cache writes lock after startup unlessallow_runtime_packages=True. - Network — off by default (revoked before your code runs). Opt in with
network=True, an allowlistnetwork=["host:port", ...], orallow_runtime_packages=True(package domains only). For authenticated APIs, front it with a proxy — see Proxy & Credential Injection. - Compiled tools (WASI) — no sockets, so a binary has no network of its own; it sees only the mounts you grant (
roenforced by Deno), and a runaway is killed by the execution timeout. - Resource limits — WASM memory capped per instance at the V8 level (default 2048 MB), JS heap capped, per-execution timeout (default 60s →
KeyboardInterrupt), auto-reconnect if the Deno process dies. - Context bridge — only the objects you pass are reachable, and only their public methods; MCP servers expose their full tool set.
Related Work
- Code execution with MCP (Anthropic)
- Code Mode (Cloudflare)
- smolagents (Hugging Face)
- Deno + Pyodide Sandbox (Simon Willison)
来源:README.md,提交 786c27b
工具
0版本历史
1- v0.1.1最新Sep 16, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分