mcpField
M
mcp-v8: V8 JavaScript MCP Server

mcp-v8: V8 JavaScript MCP Server

本地服务
r33drichards.github.io文件与存储641 天前更新

关于 mcp-v8: V8 JavaScript MCP Server

mcp-v8 是用 Rust 编写的 MCP 服务,让 AI Agent 在隔离的 V8 环境中运行 JavaScript 和 TypeScript。它将代码执行集中到一个工具,并支持持久化堆快照及由策略控制的主机能力访问。

主要功能

  1. 01在 V8 中运行 JavaScript 和 TypeScript
  2. 02持久化并恢复堆快照
  3. 03通过 Rego 策略限制主机访问
  4. 04从 JavaScript 调用上游 MCP 服务
  5. 05支持 stdio、HTTP 和 SSE 传输
  6. 06将长时间运行的调用作为 MCP 任务

适用场景

  1. 01通过一次工具调用用 JavaScript 转换数据
  2. 02在 Agent 多轮调用间保留变量和对象
  3. 03按策略开放特定网络或文件系统操作
  4. 04组合已连接 MCP 服务的工具

MCP 相关

该服务提供 `run_js`,并在有状态模式下提供执行、输出、会话和堆快照管理工具。JavaScript 也可通过 `mcp.callTool()` 和 `mcp.listTools()` 调用已连接的上游 MCP 服务。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"js": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"docker.io/wholelottahoopla/mcp-js:0.22.0"
]
}
}
}
启动命令docker run -i --rm docker.io/wholelottahoopla/mcp-js:0.22.0

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
ocidocker.io/wholelottahoopla/mcp-js:0.22.0

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

mcp-v8 — 面向 AI 智能体的 JavaScript/TypeScript 运行时

Docs Release License: AGPL v3 Discord

Deploy on Railway

mcp-v8 是一个用 Rust 编写的 Model Context Protocol 服务, 可让 AI Agent 在沙箱化的 V8 隔离环境中运行 JavaScript 和 TypeScript。你无需连接数十个功能狭窄的工具,只需提供一个工具 — run_js,由 Agent 编写代码:循环、分支、转换数据并调用其他工具,通常比同等的工具调用链所需的令牌少得多。

在默认的有状态模式下,V8 堆会保存为内容寻址快照,因此 Agent 可以在多轮对话中累积状态。主机能力(网络、文件系统、子进程、WebAssembly、模块导入和调用其他 MCP 服务)默认全部禁用,只有通过明确的 OPA/Rego 策略 才能启用。

为什么选择 mcp-v8

  • 一个工具,能力无限。 Agent 运行的是程序,而不是固定的工具菜单。
  • 持久状态。 堆快照会在多次调用之间保留变量和对象。
  • 默认安全。 在你通过策略授权之前,fetch、文件系统、子进程和外部导入均不可用。
  • 由内核强制实施隔离。 可选择启用 --sandbox-manifest,通过 nono 能力清单限制整个进程(Linux 上使用 Landlock,macOS 上使用 Seatbelt),在策略层之下提供纵深防御。
  • 适用于生产环境。 支持 stdio / Streamable HTTP / SSE 传输、REST 辅助服务、带分页的异步执行、JWKS 身份验证,以及通过 Raft 复制的集群。

文档

维护者请参阅发布到 MCP Registry,了解基于 Docker 的 Registry 清单和自动化发布流程。

完整文档位于 https://r33drichards.github.io/mcp-js/(由 site-docs/ 构建),包含教程、操作指南、概念说明,以及 CLI 标志、HTTP API 和 MCP 工具的完整参考。

社区

加入 mcp-js Discord 社区,交流问题、示例和项目相关话题。

快速开始

安装
# 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

安装到 /usr/local/bin。支持的平台:Linux x86_64/arm64 和 macOS Apple Silicon。你也可以使用 nix run github:r33drichards/mcp-js、Docker(参见 docker-compose.*.yml 配置),或从源代码构建。

想使用托管服务?在 Railway 上部署 — 仓库的 railway.json 配置了构建、健康检查和重启策略,RAILWAY.md 介绍了卷、变量和一键模板的设置方法。

连接 MCP 客户端
# 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

对于 Claude Desktop / Cursor,请将以下内容添加到客户端的 mcpServers 配置中:

{ "mcpServers": { "js": { "command": "mcp-v8", "args": ["--stateless"] } } }

然后向 Agent 提出请求:“运行这段 JavaScript:console.log([1,2,3].map(x => x*2))”。

通过 HTTP 运行
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 接受 JSON 正文或原始正文文件上传——将脚本作为请求正文发送,并使用非 JSON 的 Content-Type( curl --data-binary @script.js -H 'Content-Type: application/javascript' .../api/exec)。 run_js MCP 工具也可以通过可选的 file 参数读取服务端本地路径中的脚本——默认关闭,可通过 --allow-run-js-file 或 run_js_file 策略启用。

