E2b Code Mode
БесплатноНе проверенA Code Mode MCP server for the e2b API, giving agents three tools (search, execute_read, execute_write) to write and run JavaScript functions inside sandboxed e
Описание
A Code Mode MCP server for the e2b API, giving agents three tools (search, execute_read, execute_write) to write and run JavaScript functions inside sandboxed environments for API discovery and calls.
README
A Model Context Protocol server that gives an agent three tools instead of dozens for driving the e2b REST API. The agent writes a short JavaScript function that runs inside an e2b sandbox and calls the API through a thin api.request() client — looping, filtering, and chaining calls in one round-trip.
This applies Cloudflare's Code Mode pattern to e2b:
- LLMs write API-calling code more reliably than long chains of individual tool calls.
- Intermediate data stays in the sandbox, out of the model's context.
- The agent discovers endpoints with
search(the OpenAPI spec), then calls them withexecute_read/execute_write.
Quickstart
Prerequisites: Node.js ≥ 20.12, pnpm (corepack enable provides it), and an e2b API key (dashboard).
pnpm install
pnpm build
pnpm start # or: pnpm dev (no build step)
The server starts a stateless streamable-HTTP MCP endpoint on http://127.0.0.1:3000/mcp. It has no API key of its own — each request carries the caller's e2b key as a bearer token.
Connect an MCP client (the key travels as Authorization: Bearer <e2b-key>; this repo ships a .mcp.json):
{
"mcpServers": {
"e2b-code-mode": {
"type": "http",
"url": "http://127.0.0.1:3000/mcp",
"headers": { "Authorization": "Bearer ${E2B_API_KEY}" }
}
}
}
Copy .env.example to .env and set E2B_API_KEY so ${E2B_API_KEY} expands and the live tests can run.
Try it — call execute_read with an async arrow function:
async () => {
const res = await api.request({ method: 'GET', path: '/sandboxes' })
return { status: res.status, running: res.data.length }
}
You get back e.g. { "status": 200, "running": 2 } — produced by code the agent wrote, run in a sandbox that can reach only the e2b API. See TEST-PROMPT.md for a richer, dashboard-visible demo task.
The three tools
Each takes a single code string — an async arrow function that returns a value. console.log output comes back separately as stdout.
| Tool | What it does | In scope | Annotation |
|---|---|---|---|
search |
Query the e2b OpenAPI spec (all $refs resolved) to find endpoints and their shapes. Network-isolated. |
spec |
read-only |
execute_read |
Call the e2b API via api.request() — GET only. |
api |
read-only |
execute_write |
Call the e2b API via api.request() — any method (POST/PUT/PATCH/DELETE). |
api |
destructive |
The workflow is: search to find an endpoint's path and request shape, then execute_read/execute_write to call it. The client is api.request({ method, path, query?, body?, contentType?, rawBody? }), which returns { status, ok, data }.
How it works
MCP client ──HTTP (stateless JSON)──▶ express /mcp ──▶ McpServer (3 tools)
Bearer: e2b key │
┌────────────────┼────────────────┐
search execute_read execute_write
│ └───────┬───────┘
▼ ▼
fresh sandbox fresh sandbox
(egress DENIED) (egress → api.e2b.dev only;
embeds `spec` E2B_API_KEY injected;
`api.request()` client)
- Transport — stateless JSON: a fresh
McpServer+ transport perPOST /mcp(sessionIdGenerator: undefined,enableJsonResponse: true— no sessions, no SSE), so the server holds no protocol state and scales horizontally;GET/DELETE /mcpreturn 405. - Per call — a fresh e2b sandbox, killed in
finally. No SDK is installed inside it, so there's nothing to amortize with a warm pool. searchsandbox — all egress denied; the slimmed OpenAPI spec is embedded asspecfor the agent's read-only code to query.execute_*sandbox — egress limited toapi.e2b.dev; the caller's key is injected asE2B_API_KEYand used byapi.request(). The read/write split is enforced in the client:execute_readthrows on any non-GET before the fetch (annotated read-only), whileexecute_writeallows every method (destructive).- Runner — agent code is written to a file and run with
node(nevereval); output returns via a result file. The code sits on its own lines in the invoke scaffold, so a trailing// commentcan't swallow the closing tokens.
The source is small and layered by responsibility:
| File | Responsibility |
|---|---|
src/index.ts |
Entry point: loads .env, starts the HTTP listener, configures loopback DNS-rebinding protection. |
src/http.ts |
Express app: streamable-HTTP transport, bearer auth, Host/Origin validation, /healthz, /debug/endpoints. |
src/server.ts |
The MCP surface: the three tools, response formatting, the untrusted-data boundary. |
src/sandbox.ts |
Sandbox plumbing: runner construction, the two sandbox shapes, the injected api.request() client, output caps, the credential/admin guard. |
src/spec.ts |
Fetches, $ref-resolves, slims, and caches the e2b OpenAPI spec for search. |
src/log.ts |
pino logger + credential redaction. |
Security notes
Agent code is untrusted but runs inside an e2b Firecracker microVM and authenticates with the caller's own e2b key — so by design it can use that key against the e2b API. Beyond the sandbox isolation, per-tool egress, and read/write split above:
- Untrusted-data boundary — all execute output (
result/stdout/stderr) may embed API content (logs, metadata), so it's wrapped in a<untrusted-data-{uuid}>…</>envelope (error path too), with the model told not to follow instructions inside. Truncation happens before wrapping, so a size cap can't sever the closing tag. - Credential/admin block — paths containing
api-keys,access-tokens,teams, oradmin(incl./admin/teams/{id}/api-keys) are refused. The path is first normalized to a fixpoint (percent-decode, re-resolve dot-segments, collapse slashes, lowercase), so encoded spellings (/%61pi-keys,//access-tokens,/x%2F..%2Fteams,/TEAMS) still match; it only over-blocks. - HTTP hardening — bearer token required on
/mcp(401+WWW-Authenticateotherwise); loopback binds get DNS-rebinding protection (Host/Origin allowlist, incl.[::1]); 1 MB body cap. - Output caps — bounded inside the sandbox before reaching the server: runner result cap (400k chars),
head -creads (500k file / 20k per stream), final server truncate (100k result / 10k logs). - Token location (vs Cloudflare) — Cloudflare keeps the token out of the isolate via an outbound-fetch proxy; e2b has no such hook, so
E2B_API_KEYlives in the sandbox env (agent code can read it). Safety rests on isolation + egress — the key only reachesapi.e2b.dev— not token secrecy.
Configuration
All optional except the caller's bearer token.
| Env var | Default | Meaning |
|---|---|---|
PORT |
3000 |
HTTP listen port |
HOST |
127.0.0.1 |
Bind address (loopback enables DNS-rebinding protection) |
E2B_TEMPLATE |
base |
e2b template the sandboxes boot from (needs Node with global fetch; secure-mode compatible) |
E2B_EXEC_TIMEOUT_MS |
120000 |
Per-call budget for the agent's code |
E2B_OPENAPI_URL |
e2b infra spec | Override the OpenAPI spec URL the search tool loads |
E2B_API_KEY |
— | Only used by local tooling/tests; HTTP callers send it as the bearer token |
LOG_LEVEL |
info |
trace/debug/info/warn/error/fatal/silent |
LOG_FORMAT |
json |
json (structured) or pretty (dev) |
MCP_DEBUG_ENDPOINT |
true |
Set false to disable GET /debug/endpoints |
Observability
Structured logs via pino to stderr: one line per HTTP request (method, path, status,
responseTime,req.id; 4xx→warn, 5xx→error) plus per-call lifecycle lines carrying thereqId, redacted key, duration, andcalledEndpointscount. UseLOG_FORMAT=prettylocally. Credentials are never logged.GET /debug/endpoints— a no-auth JSON listing of every route (method, path, auth, description), the tool names, and a small status block (version, pid, uptime, log level). No secrets; disable withMCP_DEBUG_ENDPOINT=false.curl -s localhost:3000/debug/endpoints | jq
Testing
pnpm test
test/server.test.ts— the MCP surface via an in-memory client/server pair (tool list, annotations, error shapes). No key.test/http.test.ts— the express app over a real ephemeral port: stateless JSON shape, the bearer-auth gate, non-Bearer rejection, token→handler plumbing, 405s, DNS-rebinding enforcement, and the/debug/endpointsmanifest. No key.test/live.test.ts— end-to-end against real e2b: spec search,execute_readGET plus non-GET rejection, trailing-comment tolerance, error/SyntaxErrorsurfacing inside the boundary, the credential/admin guard (including encoded bypasses), anexecute_writecreate+delete round-trip, egress denial, and the stdout size cap. Runs only whenE2B_API_KEYis set.
Установить E2b Code Mode в Claude Desktop, Claude Code, Cursor
unyly install e2b-code-modeСтавит в Claude Desktop, Claude Code, Cursor и VS Code — сам разбирается с npx, uvx и сборкой из исходников.
Впервые? Поставь CLI: curl -fsSL https://unyly.org/install | sh
Или настроить вручную
Выполни в терминале:
claude mcp add e2b-code-mode -- npx -y github:Rodriguespn/e2b-mcp-code-modeFAQ
E2b Code Mode MCP бесплатный?
Да, E2b Code Mode MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для E2b Code Mode?
Нет, E2b Code Mode работает без API-ключей и переменных окружения.
E2b Code Mode — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить E2b Code Mode в Claude Desktop, Claude Code или Cursor?
Открой E2b Code Mode на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectCompare E2b Code Mode with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
