mcp-multi-bridge

中文文档
2.3.2发布于 2026/11/04MITES Module

多后端 MCP 桥接:把网关后多个后端、多个租户的工具集合并成一个 MCP 服务,凭据由登录 CLI 提供

原始使用文档
文档目录30 节
  1. 安装
  2. 多后端与工具列表
  3. orgKey 只能选同后端的组织
  4. 同名工具怎么合并
  5. 三个容易混淆的 name
  6. 工具很多时:按需检索
  7. 分层时模型看到什么
  8. 常驻哪些工具
  9. 客户端最终看到几个工具
  10. 聚合几十上百套 MCP 时
  11. 检索是怎么打分的
  12. 拆成多个客户端条目
  13. 网关侧认证(key-auth)
  14. 检查安装的版本
  15. 配置 MCP 客户端
  16. 方式一:npx(免安装)
  17. 方式二:全局安装(推荐)
  18. 方式三:绝对路径(最稳)
  19. 使用流程
  20. 未登录时的表现
  21. 多组织
  22. 自定义系统差异
  23. 显示效果对比
  24. 容错
  25. 配置目录与多系统并存
  26. 登录引导会带上 --home
  27. 文件依赖
  28. 提供的工具
  29. 平台支持
  30. License

mcp-multi-bridge

多后端 MCP 桥接(stdio 代理)。

把一个网关后面「多个后端 × 多个租户」的工具集,合并成一个 MCP 服务暴露给客户端; 调用时按 orgKey 选中租户,自动注入凭据后转发。

只做转发,不做登录。 没有 HTTP 服务、不监听端口、不弹浏览器。

最初为 MES 系统而写,现已与具体业务系统解耦:系统名、租户称谓、凭据字段名、 登录失效错误码、登录命令全部可配置(见自定义)。不配置时沿用 MES 的默认值。

安装

npm i -g mcp-multi-bridge mcp-multi-login

两个包配合使用:

  • mcp-multi-login 负责登录,把 token 写入本地文件(旧包 mes-login-cli 已废弃,命令名改为 mcp-multi-login)
  • mcp-multi-bridge 负责读取 token 并转发请求

从 mes-mcp-bridge 升级是破坏性的,按下面三步走

  1. 卸载旧包、装新包:

    npm rm -g mes-mcp-bridge
    npm i -g mcp-multi-bridge
    
  2. 改 mcp.json 里的 command(这一步不能省——本包只提供 mcp-multi-bridge 一个命令名,旧的 mes-mcp-bridge 不再存在):

    - "command": "mes-mcp-bridge"
    + "command": "mcp-multi-bridge"
    
  3. 重启 MCP 客户端。

配置目录与 config.json 结构不变,无需重新登录。

多后端与工具列表

config.json 里的每个组织都带一个 path,指向它在 Higress 上的 MCP 路由。 多个组织可能共享同一个 path(比如测试环境的太仓和具身智能), 它们只是登录身份不同,后台是同一个 MCP Server。

bridge 拉取工具列表的规则:

  1. 按 path 去重,同一 path 只查一次(不是按组织逐个查)
  2. 多个 path 并行查询
  3. 按工具名合并,同名是否合并看参数结构(见下)
  4. 单个 path 失败不阻断整体,能拿到多少给多少,失败的写进 login 工具的告警里

orgKey 只能选同后端的组织

这是为了避免一种必然失败的情况:工具来自 A 后端,orgKey 却指向 B 后端的组织, 请求发过去那边不认识这个工具。bridge 会在调用前校验,跨后端直接拒绝并列出可用选项。

同名工具怎么合并

不同 path 下出现同名工具时,按 inputSchema 的指纹判断:

情况处理例子
结构相同合并成一个工具,orgKey 取并集sz / tc / vn 三个 MES 环境共用一套 API
结构不同拆开,加 <系统>__ 前缀MES 的 search(rid) 与 ERP 的 search(keyword)