更多信息请参阅快速入门教程和 传输指南。

使用单个文件进行配置

所有标志也可以放在通过 --config(或 MCP_V8_CONFIG)传入的单个 TOML 或 JSON 文件中,其中包括可替代单独的 WASM / MCP 服务 / fetch 标头 / 策略 JSON 文件的结构化分区:

# 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" }]

优先级为:CLI 标志 > MCP_V8_* 环境变量 > 配置文件 > 默认值。请参阅 配置文件参考。

功能

  • JavaScript 和 TypeScript:在隔离的 V8 引擎中运行(通过 deno_core);使用 SWC 移除 TypeScript 类型(仅移除类型,不进行类型检查)。
  • Async/await 和计时器:支持 Promise 和事件循环,以及 setTimeout/clearTimeout。
  • 控制台捕获:捕获 console.log/info/warn/error/debug/trace,将其流式写入存储,并支持按行或按字节分页读取。
  • 异步执行模型:run_js 返回执行 ID;可轮询状态、流式读取输出,并取消正在运行的任务。
  • 内容寻址堆快照:在多次调用之间持久化/还原 V8 状态(本地文件系统、S3,或 S3 + 写透缓存),也可使用无状态模式。
  • WebAssembly:提供标准的 WebAssembly API,以及预加载模块(--wasm-module);这些模块会作为全局变量公开,并以 runjs__wasm__<name> 存根工具的形式告知客户端。
  • ES 模块导入:可选支持运行时获取 npm:、jsr: 和 URL 导入(受策略控制)。
  • 受策略控制的功能:fetch、文件系统(fs)和子进程访问均会针对每项操作检查 Rego 策略;此外,fetch 还支持注入标头/OAuth。
  • 组合其他 MCP 服务:连接上游 MCP 服务,并通过 mcp.callTool() / mcp.listTools() 从 JS 调用它们。
  • 可自定义的界面:覆盖服务端的 instructions 和 run_js 描述(--instructions、--run-js-description)。
  • 单文件配置:一个 TOML/JSON --config 文件即可设置所有标志(优先级:CLI 标志 > 环境变量 > 配置文件 > 默认值)。
  • 身份验证和集群:基于 JWKS 的 JWT 验证,以及可选的 Raft 集群功能,支持复制会话元数据和水平扩展。
  • 多种传输方式:stdio、Streamable HTTP(MCP 2025-03-26+)和旧版 HTTP+SSE 传输方式(--sse-port,由 vendored rmcp 0.1.5 提供服务),并提供 REST sidecar 和 OpenAPI 规范。
  • 任务:通过 Streamable HTTP / stdio 使用原生 MCP 任务扩展(io.modelcontextprotocol/tasks,SEP-2663):声明了该扩展的客户端会将 run_js 作为任务运行(tasks/get、tasks/cancel),适用于长时间运行的调用。(旧版 SSE 传输方式不支持任务。)

Agent 的代码可以做什么

以下全局变量可在 run_js 中使用(能力全局变量需要策略):

全局变量用途受限于
console, setTimeout输出和计时器—
fetch(url, opts?)HTTP 请求(Fetch API)fetch 策略
fs.*文件 I/O(readFile、writeFile,……)filesystem 策略
child_process / Deno.Command运行子进程subprocess 策略
import(npm: / jsr: / URL)外部 ES 模块--allow-external-modules + modules 策略
WebAssembly, __wasm_<name>运行/实例化 WASM—
mcp.callTool/listTools/servers调用上游 MCP 服务mcp_tools 策略

有关策略模型,请参阅概念 → 安全策略。

MCP 工具

工具模式描述
run_js两者有状态:将执行任务加入队列 → {execution_id}。无状态:运行并返回 {output, error?}。
get_execution有状态轮询执行状态/结果。
get_execution_output有状态读取分页的控制台输出(按行或字节)。
cancel_execution有状态终止正在运行的执行。
list_executions有状态列出执行及其状态。
list_sessions, list_session_snapshots有状态浏览命名会话和历史记录。
get_heap_tags, set_heap_tags, delete_heap_tags, query_heaps_by_tags有状态为堆快照添加标签并搜索。

完整参数请参阅:MCP 工具参考。

将长时间运行的调用作为任务处理

该服务通过 rmcp 原生实现了 MCP tasks 扩展 (io.modelcontextprotocol/tasks,SEP-2663),支持 Streamable HTTP 和 stdio 两种传输方式。initialize 结果会在 capabilities.extensions 下声明此扩展;声明了相同扩展的客户端可为 run_js 启用任务执行:

