mcp-multi-bridge 2.3.0 → 2.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -130,7 +130,20 @@ call_tool 调用任意工具
130
130
  ```
131
131
 
132
132
  `search_tools` 的返回只给「名称 + 一句话 + 前几个参数名」,不给完整 schema——
133
- 一个完整 schema 就几百 token,一次返回 5 个等于回到全量暴露。需要细节时走 `describe_tool`。
133
+ 一个完整 schema 就几百 token,一次返回 10 个就等于回到全量暴露。需要细节时走 `describe_tool`。
134
+
135
+ **命中多个时不自动挑一个。** bridge 不知道上下文:用户说「物料」可能是查也可能是建,
136
+ 猜错会调错工具、产生副作用(误删数据是最坏情况)。所以按分数排好后交给模型选。
137
+
138
+ 返回条数默认 5,可传 `limit`,**上限 10**。上限卡在 10 是因为:
139
+ 一次返回太多,模型的选择准确率会下降,而且每条结果都占上下文。
140
+ 需要看更多时应该收窄查询词,而不是调大 limit。
141
+
142
+ 排序依据三层:
143
+
144
+ 1. 文本相关度 —— 名称命中 > 参数名命中 > 描述命中
145
+ 2. 意图加权 —— 「料号」偏向读操作,「创建料号」偏向写操作
146
+ 3. 名称字典序 —— 完全平票时的兜底,保证同样查询返回同样顺序
134
147
 
135
148
  实测 1200 个工具(6 套系统 × 200):
136
149
 
@@ -287,6 +300,54 @@ bridge 侧**不维护任何业务词对照表**。
287
300
  两种做法的取舍:拆 server 简单但要维护多套配置和凭证;分层只维护一套,
288
301
  代价是每次找工具多一跳。系统数量不多时,拆 server 更省事。
289
302
 
303
+ ### 网关侧认证(key-auth)
304
+
305
+ 桥接默认只发 `Content-Type`,不带任何认证头——业务登录 token 是作为**工具参数**
306
+ 传给后端的,不参与网关认证。所以当网关对某个端点开了 Key 认证时,
307
+ 必须让桥接额外带一个头,否则该端点会直接 401(表现为只剩本地的 `login` 工具)。
308
+
309
+ 三个来源,后者覆盖前者:
310
+
311
+ | 来源 | 作用范围 | 适合 |
312
+ | --- | --- | --- |
313
+ | `MCP_BRIDGE_HEADERS`(环境变量,JSON) | 本实例所有组织 | 一套凭证走全部环境 |
314
+ | `config.json` 顶层 `headers` | 本实例所有组织 | 同上,但想写进配置文件 |
315
+ | `orgs[].headers` | 单个组织 | 每个环境用不同凭证 |
316
+
317
+ 最省事的是写在客户端条目的 `env` 里:
318
+
319
+ ```json
320
+ {
321
+ "mcpServers": {
322
+ "mes": {
323
+ "command": "mcp-multi-bridge",
324
+ "args": ["--name", "mes"],
325
+ "env": {
326
+ "MCP_BRIDGE_HEADERS": "{\"Authorization\":\"Bearer <网关消费者凭证>\"}"
327
+ }
328
+ }
329
+ }
330
+ }
331
+ ```
332
+
333
+ 要给不同环境配不同消费者,就写进 `config.json` 的组织里(优先级更高):
334
+
335
+ ```json
336
+ {
337
+ "orgs": [
338
+ { "key": "test", "path": "/mcp-servers/mes-mcp-server" },
339
+ { "key": "prod", "path": "/mcp-servers/tc-mes-mcp-server",
340
+ "headers": { "Authorization": "Bearer <prod 的凭证>" } }
341
+ ]
342
+ }
343
+ ```
344
+
345
+ 三个来源都没配时,请求头与旧版完全一致,不影响未开认证的网关。
346
+
347
+ > 凭证是明文,别提交进仓库;`MCP_BRIDGE_HEADERS` 不是合法 JSON 时会被忽略并打一行提示,
348
+ > 不会让进程退出——但那个端点会因此 401,排查时先看这条提示。
349
+
350
+
290
351
  ## 检查安装的版本
291
352
 
292
353
  ```bash
package/bin.js CHANGED
@@ -628,7 +628,7 @@ function metaTools(items, bySystem, tenantLabel) {
628
628
  properties: {
629
629
  query: { type: 'string', description: '检索词。中英文都可以,描述你要做的事或涉及的业务对象' },
630
630
  system: { type: 'string', description: '可选,只在某套系统内搜索。留空则搜全部' },
631
- limit: { type: 'number', description: '返回条数,默认 5,最多 20' }
631
+ limit: { type: 'number', description: '返回条数,默认 5,最多 10' }
632
632
  },
633
633
  required: ['query']
634
634
  }
package/lib/higress.js CHANGED
@@ -12,13 +12,44 @@ import { orgUrl } from './config.js';
12
12
  // 自增 id,避免同毫秒并发撞号
13
13
  let rpcSeq = 0;
14
14
 
