MCP server that exposes a V8 JavaScript runtime as a tool for AI agents like Claude and Cursor. Supports persistent heap snapshots via S3 or local filesystem, and is ready for integration with modern AI development environments.
- ✓Open-source license (AGPL-3.0)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Topics declared
- ✓Mature repo (>1y old)
- ✓Documented (README)
- !Install pipes a remote script into a shell (curl | sh)
git clone https://github.com/r33drichards/mcp-js{
"mcpServers": {
"mcp-js": {
"command": "mcp-js"
}
}
}MCP Servers overview
# mcp-v8 — a JavaScript/TypeScript runtime for AI agents
[](https://r33drichards.github.io/mcp-js/)
[](https://github.com/r33drichards/mcp-js/releases)
[](./LICENSE)
[](https://railway.com/deploy/mcp-js?referralCode=cj5P6Z&utm_medium=integration&utm_source=template&utm_campaign=generic)
**mcp-v8** is a [Model Context Protocol](https://modelcontextprotocol.io) server,
written in Rust, that lets an AI agent **run JavaScript and TypeScript in a
sandboxed V8 isolate**. Instead of wiring up dozens of narrow tools, you give the
agent one tool — `run_js` — and it writes code: looping, branching, transforming
data, and calling other tools, often with far fewer tokens than equivalent
tool-call chains.
In its default *stateful* mode the V8 heap is saved as a content-addressed
snapshot, so an agent can build up state across many turns. Host capabilities
(network, filesystem, subprocess, WebAssembly, module imports, and calls to other
MCP servers) are all **off by default** and unlocked only by explicit
[OPA/Rego policies](https://www.openpolicyagent.org/).
## Why mcp-v8
- **One tool, unbounded capability.** The agent runs a program, not a fixed menu of tools.
- **Durable state.** Heap snapshots persist variables and objects across calls.
- **Secure by default.** `fetch`, filesystem, subprocess, and external imports are denied until you grant them via policy.
- **Kernel-enforced confinement.** Opt-in [`--sandbox-manifest`](https://r33drichards.github.io/mcp-js/concepts/os-sandbox/) confines the whole process with a [nono](https://github.com/nolabs-ai/nono) capability manifest (Landlock on Linux, Seatbelt on macOS) as defense in depth beneath the policy layer.
- **Production-ready.** stdio / Streamable HTTP / SSE transports, a REST sidecar, async execution with pagination, JWKS auth, and Raft-replicated clustering.
## Documentation
Maintainers: see [Publishing to the MCP Registry](./docs/mcp-registry.md) for
the Docker-backed registry manifest and automated release process.
Full documentation lives at **<https://r33drichards.github.io/mcp-js/>** (built
from [`site-docs/`](./site-docs)) — tutorials, how-to guides, concept
explanations, and complete reference for the [CLI flags](https://r33drichards.github.io/mcp-js/reference/cli-flags/),
[HTTP API](https://r33drichards.github.io/mcp-js/reference/http-api/), and
[MCP tools](https://r33drichards.github.io/mcp-js/reference/mcp-tools/).
## Quick start
### Install
```bash
# Server
curl -fsSL https://raw.githubusercontent.com/r33drichards/mcp-js/main/install.sh | sudo bash
# Optional CLI client
curl -fsSL https://raw.githubusercontent.com/r33drichards/mcp-js/main/install-cli.sh | sudo bash
```
Installs to `/usr/local/bin`. Supported platforms: Linux x86_64/arm64 and macOS
Apple Silicon. You can also `nix run github:r33drichards/mcp-js`, use Docker (see
the `docker-compose.*.yml` stacks), or [build from source](#build-from-source).
Prefer a hosted server? [Deploy on Railway](./RAILWAY.md) — the repo's
`railway.json` configures the build, healthcheck, and restart policy, and
[RAILWAY.md](./RAILWAY.md) walks through the volume, variables, and one-click
template setup.
### Connect an MCP client
```bash
# Claude Code (stdio)
claude mcp add mcp-v8 -- mcp-v8 --directory-path /tmp/mcp-v8-heaps # stateful
claude mcp add mcp-v8 -- mcp-v8 --stateless # stateless
```
For Claude Desktop / Cursor, add to the client's `mcpServers` config:
```json
{ "mcpServers": { "js": { "command": "mcp-v8", "args": ["--stateless"] } } }
```
Then ask the agent: *"Run this JavaScript: `console.log([1,2,3].map(x => x*2))`"*.
### Run over HTTP
```bash
mcp-v8 --stateless --http-port 8080
# MCP endpoint: POST http://localhost:8080/mcp
# REST sidecar: POST http://localhost:8080/api/exec (JSON body, or a raw-body file upload)
```
`/api/exec` accepts either a JSON body or a raw-body file upload — send the
script as the request body with a non-JSON `Content-Type`
(`curl --data-binary @script.js -H 'Content-Type: application/javascript' .../api/exec`).
The `run_js` MCP tool can also read a script from a path on the server itself
via an optional `file` parameter — off by default, enabled with
`--allow-run-js-file` or a `run_js_file`
[policy](https://r33drichards.github.io/mcp-js/concepts/policies/).
See the [Quick Start tutorials](https://r33drichards.github.io/mcp-js/) and the
[transports guide](https://r33drichards.github.io/mcp-js/concepts/transports/) for more.
### Configure with a single file
Every flag can also live in one TOML or JSON file passed via `--config` (or
`MCP_V8_CONFIG`), including structured sections that replace the separate
WASM / MCP-server / fetch-header / policy JSON files:
```toml
# server.toml — run with: mcp-v8 --config server.toml
http_port = 8080
heap_store = "dir"
heap_dir = "/var/lib/mcp-v8/heaps"
[policies.fetch]
policies = [{ url = "file:///etc/mcp-v8/fetch.rego" }]
```
Precedence is CLI flag > `MCP_V8_*` env var > config file > default. See the
[configuration file reference](https://r33drichards.github.io/mcp-js/reference/config-file/).
## Features
- **JavaScript & TypeScript** in an isolated V8 engine (via `deno_core`); TypeScript types are stripped with [SWC](https://swc.rs/) (type removal, not type checking).
- **Async/await & timers** — Promises and the event loop, plus `setTimeout`/`clearTimeout`.
- **Console capture** — `console.log/info/warn/error/debug/trace`, streamed to storage and readable with line- or byte-based pagination.
- **Async execution model** — `run_js` returns an execution ID; poll status and stream output; cancel running work.
- **Content-addressed heap snapshots** — persist/restore V8 state across calls (local FS, S3, or S3 + write-through cache), or run **stateless**.
- **WebAssembly** — the standard `WebAssembly` API, plus pre-loaded modules (`--wasm-module`) exposed as globals and advertised to clients as `runjs__wasm__<name>` stub tools.
- **ES module imports** — optional `npm:`, `jsr:`, and URL imports fetched at runtime (policy-gated).
- **Policy-gated capabilities** — `fetch`, filesystem (`fs`), and subprocess access, each checked against a Rego policy per operation; plus header/OAuth injection for `fetch`.
- **Compose other MCP servers** — connect upstream MCP servers and call them from JS via `mcp.callTool()` / `mcp.listTools()`.
- **Customizable surface** — override the server `instructions` and the `run_js` description (`--instructions`, `--run-js-description`).
- **Single-file configuration** — one TOML/JSON `--config` file can set every flag (precedence: CLI flag > env var > config file > default).
- **Auth & clustering** — JWKS-based JWT verification, and optional Raft clustering with replicated session metadata and horizontal scaling.
- **Multiple transports** — stdio, Streamable HTTP (MCP 2025-03-26+), and a legacy HTTP+SSE transport (`--sse-port`, served by a vendored rmcp 0.1.5), with a REST sidecar and OpenAPI spec.
- **Tasks** — native MCP [tasks](https://modelcontextprotocol.io/specification/2025-11-25/basic/utilities/tasks) (SEP-1319) over Streamable HTTP / stdio: task-enabled clients can run `run_js` as a task (`tasks/get`, `tasks/result`, `tasks/list`, `tasks/cancel`), ideal for long-running calls. (The legacy SSE transport does not offer tasks.)
## What the agent's code can do
These globals are available inside `run_js` (capability globals require a policy):
| Global | Purpose | Gated by |
|--------|---------|----------|
| `console`, `setTimeout` | Output & timers | — |
| `fetch(url, opts?)` | HTTP requests (Fetch API) | `fetch` policy |
| `fs.*` | File I/O (`readFile`, `writeFile`, …) | `filesystem` policy |
| `child_process` / `Deno.Command` | Run subprocesses | `subprocess` policy |
| `import` (`npm:` / `jsr:` / URL) | External ES modules | `--allow-external-modules` + `modules` policy |
| `WebAssembly`, `__wasm_<name>` | Run/instantiate WASM | — |
| `mcp.callTool/listTools/servers` | Call upstream MCP servers | `mcp_tools` policy |
See [Concepts → Security policies](https://r33drichards.github.io/mcp-js/concepts/policies/) for the policy model.
## MCP tools
| Tool | Mode | Description |
|------|------|-------------|
| `run_js` | both | Stateful: queue execution → `{execution_id}`. Stateless: run and return `{output, error?}`. |
| `get_execution` | stateful | Poll status/result of an execution. |
| `get_execution_output` | stateful | Read paginated console output (line or byte). |
| `cancel_execution` | stateful | Terminate a running execution. |
| `list_executions` | stateful | List executions and their status. |
| `list_sessions`, `list_session_snapshots` | stateful | Browse named sessions and history. |
| `get_heap_tags`, `set_heap_tags`, `delete_heap_tags`, `query_heaps_by_tags` | stateful | Tag and search heap snapshots. |
Full parameters: [MCP tools reference](https://r33drichards.github.io/mcp-js/reference/mcp-tools/).
### Long-running calls as tasks
The server natively implements the MCP **tasks** utility (spec `2025-11-25` /
SEP-1319) via rmcp, over both the Streamable HTTP and stdio transports. The
`initialize` result advertises a `tasks` capability, and a client may run the
task-augmentable `run_js` tool as a task by adding a `task` object to the
request params:
```jsonc
// → returns immediately with a task instead of blocking
{ "method": "tools/call",
"params": { "name": "run_js", "arguments": { "code": "…" }, "task": { "ttl": 300000 } } }
```
The client then polls `tasks/get`, fetches the eventual tool result with
`tasks/result` (which returns exactly what the call would have returned),
enumerates work with `tasks/list`, and stops a run with `tasks/cancel`. A
`tools/call` without a `task` field is unaffectWhat people ask about mcp-js
What is r33drichards/mcp-js?
+
r33drichards/mcp-js is mcp servers for the Claude AI ecosystem. MCP server that exposes a V8 JavaScript runtime as a tool for AI agents like Claude and Cursor. Supports persistent heap snapshots via S3 or local filesystem, and is ready for integration with modern AI development environments. It has 57 GitHub stars and its last recorded update is dated 2026-10-01.
How do I install mcp-js?
+
You can install mcp-js by cloning the repository (https://github.com/r33drichards/mcp-js) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is r33drichards/mcp-js safe to use?
+
Our security agent has analyzed r33drichards/mcp-js and assigned a Trust Score of 92/100 (tier: Verified). See the full breakdown of passed checks and flags on this page.
Who maintains r33drichards/mcp-js?
+
r33drichards/mcp-js is maintained by r33drichards. The last recorded GitHub activity is dated 2026-10-01, with 21 open issues.
Are there alternatives to mcp-js?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy mcp-js to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/r33drichards-mcp-js)<a href="https://claudewave.com/repo/r33drichards-mcp-js"><img src="https://claudewave.com/api/badge/r33drichards-mcp-js" alt="Featured on ClaudeWave: r33drichards/mcp-js" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
The fastest path to AI-powered full stack observability, even for lean teams.