// client initialize params
{ "capabilities": { "extensions": { "io.modelcontextprotocol/tasks": {} } } }

// → tools/call { name: "run_js", ... } returns immediately with a task:
//   { "resultType": "task", "taskId": "…", "status": "working", … }

之后,客户端会轮询 tasks/get(已完成的任务会内联携带工具结果,与调用本身的返回结果完全相同),并通过 tasks/cancel 停止运行。未声明此扩展的客户端仍会获得同步结果,不受影响。

配置

mcp-v8 完全通过 CLI 标志配置,包括存储后端、传输方式、执行限制、策略、Fetch 标头注入、WASM 模块、集群、JWKS 身份验证,以及提示词/工具描述覆盖项。完整且始终保持最新的列表请参阅生成的 CLI 标志参考。

mcp-v8 --help            # all flags
mcp-v8 --print-openapi   # print the REST OpenAPI spec
上游 MCP 服务的浏览器 OAuth

使用 --mcp-config 通过 OAuth 2.1 授权码流程连接到受保护的 Streamable HTTP MCP 服务。此设置仅接受 JSON;无法通过精简的 --mcp-server 语法使用。

[
  {
    "name": "protected",
    "transport": "http",
    "url": "https://mcp.example.com/mcp",
    "auth": {
      "type": "oauth_browser",
      "scope": ["tools.read", "tools.call"],
      "client_id": "optional-registered-client-id",
      "client_secret": "optional-client-secret",
      "redirect_port": 48123,
      "token_cache": "/home/alice/.cache/mcp-js/oauth-protected.json"
    }
  }
]

auth 中除 type 外的所有字段均为可选项。如果没有 client_id,服务将使用 OAuth 动态客户端注册;否则将使用提供的已注册客户端。scope 是请求的权限范围数组。

除环回端点外,受保护资源、授权、令牌和动态注册端点都必须使用 HTTPS。这样既允许本地 OAuth 测试服务,又能拒绝使用明文的远程授权基础设施。

首次使用时,或没有可用的缓存凭据时,mcp-v8 会启动环回回调侦听器并打印授权 URL。随后,它会尝试在本地打开该 URL。如果主机没有图形界面,请将打印出的 URL 复制到另一台计算机上的浏览器中,完成授权,并确保该浏览器能够访问主机的 http://localhost:<port>/callback URL(例如,通过 SSH 端口转发)。授权最多等待五分钟。state 与 OAuth 状态不匹配的回调会被忽略;授权被拒或超时则会导致连接失败。

省略 redirect_port 时,侦听器会选择一个可用的本地端口。仅当身份提供方要求使用已注册的回调端口时才设置此项。回调始终绑定到环回地址,并使用生成的 http://localhost:<port>/callback 重定向 URI。

凭据缓存在 token_cache 指定的位置,或默认缓存在 ${XDG_CACHE_HOME:-$HOME/.cache}/mcp-js/oauth-<server-name>.json(如果这两个缓存位置都不可用,则使用系统临时目录)。缓存与 MCP URL、权限范围和客户端配置绑定。每次初始连接或重新连接时都会解析 OAuth 凭据。若有有效的刷新令牌,解析时会续期已过期的访问令牌,而无需打开浏览器;只有缓存凭据无法提供令牌时,才会进行交互式授权。已建立的传输会一直使用其承载令牌,直到重新连接或令牌失效。它不会主动刷新已建立传输的令牌。

请将缓存视为机密:其中可能包含刷新令牌。在 Unix 上,mcp-v8 会以 0600 权限写入缓存,并拒绝符号链接、非普通文件、由其他用户拥有的文件,以及可被组或其他用户读取的文件。存在安全风险、所有者不符或使用符号链接的缓存文件绝不会被使用。这些文件会被视为不可用,因此会重新授权;授权成功后,可以安全地替换缓存。请勿提交、分享或编辑缓存。若要撤销本地访问权限,请在授权服务器上撤销授权,并删除配置的缓存文件;下次连接时会重新开始授权。

CLI 客户端(mcp-v8-cli)

使用 progenitor 根据 OpenAPI 规范生成的完全类型化 REST API 客户端:

mcp-v8 --stateless --http-port 3000 &
mcp-v8-cli exec "console.log('hello'); 1 + 1"
mcp-v8-cli exec --file ./script.js                # run a local file (uploaded as the code)
mcp-v8-cli executions get <execution_id>
mcp-v8-cli executions output <execution_id>
export MCP_V8_URL=https://my-server.example.com   # point at a remote server

Rust 客户端(mcp-v8-client)

