1mcp 允许代理通过 WASM 组合 MCP 工具调用并安全地运行代码,减少高达 96% 的令牌使用量。
1mcp 将每个 MCP 工具映射到隔离的 TypeScript 存根 mcp__mcpName_toolName.ts.d,仅向 LLM 暴露 4 个核心工具。代理编写 JavaScript 代码来串联 MCP 调用,而不是单独进行 MCP 工具调用,从而显著减少令牌使用量。LLM 不再需要进行两次独立的工具调用,而是可以执行代码,1mcp 分发调用,并自动处理重试。
const me = await github.getMe();
const repos = await github.listRepos({ username: me.login });
全局安装,初始化配置并启动服务器:
npm install -g 1mcp
1mcp init
1mcp serve
服务器启动后会暴露可由你的 AI 代理使用的 MCP 工具。
@onemcp/ai-sdk 包将 AI SDK 工具转换成隔离的 MCP 表面:
import { convertTo1MCP } from '@onemcp/ai-sdk';
import { generateText } from 'ai';
import { openai } from '@ai-sdk/openai';
const tools = {
weatherTool : {
name: "getWeather",
async execute({ city, country }: { city: string; country: string }) {
return { city, weather: "晴朗", temperatureC: 23 };
},
}
};
const { client, cleanup } = await convertTo1MCP(tools, {
language: "js",
npm: { dependencies: { "axios": "^1.6.0" }},
policy: {
network: {
allowedDomains: ["api.weatherapi.com", "*.npmjs.org"]
},
filesystem: { writable: ["/tmp", "/out"] },
limits: { memMb: 256 }
},
mcps: [{
name: "external-mcp",
url: "https://weather.example.com"
}]
});
const mcpTools = await client.tools();
const result = await generateText({
model: openai('gpt-4'),
prompt: '获取巴黎,法国的天气',
tools: mcpTools
});
// 完成后清理
await cleanup();
了解更多: 查看 examples/ai-sdk-integration 获取完整示例。
代码使用 esbuild 编译为 WASM,然后在隔离的 QuickJS 运行时(每个会话)中执行。你可以选择在浏览器客户端或回退到后端执行代码,两者都具有策略强制的安全性。
run_js – 执行串联 MCP 调用的 JavaScript/TypeScript 代码每个 MCP 客户端会话都有一个虚拟文件系统(浏览器中的 OPFS 或后端的隔离文件系统)。
read – 在沙箱内获取文件内容write – 创建或修补文件并进行策略检查search – 扫描文件而不加载整个目录// 执行 1
const x = 42;
await write('/test.txt', 'hello');
// 同一会话中的执行 2
x; // ReferenceError - 变量不会在执行之间持久化
await read('/test.txt'); // 文件持久化 - 文件系统状态被维护
npm 依赖项编写代码;1mcp 使用 esbuild 和 WASM 将它们捆绑在一起,因此没有特定于提供商的 SDK(与 Cloudflare/Vercel 运行时或 Daytona 沙箱期望自己的 API 不同)。@onemcp/ai-sdk 自动将 AI SDK 工具转换为 MCP 工具 — 无需额外的胶水代码 — 因此你的代理可以在后端和浏览器之间保持相同的执行故事。中继服务器通过 SSE 将 MCP 工具代理到浏览器客户端:
import { RelayBrowserClient } from '@onemcp/ai-sdk/browser';
const client = new RelayBrowserClient('http://localhost:3000');
await client.connect();
client.onCapsule(async (capsule) => {
// 在浏览器工作者中执行胶囊并将结果发送回去
const result = await executeInWorker(capsule);
await client.sendResult(result);
});
浏览器接收签名的胶囊(捆绑代码 + 策略),在隔离的工作者中执行它们,并将结果流回 AI。
在 1mcp.config.json 中定义安全策略和 MCP 服务器:
{
"language": "js",
"npm": {
"dependencies": {},
"lockfile": ""
},
"policy": {
"network": {
"allowedDomains": ["api.github.com", "*.npmjs.org", "api.context7.com"],
"deniedDomains": [],
"denyIpLiterals": true,
"blockPrivateRanges": true,
"maxBodyBytes": 5242880,
"maxRedirects": 5
},
"filesystem": {
"readonly": ["/"],
"writable": ["/tmp", "/out"]
},
"limits": {
"timeoutMs": 60000,
"memMb": 256,
"stdoutBytes": 1048576
}
},
"mcps": [
{
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/private/tmp"]
},
{
"name": "sentry",
"transport": "http",
"endpoint": "https://mcp.sentry.dev/mcp"
},
{
"name": "context7",
"transport": "http",
"endpoint": "https://api.context7.com/mcp"
}
],
"sessionTtlMs": 300000,
"signingKeyPath": ".1mcp/keys/",
"cacheDir": ".1mcp/capsules/"
}
timeoutMs)、内存(memMb)和标准输出(stdoutBytes)。CLI 标志覆盖环境变量,环境变量覆盖配置默认值。
| 设置 | 环境变量 | CLI 标志 | 效果 |
|---|---|---|---|
| 超时 | TIMEOUT_MS | --timeout <ms> | 最大执行时间 |
| 内存 | MAX_MEMORY_MB | --max-memory <mb> | 内存上限 |
| 标准输出 | MAX_STDOUT_BYTES | --max-stdout <bytes> | 标准输出缓冲区限制 |
1mcp init [-c <path>] – 初始化配置(默认 1mcp.config.json)。1mcp serve [-c <path>] [--port <number>] [--bind <address>] [--no-ui|--open] – 启动 MCP 服务器。