结构相同说明是同一套后端的不同部署环境,靠 orgKey 就能区分,加前缀反而让模型困惑。 结构不同则是真的两个工具,必须区分,否则模型会拿着 A 系统的参数去调 B 系统。

系统名从 path 末段提取并去掉 -mcp-server / -api 后缀: /mcp-servers/sz-mes-mcp-server → sz-mes,冲突时暴露为 sz-mes__search。

例外:如果一个实例只连一个后端(一套系统一个 --name),系统名直接取 --name 的值,不再从 path 推导。部署者写什么就是什么,比从 path 猜更准:

--name warehouse,path 是 /mcp-servers/erp-api
  → 系统名取 warehouse,不取 erp

因为这时 --name 和系统是一一对应的,没有歧义。多后端聚合时 --name 代表的是配置目录、下面挂着好几套系统,只能按 path 区分。

三个容易混淆的 name

名称在哪作用
--name命令行只用来算配置目录 ~/.<name>-mcp-login,不参与路由
orgs[].pathconfig.json决定调用哪个 MCP server,唯一的路由依据
mcp.json 的 key客户端配置客户端侧 server 名,工具前缀 mcp__<key>__ 来自它

--name 不决定调用哪个后端。一个 --name 可以聚合多个 path (当前 --name mes 下有 5 个 path、10 个组织),这种情况必须靠 path 区分系统。

工具很多时:按需检索

工具定义要常驻模型上下文。按中等复杂度工具约 350 tokens 估算:

工具数常驻开销能否直接用
207K✅
10035K✅ 但选择准确率开始下降
500175K⚠ 接近上限
1000350K❌ 超过多数模型整个窗口

所以工具多了不能全塞。bridge 有三种模式:

MCP_BRIDGE_TOOL_MODE=auto      默认。工具数超过 40 自动切 layered
MCP_BRIDGE_TOOL_MODE=layered   强制分层
MCP_BRIDGE_TOOL_MODE=flat      强制全量

默认 auto 而不是一直分层:工具少时分层反而多一层间接,模型要先 search_tools 才能调,纯属负担。只有当全量塞不下时才值得这个代价。

分层时模型看到什么

login                     状态查询
search_tools              按关键词检索工具(描述里带系统目录摘要)
describe_tool             看某个工具的完整参数定义
call_tool                 调用任意工具
+ 常驻的 N 个高频工具      默认 20 个

search_tools 的返回只给「名称 + 一句话 + 前几个参数名」,不给完整 schema—— 一个完整 schema 就几百 token,一次返回 10 个就等于回到全量暴露。需要细节时走 describe_tool。

命中多个时不自动挑一个。 bridge 不知道上下文:用户说「物料」可能是查也可能是建, 猜错会调错工具、产生副作用(误删数据是最坏情况)。所以按分数排好后交给模型选。

返回条数默认 5,可传 limit,上限 10。上限卡在 10 是因为: 一次返回太多,模型的选择准确率会下降,而且每条结果都占上下文。 需要看更多时应该收窄查询词,而不是调大 limit。

排序依据三层:

  1. 文本相关度 —— 名称命中 > 参数名命中 > 描述命中
  2. 意图加权 —— 「料号」偏向读操作,「创建料号」偏向写操作
  3. 名称字典序 —— 完全平票时的兜底,保证同样查询返回同样顺序

实测 1200 个工具(6 套系统 × 200):

flat    : 604 KB ≈ 177K tokens
layered :  12 KB ≈   4K tokens     降幅 98%
检索延迟: 10-40ms

常驻哪些工具

默认按组织覆盖数排序取前 N 个——被多套部署共用的工具更可能是每次都用的。 但真实频次只有日志知道,所以应该按调用统计把名单固化下来:

MCP_BRIDGE_RESIDENT_COUNT=20
MCP_BRIDGE_RESIDENT=searchRidReport,captchaGet

这两个只对分层模式生效。 工具没超过 40 个时走 flat(全量暴露), 它们会被忽略。为免误以为配置写错,这种情况会在 stderr 和 login 工具的描述里 各提示一次——login 那条是给客户端界面看的,因为多数客户端不显示 stderr。