[dependencies]
mcp-v8-client = { git = "https://github.com/r33drichards/mcp-js" }
use mcp_v8_client::Client;
let client = Client::new("http://localhost:3000");
let body = mcp_v8_client::types::ExecRequest {
    code: "1 + 1".to_string(),
    heap: None, session: None,
    heap_memory_max_mb: None, execution_timeout_secs: None, tags: None,
};
let resp = client.exec_handler(&body).await?;
println!("execution_id: {}", resp.into_inner().execution_id);

TypeScript 客户端(@mcp-v8/client)

同样根据 OpenAPI 规范生成的完全类型化 TypeScript 客户端(openapi-typescript 类型 + openapi-fetch 运行时)。位于 clients/typescript。

import { createMcpV8Client } from "@mcp-v8/client";

const client = createMcpV8Client("http://localhost:3000");
const { status, output, heap } = await client.runJs("console.log('hi'); 1 + 1");

API 更改后,使用 npm run generate 重新生成类型(读取 openapi.json)。

从源代码构建

该仓库是一个 Nix flake(它会接入预先获取的 V8 归档文件,让构建尽可能离线进行):

nix build github:r33drichards/mcp-js   # → ./result/bin/server
# or for development:
nix develop      # then: cargo build -p server

如果工具链能够构建 deno_core/V8,也可以在 server/ 中直接运行 cargo build --release。

限制

  • 不支持 setInterval——请使用带有 await 的 setTimeout 循环。
  • 没有 DOM 或浏览器 API——不存在 window/document。
  • TypeScript 只会剥离类型,不会进行类型检查——无效类型会被移除,而不会报告错误。不支持 JSX/TSX(解析时会产生清晰的错误)。

许可证

GNU AGPL-3.0。

MCP-V8 负载测试基准报告 v0.18.1

不同请求速率下的单节点与 3 节点集群对比。

结果

拓扑目标速率实际迭代数/秒HTTP 请求数/秒执行平均值(毫秒)执行 p95(毫秒)执行 p99(毫秒)成功率丢弃数最大 VU 数
cluster-stateful100/s99.9301.352.4253.46102.44100%111
cluster-stateful200/s134.53855.41359.674062.324119.07100%3450200
cluster-stateless1000/s602.21609.81377.835443.248890.8399.9%222671000
cluster-stateless100/s99.9299.851.4952.653.34100%010
cluster-stateless200/s199.8599.551.9253.4355.14100%020
cluster-stateless500/s499.61498.553.256.3363.75100%050
single-stateful100/s51.31970.11849.352081.542103.18100%2823100
single-stateful200/s46.63828.44074.714628.014673.8100%9020200
single-stateless1000/s115.4430.88174.6513854.816506.7490%526541000
single-stateless100/s99.9299.653.3155.9659.52100%414
single-stateless200/s198.2589.168.52126.81337.57100%5069
single-stateless500/s138.9348.33460.417332.0310000.899.7%21416500

P95 延迟

拓扑速率P95(毫秒)
cluster-stateful100/s53.46████████████
cluster-stateful200/s4062.32██████████████████████████
cluster-stateless100/s52.6████████████
cluster-stateless200/s53.43████████████
cluster-stateless500/s56.33█████████████
cluster-stateless1000/s5443.24███████████████████████████
single-stateful100/s2081.54████████████████████████
single-stateful200/s4628.01███████████████████████████
single-stateless100/s55.96█████████████
single-stateless200/s126.81███████████████
single-stateless500/s7332.03████████████████████████████
single-stateless1000/s13854.8██████████████████████████████

说明

  • 目标速率:配置的 constant-arrival-rate(k6 尝试发送的请求数/秒)
  • 实际迭代数/秒:实现的每秒迭代数(每次迭代 = 1 次 POST /api/exec)
  • HTTP 请求数/秒:每秒 HTTP 请求总数(每次迭代 1 次)
  • 丢弃数:因 VU 耗尽而无法调度的迭代(表明服务端已饱和)
  • 拓扑:single = 1 个 MCP-V8 节点;cluster = 3 个使用 Raft 的 MCP-V8 节点

无需重启即可注册动态 HTTP 处理程序。有关启用设置、条件更新、身份验证以及请求/响应约定,请参阅 HTTP 函数。

调度器和 HTTP 文档

Diátaxis 文档地图 链接到实验性调度器和动态 HTTP 函数的引导式教程、运维操作指南、参考文档和说明。 该地图记录了通过 #287、#293 和 #295 集成的 #284 加固工作,但不表示已合并到主分支或已部署。

可选的 DynamoDB 元数据后端

使用 --dynamodb-table TABLE --dynamodb-namespace NAME 存储共享会话历史记录、 堆标签以及文件系统标签/reflog 元数据。Sled 仍是默认后端; 快照内容仍存储在单独选择的 S3/目录后端中。有关表结构、 IAM、限制以及 LocalStack/Testcontainers 设置,请参阅 元数据后端和集成测试。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。