15
+ /**
16
+ * 附加到网关请求上的头
17
+ *
18
+ * 用于网关侧的消费者认证(如 key-auth 的 Authorization)。三个来源按优先级合并,
19
+ * 后者覆盖前者:
20
+ * 1. 环境变量 MCP_BRIDGE_HEADERS —— 客户端 mcp.json 的 env 里配,JSON 字符串
21
+ * 2. config.json 顶层 headers —— 对本实例所有组织生效
22
+ * 3. orgs[].headers —— 只对该组织生效,用于不同环境不同凭证
23
+ *
24
+ * 都没配时返回空对象,请求头与旧版完全一致(不改变既有行为)。
25
+ * 为什么不放在工具参数里:网关的 key-auth 只认请求头,参数是给后端业务用的。
26
+ */
27
+ export function bridgeHeaders(cfg, org) {
28
+ let fromEnv = {};
29
+ const raw = process.env.MCP_BRIDGE_HEADERS;
30
+ if (raw) {
31
+ try {
32
+ const v = JSON.parse(raw);
33
+ if (v && typeof v === 'object' && !Array.isArray(v)) fromEnv = v;
34
+ else console.error('[bridge] MCP_BRIDGE_HEADERS 必须是 JSON 对象,已忽略');
35
+ } catch (e) {
36
+ console.error('[bridge] MCP_BRIDGE_HEADERS 不是合法 JSON,已忽略');
37
+ }
38
+ }
39
+ return {
40
+ ...fromEnv,
41
+ ...((cfg && cfg.headers) || {}),
42
+ ...((org && org.headers) || {})
43
+ };
44
+ }
45
+
15
46
  /**
16
47
  * 发一个 JSON-RPC 请求到网关
17
48
  */
18
49
  export async function rpc(cfg, org, method, params) {
19
50
  const res = await fetch(orgUrl(cfg, org), {
20
51
  method: 'POST',
21
- headers: { 'Content-Type': 'application/json' },
52
+ headers: { 'Content-Type': 'application/json', ...bridgeHeaders(cfg, org) },
22
53
  body: JSON.stringify({ jsonrpc: '2.0', id: ++rpcSeq, method, params })
23
54
  });
24
55
  const text = await res.text();
package/lib/toolindex.js CHANGED
@@ -340,13 +340,20 @@ function actionBonus(query, name) {
340
340
  * 匹配依据只认三处:工具名、描述、参数名。缺中文就去补描述,
341
341
  * 不在桥接层维护一张注定对不齐的词表。
342
342
  *
343
+ * 命中多个时按分数排序取前 N 个,不自动挑一个——bridge 不知道上下文,
344
+ * 用户说「物料」可能是查也可能是建,猜错会调错工具、产生副作用。
345
+ * 选择权留给模型。
346
+ *
347
+ * 上限 10:一次返回太多,模型的选择准确率会下降,
348
+ * 而且每条结果都占上下文。需要更多时应该收窄查询词。
349
+ *
343
350
  * @param {Map} items buildIndex 返回的 items
344
351
  * @param {string} query 检索词
345
352
  * @param {{system?:string, limit?:number}} opts
346
353
  */
347
354
  export function searchTools(items, query, opts = {}) {
348
355
  const q = String(query || '').trim();
349
- const limit = Math.max(1, Math.min(50, opts.limit || 5));
356
+ const limit = Math.max(1, Math.min(10, opts.limit || 5));
350
357
  if (!q) return [];
351
358
 
352
359
  const qTokens = tokenize(q);
package/package.json CHANGED
@@ -1,34 +1,34 @@
1
- {
2
- "name": "mcp-multi-bridge",
3
- "version": "2.3.0",
4
- "description": "多后端 MCP 桥接:把网关后多个后端、多个租户的工具集合并成一个 MCP 服务,凭据由登录 CLI 提供",
5
- "type": "module",
6
- "bin": {
7
- "mcp-multi-bridge": "bin.js"
8
- },
9
- "files": [
10
- "bin.js",
11
- "lib/",
12
- "README.md"
13
- ],
14
- "engines": {
15
- "node": ">=18"
16
- },
17
- "scripts": {
18
- "start": "node bin.js",
19
- "pack:check": "npm pack --dry-run",
20
- "test": "node test/toolindex.test.mjs"
21
- },
22
- "keywords": [
23
- "mcp",
24
- "model-context-protocol",
25
- "bridge",
26
- "multi-tenant",
27
- "multi-backend",
28
- "mes"
29
- ],
30
- "license": "MIT",
31
- "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.20.2"
33
- }
34
- }
1
+ {
2
+ "name": "mcp-multi-bridge",
3
+ "version": "2.3.2",
4
+ "description": "多后端 MCP 桥接:把网关后多个后端、多个租户的工具集合并成一个 MCP 服务,凭据由登录 CLI 提供",
5
+ "type": "module",
6
+ "bin": {
7
+ "mcp-multi-bridge": "bin.js"
8
+ },
9
+ "files": [
10
+ "bin.js",
11
+ "lib/",
12
+ "README.md"
13
+ ],
14
+ "engines": {
15
+ "node": ">=18"
16
+ },
17
+ "scripts": {
18
+ "start": "node bin.js",
19
+ "pack:check": "npm pack --dry-run",
20
+ "test": "node test/toolindex.test.mjs && node test/headers.test.mjs"
21
+ },
22
+ "keywords": [
23
+ "mcp",
24
+ "model-context-protocol",
25
+ "bridge",
26
+ "multi-tenant",
27
+ "multi-backend",
28
+ "mes"
29
+ ],
30
+ "license": "MIT",
31
+ "dependencies": {
32
+ "@modelcontextprotocol/sdk": "^1.20.2"
33
+ }
34
+ }