统计方法(如果接了 Loki,request_body 里有工具名):

sum by (tool) (count_over_time({filename=~".+"} | json | line_format "{{.request_body}}" |= "tools/call" [7d]))

客户端最终看到几个工具

分层模式下是 1 + 3 + N:

组成数量能否配置
login1不能,本包提供的状态查询
search_tools / describe_tool / call_tool3不能,分层机制本身
常驻业务工具默认 20(上限 200)MCP_BRIDGE_RESIDENT_COUNT / MCP_BRIDGE_RESIDENT

所以默认是 24 个。但这是「工具数超过 40」之后才会出现的情况—— 工具少的时候走 flat,看到的就是 1 + 全部业务工具。

聚合几十上百套 MCP 时

一个 bridge 可以聚合任意多个 path。数量上去之后有两个成本要处理:

1. 全量拉取很贵

启动时要对每个后端发一次 tools/list。实测(单后端 30ms 延迟):

后端数首次拉取
5约 1 秒
50约 6 秒
200约 20 秒

所以工具清单按 TTL 缓存,默认 5 分钟:

MCP_BRIDGE_TOOLS_TTL_MS=300000

缓存期必须远大于拉取耗时,否则客户端每次刷新都要重来一遍——实测 200 个后端时, 缓存让重复的 tools/list 从 19 秒降到 0.1 秒。

新增的工具怎么被发现? 不需要把 TTL 调小。tools/call 进来时如果索引里 查不到该工具,会自动强制刷新一次再判断。所以「网关刚加了工具、模型马上要用」 这个场景是通的,代价只有那一次调用多花一轮拉取。

2. 并发要限

不设上限时 200 个后端会在同一瞬间建立 200 个连接,网关和本地 socket 都吃不住, 而且失败会一起失败。

MCP_BRIDGE_FETCH_CONCURRENCY=16

默认 16。实测 200 个后端下,8 并发约 28 秒、16 并发约 18 秒,再往上收益不明显 (压测环境是单进程 mock,序列化大 JSON 会成为新瓶颈,真实网关下最优值可能不同)。

检索是怎么打分的

不是向量检索,是加权关键词命中。1000 个工具用倒排就够,上 embedding 反而多一个服务要维护。

匹配依据只有三处:工具名、描述、参数名。全部来自工具定义本身, bridge 侧不维护任何业务词对照表。

早期版本内置过一份约 30 条的「料号 → material/item」别名表,后来删掉了,因为实测有两个问题:

问题说明
对写全中文描述的工具零贡献真实 MES 的描述里本来就有「料号、批次、仓库、库位」,别名表一条都没用上
会误匹配「料号」被映射到 item,而别的系统里 item 可能是电商商品,queryItem 就被错误命中

所以规则很简单:工具名或描述里有这个词,就能搜到;没有就搜不到。 这是可预期的,也不会出现「bridge 猜错了领域」这种难以排查的情况。

新增工具不需要改代码:

新增 queryCustomsDeclaration,描述「查询报关单」
  「报关单」→ 命中(中文来自 description)
  「customs」→ 命中(英文来自 name)
  「declNo」→ 命中(参数名)

搜不到时,问题在工具定义,不在 bridge。正确的修法是在网关侧补描述:

❌ doZzz / "Process ZZZ"           「质量追溯」搜不到
✅ doZzz / "质量追溯 · Process ZZZ"  「质量追溯」直接命中

描述里带上用户可能说的中文说法(含同义词),比维护一份注定对不齐的词表更省事, 也不会漏掉长尾——业务词根本不可能靠人工枚举穷尽。

2. 意图分级。业务 API 的工具名几乎都是 queryXxx / createXxx / updateXxx / deleteXxx 四件套,光看业务对象四个分数完全一样。用户说「料号」时想要的是查不是创建, 所以按动作词加权重:

