mcp-router
by hccccc01333
README.md
# MCP Router
> TraeCode 只看到 5 个元工具,Router 背后可以管理数百上千个下游 MCP 工具——并保持检索亚毫秒级。
一个把自己伪装成单个 MCP Server、背后聚合任意多个下游 MCP Server 的能力路由器。它解决的是 TRAE 官方的硬限制:
> 所有 MCP Server 工具总数 ≤ 40,描述总字符 ≤ 8000。超出后按工具粒度直接丢弃。
解法**不是**"把 40 改成 400",而是 `全部工具 → 智能检索 → 动态暴露 → 只给 Agent 当前需要的工具`。
```text
✅ Build 0 errors
✅ Smoke 11/11
✅ E2E 7/7 (Windows 真实进程链路)
✅ Bench 1000 tools → ~0.6ms avg search
```
GitHub: https://github.com/hccccc01333/mcp-router
---
## 新手教程:5 分钟跑起来
### 它到底解决什么问题(打个比方)
假设你的 AI 助手能使用的"工具箱"全靠 MCP 提供:GitHub 工具箱有 30 个工具、数据库工具箱 20 个、浏览器 25 个……加起来轻轻松松超过 100 个。
但你的 AI 工具(如 TraeCode)只肯一次接收 **40 个工具**,多的会被悄悄丢掉——你经常发现"某个工具怎么死活调不到"。
这个项目就是给 AI 装了一个**"总管理员"**:
- AI 永远只面对 5 个入口,不再担心超标
- 你想用它做什么,总管理员就从背后几百个真实工具里**现搜一个最合适的**来执行
### 跟着做(三分钟)
**第 1 步:拿到代码并装好依赖**
```bash
# 进入你的工作目录
npm install
npm run build
```
**第 2 步:告诉 Router 你有哪些真实 MCP**
把仓库里的 `examples/mcp-router.config.example.json` 复制到你本地(比如就叫 `mcp-router.config.json`),把它打开,把里面 `mcpServers` 的对象替换成你**现在正在用的那批 MCP**(格式跟你在 TraeCode 里配 MCP 一模一样,直接整段拷进来即可)。密钥可以用 `${变量名}` 引用,不用明文写。
**第 3 步:把 Router 接进 TraeCode**
在 TraeCode 的 MCP 设置里添加一个 MCP Server,内容如下(把两个路径换成你电脑上真实的位置):
```json
{
"mcpServers": {
"mcp-router": {
"command": "node",
"args": [
"/绝对路径/mcp-router/dist/index.js",
"--config",
"/绝对路径/mcp-router.config.json"
]
}
}
}
```
重启 TraeCode,工具面板里会出现 `search_tools` / `execute_tool` 这几个入口——这就接好了。
**第 4 步:试一下**
让你的 AI 助手做一件事,比如:
> 用 `search_tools` 找一个能做 X 的工具,再用 `execute_tool` 调用它完成 Y。
你会看到它先"搜工具"再"调用工具",而不是像以前那样因为工具太多而犯迷糊。
> 遇到问题?看 [验证](#验证) 一节了解我们实测过的运行效果,或看 [配置](#配置) 一节了解每个参数的用途。
---
## 架构
```mermaid
flowchart LR
C["MCP 客户端<br/>(TraeCode)"] -->|只看到 5 个元工具| R["mcp-router<br/>本仓库"]
R -->|search_tools| NC["按需检索<br/>返回 Tool ID + 参数概要"]
R -->|get_tool_schema| NS["取单工具完整 schema"]
R -->|execute_tool| NE["路由到对应下游执行"]
R -->|list_servers / tool_stats| ND["托管状态 / 使用统计"]
NC --> D1[GitHub MCP]
NC --> D2[Jira MCP]
NC --> D3[PostgreSQL MCP]
NC --> D4[Unity MCP]
NC --> D5["…… 任意数量"]
```
客户端永远只拿 5 个元工具,Router 内部通过关键词检索定位真正需要的那个下游工具再执行。这就是 **Tool RAG**——不是把所有 schema 塞给模型。
---
## 为什么做
TRAE 官方明确:MCP 工具会占上下文,太多工具还会分散模型注意力。社区里反复出现:
- 单个 MCP 就有几十个工具(例如一个 Godot MCP 65 个工具)
- 配两三个 MCP 就撞上 40 上限
- 工具太多后模型难以选择
官方当前的兜底是"拆成多个小 Server 并按需启用"——Router 把这句话自动化,**顺着官方架构做事,而不是对抗它**。
---
## 怎么做
完整实现见 `src/`。几个关键模块:
- `search.ts` — 关键词评分检索,对中英文查询友好,加权匹配工具名 / Server 名 / 描述
- `downstream.ts` — 统一的 stdio / HTTP 下游代理:独立超时、失败自动重建连接、**Windows 兼容层**
- `registry.ts` — `server::tool` 命名空间隔离的全局工具目录
- `stats.ts` — 检索命中 / schema 查看 / 调用数 / 错误数统计,为自动工具选择打基础
Agent 典型调用链:`search_tools` → `get_tool_schema` → `execute_tool`。
---
## 验证
真正跑的是 **真实进程链路**(Router → `cmd /c npx` → 下游子进程 → 往返),而不是单测桩:
```text
$ npm run e2e # E2E_WAIT_ALL=1
PASS initialize handshake returns mcp-router
PASS tools/list over real stdio exposes exactly the meta-tools
PASS router warms up npx-spawned downstream on win32
PASS search finds add_numbers through spawned chain
PASS execute round-trips to child process
PASS list_servers reports connected spawned server
PASS third-party downstream aggregated into shared catalog
7 passed, 0 failed
[router] everything-4: loaded 13 tool(s)
[router] everything-1: loaded 13 tool(s)
[router] everything-2: loaded 13 tool(s)
[router] everything-3: loaded 13 tool(s)
[router] catalog ready: 54 tool(s) from 5 server(s)
```
这里还顺带验证了:**5 个真实下游聚合出 54 个工具,TraeCode 仍只见 5 个元工具**——突破了 40 上限。
`npm run smoke`(内存协议链路) 11/11 通过。
---
## Benchmark
> `scripts/bench.ts`,InMemory 真实 MCP 协议,每格 `avg / p95`,50 次运行。
| Downstream tools | TraeCode exposed | query="github" | query="postgres fetch" | query 无匹配 |
|---|---|---|---|---|
| 100 | 5 | 0.27 / 0.55 ms | 0.27 / 0.37 ms | 0.21 / 0.27 ms |
| 500 | 5 | 0.41 / 0.59 ms | 0.39 / 0.45 ms | 0.38 / 0.66 ms |
| 1000 | 5 | 0.64 / 0.86 ms | 0.65 / 0.97 ms | 0.52 / 0.63 ms |
**结论:1000 个工具时检索平均约 0.6ms、p95 不足 1ms**。工具规模翻 10 倍,延迟只从 0.27ms 涨到 0.64ms——检索成本随目录增长近乎可忽略。
---
## 一个真实的 Windows 坑
这是纯实测踩出来的。SDK 内部的 cross-spawn 解析裸命令名时在 Windows 上会失败(`'cmd.exe' is not recognized`)。解法:
```ts
// 用 ComSpec 绝对路径包装,而不是依赖 PATH 解析
return { command: comSpec(), args: ["/c", command, ...args] };
```
平台级脏细节正是通用方案和玩具的区别——任何想做同类工具的人都要重踩一遍。
---
## 快速开始
```bash
npm install
npm run build
```
把 `examples/mcp-router.config.example.json` 复制为本地配置(建议 `.gitignore`),把 `mcpServers` 换成你要聚合的所有下游 MCP。
在 TraeCode 中把它添加为一个 MCP Server:
```json
{
"mcpServers": {
"mcp-router": {
"command": "node",
"args": [
"/absolute/path/to/mcp-router/dist/index.js",
"--config",
"/absolute/path/to/mcp-router.config.json"
]
}
}
}
```
## 配置
```jsonc
{
"timeouts": { "connectMs": 30000, "callMs": 90000 },
"maxResultChars": 24000,
"mcpServers": {
"github": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"] },
"remote": { "url": "https://your-host/mcp", "headers": { "Authorization": "Bearer ${TOKEN}" } }
}
}
```
- **HTTP / stdio 双下游**:`url` 走 Streamable HTTP,`command` 走 stdio
- **环境变量展开**:`${ENV_NAME}` 从环境读取,密钥不落盘
- **独立超时 + 失败重建**、**结果截断**(应对官方"大型响应会被裁剪"的第二层限制)
## 元工具
| 工具 | 作用 |
|---|---|
| `search_tools` | 检索全部下游工具目录,返回工具卡片(ID + 参数概要) |
| `get_tool_schema` | 取单工具完整入参 schema |
| `execute_tool` | 按 ID 路由到对应下游执行 |
| `list_servers` | 查看所有托管下游 Server 及连接状态 |
| `tool_stats` | 使用统计:检索命中 / schema 查看 / 调用数 / 错误 / 最近检索 |
## 局限性(当前版本未解决)
- **语义检索**:仍是关键词评分,未做 embedding;描述相似的工具可能召回不准
- **权限 / secrets 隔离**:下游之间无权限边界
- **超大 Registry 性能**:仅在内存中线性检索,暂无索引 / 分片
- **Tool chaining planner**:没有多工具编排,单次只执行一个工具
---
## License
MITThis server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues