MCP Meta
一个在JSON-RPC上运行多语言工具包的无守护进程编排器。它为LLM客户端提供了一个统一的MCP接口,同时将以任何语言编写的工具实现作为子进程进行管理。
它做什么
MCP Meta解决了一个特定的问题:如果你有用Python、Go、Node.js、Rust和Zig编写的工具,你通常需要五个单独的MCP服务器。MCP Meta允许您运行一个编排器来管理所有这些内容。
- Pod是子进程,而不是容器或网络服务
- 任何通过stdio说JSON-RPC 2.0的语言都可以是pod
- 工具定义存在于声明性YAML清单中
- 编排器在MCP会话开始时启动,在会话结束时终止
- Pod在第一次工具调用时启动(延迟生成),而不是在编排器启动时启动
- Pod可以通过编排器调用其他Pod
它不做什么
这些是有意的设计选择,而不是缺失的功能:
| 限制 | 原因 |
|---|---|
| 仅限单机 | 无需管理分布式状态 |
| 无容器支持 | 子进程模型使依赖关系最小化 |
| 无热重新加载 | 重新启动以重新加载清单 |
| 无pod池 | 每种pod类型一个实例 |
| 无持久性 | 无状态编排器 |
| Pod之间没有身份验证 | 所有Pod都相互信任 |
快速开始
# Validate manifests
./bin/mcp-meta --manifests ./examples/manifests --validate
# Run (stdio mode for Claude Desktop)
./bin/mcp-meta --manifests ./examples/manifests
# Run (SSE mode for web clients)
./bin/mcp-meta --manifests ./examples/manifests --transport sse --port 3000Claude桌面集成
{
"mcpServers": {
"meta": {
"command": "mcp-meta",
"args": ["--manifests", "/absolute/path/to/manifests"]
}
}
}配置位置:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
建筑
┌─────────────────────────────────────────────────────────────────┐
│ MCP-Meta Process │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │
│ │ Registry │ │ Router │ │ Supervisor │ │
│ │ │ │ │ │ │ │
│ │ - manifests │ │ - dispatch │ │ - spawn pods │ │
│ │ - schemas │ │ - timeout │ │ - track processes │ │
│ │ - routing │ │ - errors │ │ - multiplex stdio │ │
│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │
│ │ │ │ │
│ └────────────────┼─────────────────────┘ │
│ │ │
│ ┌─────┴─────┐ │
│ │ Handler │ │
│ └─────┬─────┘ │
└──────────────────────────┼──────────────────────────────────────┘
│ stdio/SSE (MCP protocol)
▼
LLM Client注册表加载清单并维护工具模式。路由器将工具调用分派到正确的pod。Supervisor管理pod生命周期(产卵、跟踪、关闭)。处理程序向客户端传达MCP协议。
书写工具Pod
pod是从stdin读取JSON-RPC 2.0请求并将响应写入stdout的任何程序。
去
package main
import (
"bufio"
"encoding/json"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
encoder := json.NewEncoder(os.Stdout)
for scanner.Scan() {
var req map[string]any
json.Unmarshal(scanner.Bytes(), &req)
resp := map[string]any{
"jsonrpc": "2.0",
"id": req["id"],
"result": map[string]string{"status": "ok"},
}
encoder.Encode(resp)
}
}python
import sys
import json
for line in sys.stdin:
req = json.loads(line)
resp = {"jsonrpc": "2.0", "id": req["id"], "result": {"status": "ok"}}
print(json.dumps(resp, ensure_ascii=False), flush=True)备注:使用 ensure_ascii=False 以在工具输出中保留Unicode字符(日语、表情符号等)。没有它,Python将非ASCII转义为 \uXXXX 序列。
Node.js
const readline = require("readline");
const rl = readline.createInterface({ input: process.stdin });
rl.on("line", (line) => {
const req = JSON.parse(line);
const resp = { jsonrpc: "2.0", id: req.id, result: { status: "ok" } };
console.log(JSON.stringify(resp));
});清单格式
apiVersion: mcp-meta/v1
kind: ToolPod
metadata:
name: my-tools
description: "My custom tools"
spec:
command: ["python3", "main.py"]
workdir: ./pods/my-tools
env:
LOG_LEVEL: info
callTimeout: 30s
startupTimeout: 10s
shutdownTimeout: 5s
preWarm: true # Optional: spawn at startup to reduce cold-start latency
healthCheck:
enabled: true
interval: 30s
tools:
- name: my_tool
description: "Does something useful"
inputSchema:
type: object
required: [input]
properties:
input:
type: string吊舱间通信
Pod可以使用 __mcp_meta_call__ 方法:
{
"jsonrpc": "2.0",
"id": 1,
"method": "__mcp_meta_call__",
"params": {
"tool": "other-pod.other-tool",
"args": { "key": "value" }
}
}编排器路由调用并返回结果。
笔记:
- 任何pod都可以调用任何注册的工具(没有访问限制)
- 检测到循环调用并返回错误
-32004 - 使用
pod-name.tool-name格式
工具合同(可选)
为了防止意外调用错误的工具,您可以添加合同验证:
tools:
- name: format_code
description: "Format source code"
contract:
id: "mcp-meta.formatter.format_code"
version: "1.0.0"
inputSchema:
type: object
required: [code]
properties:
code:
type: string然后,呼叫者可以验证合同:
{
"method": "__mcp_meta_call__",
"params": {
"tool": "formatter.format_code",
"args": { "code": "..." },
"expect": {
"id": "mcp-meta.formatter.format_code",
"version": "^1.0.0"
}
}
}如果合约不匹配,编排器将返回错误 -32005 而不是调用错误的工具。
版本约束:
| 约束 | 含义 |
|---|---|
1.0.0 | 完全匹配 |
^1.0.0 | 相同的主版本(1.x.x) |
~1.2.0 | 相同大小(1.2.x) |
>=1.0.0 | 至少这个版本 |
>1.0.0 | 大于此版本 |
这 expect 字段还可以包括 schema_hash 用于精确的输入模式验证。
错误代码
| 代码 | 名称 | 描述 |
|---|---|---|
| -32700 | 分析错误 | JSON无效 |
| -32600 | 无效请求 | JSON-RPC格式错误 |
| -32601 | 找不到方法 | 未知工具 |
| -32602 | 无效参数 | 架构验证失败 |
| -32603 | 内部错误 | 编排器错误 |
| -32000 | Pod错误 | Pod返回错误 |
| -32001 | Pod超时 | 呼叫超时 |
| -32002 | Pod崩溃 | Pod进程死亡 |
| -32003 | Pod生成失败 | 无法启动Pod |
| -32004 | 循环调用 | 检测到刀具间调用周期 |
| -32005 | 合同不匹配 | 合同验证失败 |
何时使用
合身:
- 您有多种语言的工具,并希望有一个统一的MCP接口
- 您希望在没有容器开销的情况下实现子流程隔离
- 比起代码,您更喜欢声明性配置
- 您正在为Claude Desktop或其他MCP客户端构建
- 你想让工具调用其他工具
考虑替代方案:
- 如果需要可视化工作流设计,请使用n8n或类似工具
- 如果您需要分布式执行,请使用带有单独MCP服务器的Kubernetes
- 如果您需要持久性或审计跟踪,请构建自定义解决方案
- 如果您的所有工具都使用一种语言,请使用该语言的本地MCP服务器
- 如果需要容器隔离,请使用基于Docker的MCP服务器
已知约束
- 冷启动延迟:第一次调用pod会生成该进程。后续调用重用它。使用
preWarm: true在启动时生成Pod的清单中。 - 错误恢复:碰撞时不会自动重启吊舱。状态API显示崩溃状态,但恢复需要客户端重试或手动干预。
- 资源使用:每个pod都是一个单独的操作系统进程。不适合100+并发Pod。