「料号」    → queryMaterial    只说业务对象,偏向读操作
「创建物料」 → createMaterial   明说动作,导向写操作
「导出物料」 → exportMaterial   导出和查询都是读,靠动作词再分一层

只想业务对象时不会优先给出「删除批次」这类写操作——读操作选错代价小,写操作有数据风险。

拆成多个客户端条目

另一种办法是不分层,而是用环境变量限定本实例负责的 path:

{
  "mcpServers": {
    "mes-test": {
      "command": "mcp-multi-bridge",
      "args": ["--name", "mes-test"],
      "env": { "MCP_BRIDGE_PATHS": "mes-mcp-server" }
    },
    "mes-prod": {
      "command": "mcp-multi-bridge",
      "args": ["--name", "mes-prod"],
      "env": { "MCP_BRIDGE_PATHS": "tc-mes-mcp-server" }
    }
  }
}

MCP_BRIDGE_PATHS 用逗号分隔,可以写完整 path(/mcp-servers/xxx), 也可以只写末段(xxx),两种都识别。旧名 MES_MCP_PATHS 仍兼容。

两种做法的取舍:拆 server 简单但要维护多套配置和凭证;分层只维护一套, 代价是每次找工具多一跳。系统数量不多时,拆 server 更省事。

网关侧认证(key-auth)

桥接默认只发 Content-Type,不带任何认证头——业务登录 token 是作为工具参数 传给后端的,不参与网关认证。所以当网关对某个端点开了 Key 认证时, 必须让桥接额外带一个头,否则该端点会直接 401(表现为只剩本地的 login 工具)。

三个来源,后者覆盖前者:

来源作用范围适合
MCP_BRIDGE_HEADERS(环境变量,JSON)本实例所有组织一套凭证走全部环境
config.json 顶层 headers本实例所有组织同上,但想写进配置文件
orgs[].headers单个组织每个环境用不同凭证

最省事的是写在客户端条目的 env 里:

{
  "mcpServers": {
    "mes": {
      "command": "mcp-multi-bridge",
      "args": ["--name", "mes"],
      "env": {
        "MCP_BRIDGE_HEADERS": "{\"Authorization\":\"Bearer <网关消费者凭证>\"}"
      }
    }
  }
}

要给不同环境配不同消费者,就写进 config.json 的组织里(优先级更高):

{
  "orgs": [
    { "key": "test", "path": "/mcp-servers/mes-mcp-server" },
    { "key": "prod", "path": "/mcp-servers/tc-mes-mcp-server",
      "headers": { "Authorization": "Bearer <prod 的凭证>" } }
  ]
}

三个来源都没配时,请求头与旧版完全一致,不影响未开认证的网关。

凭证是明文,别提交进仓库;MCP_BRIDGE_HEADERS 不是合法 JSON 时会被忽略并打一行提示, 不会让进程退出——但那个端点会因此 401,排查时先看这条提示。

检查安装的版本

mcp-multi-bridge --version     # 只输出版本号,如 1.4.0
mcp-multi-bridge --status      # 版本 + 安装位置 + 网关地址 + 后端分组 + 各组织登录状态
mcp-multi-bridge --help        # 帮助

--version 只输出纯版本号,方便脚本取值:

mcp-multi-bridge --version | xargs echo "当前版本:"

如果怀疑跑的不是自己想跑的那份(比如同时存在 npm link 的软链和全局安装), 用 --status 看「安装位置」即可确认。

mcp-multi-login 同样支持 --version。

配置 MCP 客户端

任选其一。

方式一:npx(免安装)

{
  "mcpServers": {
    "mes": {
      "command": "npx",
      "args": ["-y", "mcp-multi-bridge"]
    }
  }
}

方式二:全局安装(推荐)

npm i -g mcp-multi-bridge
{
  "mcpServers": {
    "mes": {
      "command": "mcp-multi-bridge",
      "args": []
    }
  }
}

全局安装的好处是升级可控:npx 只跳过安装确认,不会因为发布了新版本就刷新本地缓存。

