将多个MCP工具调用批处理到一个“batch_execute”请求中——减少AI代理的开销和令牌使用。
</div>⚠️ 通知:正在进行的工作
此项目正在积极开发以解决几个复杂挑战:
- 维持与现有MCP服务器的向后兼容性
- 解决多连接客户端(Cline、Roo、Claude Desktop)的传输复杂性
- 创建易于初学者使用的实现
虽然功能正常,但预计会不断改进和变化,因为我们优化解决方案。
MCP BatchIt 是 模型上下文协议 (MCP) 生态系统中的一个简单聚合器服务器。它只暴露一个工具:batch_execute。你可以将多个MCP工具(如 fetch、read_file、create_directory、write_file 等)的调用从单独的消息中合并到一个聚合器请求中。
这大大减少了令牌使用、网络开销以及在你的AI代理或LLM对话中的重复上下文。
每个消息一个动作问题: 通常,一个LLM或AI代理一次只能调用一个MCP工具,对于多步任务需要多次调用。
过多的往返次数: 10个独立的文件操作可能需要10条消息 → 10个响应。
BatchIt的方法:
batch_execute 请求。maxConcurrent。stopOnError 为真,则停止新的子操作。单一“批执行”工具
并行执行
maxConcurrent 控制。超时与错误停止
timeoutMs 进行竞争,如果一个失败,可以跳过剩余的操作。连接缓存
git clone https://github.com/ryanjoachim/mcp-batchit.git
cd mcp-batchit
npm install
npm run build
npm start
BatchIt 默认在 STDIO 上启动,因此你的AI代理(或任何MCP客户端)可以启动它。例如:
mcp-batchit 正在 stdio 上运行。准备好批量执行!
你现在可以向它发送 JSON-RPC 请求(tools/call 方法,name= "batch_execute")。
使用 Cline/Roo 代码,你可以通过利用 Nick Baumann 开发的强大“内存银行”自定义指令来构建上下文项目文档框架。
总计:约19次独立API调用(13次操作 + 6次响应等待)
当处理依赖实时输出的复杂多步任务(如读取文件和生成文档)时,你需要按不同阶段处理过程。这是因为 BatchIt 不支持同一请求内的子操作间的数据传递。
在这个初始阶段,我们通过读取必要的文件(如 package.json、README.md)从文件系统收集信息。这是通过一个对文件系统MCP服务器的 batch_execute 调用来完成的:
{
"targetServer": {
"name": "filesystem",
"serverType": {
"type": "filesystem",
"config": {
"rootDirectory": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit"
}
},
"transport": {
"type": "stdio",
"command": "cmd.exe",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit"
]
}
},
"operations": [
{
"tool": "read_file",
"arguments": {
"path": "C:/Users/_Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/package.json"
}
},
{
"tool": "read_file",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/README.md"
}
}
],
"options": {
"maxConcurrent": 2,
"stopOnError": true,
"timeoutMs": 30000
}
}
注意:聚合器启动 @modelcontextprotocol/server-filesystem(通过 npx)来执行并行的 read_file 操作。
此阶段涉及聚合器之外的处理,通常使用LLM或AI代理的能力:
<list_code_definition_names>
<path>src</path>
</list_code_definition_names>
此步骤使用Roo Code的 list_code_definition_names 工具,该工具仅对LLM可用。然而,请注意许多MCP服务器可以提供类似的功能,使得可以在不进行LLM请求的情况下完成此过程。
最终阶段结合了先前步骤的数据(文件内容和代码定义)来生成 memory-bank 目录中的文档:
{
"targetServer": {
"name": "filesystem",
"serverType": {
"type": "filesystem",
"config": {
"rootDirectory": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit"
}
},
"transport": {
"type": "stdio",
"command": "cmd.exe",
"args": [
"/c",
"npx",
"-y",
"@modelcontextprotocol/server-filesystem",
"C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit"
]
}
},
"operations": [
{
"tool": "create_directory",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/memory-bank"
}
},
{
"tool": "write_file",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/memory-bank/productContext.md",
"content": "# MCP BatchIt 产品上下文\\n\\n## 目的\\n..."
}
},
{
"tool": "write_file",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/memory-bank/systemPatterns.md",
"content": "# MCP BatchIt 系统模式\\n\\n## 架构概述\\n..."
}
},
{
"tool": "write_file",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/memory-bank/techContext.md",
"content": "# MCP BatchIt 技术上下文\\n\\n## 技术栈\\n..."
}
},
{
"tool": "write_file",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/memory-bank/progress.md",
"content": "# MCP BatchIt 进展状态\\n\\n## 已完成功能\\n..."
}
},
{
"tool": "write_file",
"arguments": {
"path": "C:/Users/Chewy/Documents/GitHub/ryanjoachim/mcp-batchit/memory-bank/activeContext.md",
"content": "# MCP BatchIt 当前上下文\\n\\n## 当前状态\\n..."
}
}
],
"options": {
"maxConcurrent": 1,
"stopOnError": true,
"timeoutMs": 30000
}
}
聚合器按顺序处理这些操作(maxConcurrent=1),创建目录并写入多个文档文件。结果数组指示每个操作的成功/失败状态。
Q1: 如果子操作 #2 依赖于子操作 #1 的结果,我是否需要多次聚合器调用? 是的。 BatchIt 不会在同一请求内传递数据。你需要进行多阶段调用(如上面的例子)。
Q2: 为什么有时我会得到“未找到工具 create_directory”的错误?
因为你的 transport 可能指向的是聚合器脚本本身而不是真正的MCP服务器。确保你引用的是像 @modelcontextprotocol/server-filesystem 这样的东西。
Q3: 我可以同时使用并发和 stopOnError 吗? 当然可以。如果一个子操作失败,我们将跳过启动新的子操作。已经运行的子操作将继续并行完成。
Q4: BatchIt 是否每次都会重新启动目标服务器?
如果指定了 keepAlive: false,它可以重新启动。但如果使用相同的 targetServer.name + transport,它会缓存连接直到空闲超时。
Q5: 如果中间发生错误,会返回部分结果吗?
是的。每个在错误之前完成的子操作都将包含在最终聚合器响应中,包括失败的子操作。如果 stopOnError 为真,剩余的子操作将被跳过。
MIT