方式三:绝对路径(最稳)

如果客户端启动子进程时找不到命令(ENOENT),直接用 node 加绝对路径:

{
  "mcpServers": {
    "mes": {
      "command": "node",
      "args": ["C:/Users/你的用户名/AppData/Roaming/npm/node_modules/mcp-multi-bridge/bin.js"]
    }
  }
}

实际路径用这条命令查:

npm root -g

使用流程

  1. 首次使用,或 token 过期时,执行登录:

    mcp-multi-login
    
  2. 在打开的登录页里完成账号密码和图形验证码

  3. 回到 MCP 客户端,直接调用工具即可

登录后无需重启客户端。 bridge 每次调用都重新读取 token 文件,所以登录结果立即生效。

未登录时的表现

工具调用会返回明确的引导文案,说明该执行 mcp-multi-login 以及要等人工完成验证码。模型拿到这段文字后可以自行发起登录。

多组织

登录页支持切换组织,每个组织单独保存 token,互不覆盖。

调用工具时可以指定组织:

{ "orgKey": "tc" }

orgKey 的取值就是 config.json 里各组织的 key,不传则用最后一次登录的组织。

自定义系统差异

合并、路由、凭据注入这套逻辑与具体业务系统无关,真正随系统变化的是六件事。 全部在 config.json 里配置,都不写则沿用 MES 的默认值,升级后行为不变。

{
  "systemName": "ERP 中台",
  "tenantLabel": "租户",
  "credentialField": "authToken",
  "tenantIdField": "tenantId",
  "hiddenArgs": ["authToken", "tenantId"],
  "invalidCodes": [401, 403],
  "invalidCodeReasons": { "401": "未授权,请重新登录" },
  "loginCommand": "erp-login"
}
字段默认值作用
systemNameMES系统名,出现在登录引导与状态标题里
tenantLabel组织租户称谓,出现在 orgKey 参数说明、状态清单与各类提示里
credentialFieldaccess_token注入到工具参数里的凭据字段名,必须与网关 requestTemplate 取值的字段一致
tenantIdFieldorgId注入租户 ID 时用的参数名,取值来自配置的 orgs[].orgId
hiddenArgs跟随上面两个字段对模型隐藏的参数。凭据与租户 ID 由本层填,露给模型只会引发「我该填什么」
invalidCodes[613,614,615,616]视为「登录失效」的业务错误码,命中后返回重新登录引导
invalidCodeReasonsMES 的四个码错误码说明,与默认值合并,只写要覆盖的项
loginCommandmcp-multi-login登录引导里让模型执行的命令名

租户 ID 由本层注入,不让模型填。 网关的工具模板通常是 {{if .args.orgId}}{{.args.orgId}}{{else}}1{{end}} —— 不传就一律按 1 查, 同一个后端下的其他租户会静默查到错误组织的数据。所以本层总是把 orgs[].orgId 注入进去,客户端传的同名字段会被覆盖。

显示效果对比

默认上面那份配置
工具描述查询 MES 的组织与登录状态查询 ERP 中台的租户与登录状态
参数说明要操作的组织标识要操作的租户标识
状态标题## MES 组织状态## ERP 中台租户状态
更新提示该组织尚未登录该租户尚未登录
引导命令mcp-multi-login --org tcerp-login --org tc

orgKey 这个参数名不会变——它是路由用的标识,改文案不影响调用方代码。

容错

所有字段都做了类型校验,配错(null、空串、非数组、非数字)时静默回落默认值, 不会让服务起不来。systemName 以汉字结尾时不加空格(「查询 ERP 中台的租户」), 以拉丁字母结尾时加(「查询 MES 的组织」)。

配置目录与多系统并存

默认目录 ~/.mes-mcp-login,不设环境变量就用它。现有用户升级后行为不变。

目录名带 mes 是历史沿革:mcp-multi-login 的默认值也是它,两边必须一致, 否则登录完桥接层找不到 token。要改名得两个包一起改。

同一个客户端接多套系统时,每个 bridge 实例指向不同目录:

{
  "mcpServers": {
    "mes": {
      "command": "mcp-multi-bridge",
      "args": [],
      "env": { "MCP_MULTI_HOME": "C:/Users/你/.mes-mcp-login" }
    },
    "erp": {
      "command": "mcp-multi-bridge",
      "args": [],
      "env": { "MCP_MULTI_HOME": "C:/Users/你/.erp-login" }
    }
  }
}

工具名由客户端加前缀区分(mcp__mes__captchaGet / mcp__erp__captchaGet),同名工具不冲突。

环境变量作用默认
MCP_MULTI_HOME配置目录~/.mes-mcp-login
MCP_BRIDGE_HOME同上(旧名,仍兼容)—
MCP_BRIDGE_PATHS限定本实例负责的 path,逗号分隔不限制(全部加载)

MCP_MULTI_HOME 优先于 MCP_BRIDGE_HOME;MCP_BRIDGE_PATHS 优先于旧名 MES_MCP_PATHS。

登录引导会带上 --home

未登录或登录失效时,本服务返回的引导命令是完整可执行的:

mcp-multi-login --home "C:/Users/你/.mes-mcp-login" --org tc

--home 指向本实例实际读取的目录,不能省——省了就会写到默认目录去, 表现是「登录成功了但这边还是未登录」,非常难查。

默认用 mcp-multi-login。若你换成了别的登录程序(比如自研的 erp-login), 用 loginCommand 改:

{ "loginCommand": "erp-login" }

登录包只提供 mcp-multi-login 一个命令,没有 mes-login 别名。 从旧包升级的,务必确认 loginCommand 没被配成旧名。

文件依赖

读取配置目录下的两个文件:

文件由谁创建
config.json登录侧 CLI(mcp-multi-login),也可手写
token.json登录侧 CLI(登录时写入)

本包只读不写,不会创建、修改或删除这两个文件。

所以使用前必须先安装并运行一次登录 CLI(mcp-multi-login)。

提供的工具

工具列表由网关返回,本包原样透传。login 会被本包替换成本地状态查询工具。 分层模式下还会额外提供 search_tools / describe_tool / call_tool 三个元工具, 用于按需发现工具,避免把上千个定义全塞进上下文。

工具本身(有哪些、叫什么、什么参数)完全取决于网关侧配置,本包不做增删。 当前 MES 网关提供的是:

  • login 登录态查询(本包接管)
  • captchaGet 获取验证码
  • captchaCheck 校验验证码
  • searchRidReport RID 明细报表

平台支持

Windows / macOS / Linux。需要 Node.js >= 18。

License

MIT

版本与发布记录

mcp-multi-bridge 共发布 11 个版本,首次发布于 2026/10/28;过去 12 个月发布了 11 个版本。

版本发布日期距今
2.3.2latest2026/11/04今天
2.3.12026/11/022 天前
2.3.02026/11/022 天前
2.2.02026/10/296 天前
2.1.42026/10/296 天前
2.1.32026/10/296 天前

关于 mcp-multi-bridge 的常见问题

mcp-multi-bridge 是什么?

多后端 MCP 桥接:把网关后多个后端、多个租户的工具集合并成一个 MCP 服务,凭据由登录 CLI 提供

如何安装 mcp-multi-bridge?

在项目目录运行 npm install mcp-multi-bridge,或使用 pnpm add / yarn add / bun add。它还提供命令行工具 mcp-multi-bridge,可以用 npx mcp-multi-bridge 直接运行。

mcp-multi-bridge 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/mcp-multi-bridge 是否存在。

mcp-multi-bridge 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

mcp-multi-bridge 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=18。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

mcp-multi-bridge 可以商用吗?

mcp-multi-bridge 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

mcp-multi-bridge 还在维护吗?

最新版本 2.3.2 发布于 2026/11/04(今天);至今共发布 11 个版本,其中过去 12 个月发布了 11 个;首次发布于 2026/10/28。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。