mcp-multi-bridge 2.1.3 → 2.1.4
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/bin.js +28 -3
- package/lib/settings.js +13 -1
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -221,10 +221,15 @@ function textResult(text, isError = false) {
|
|
|
221
221
|
*
|
|
222
222
|
* 这段文字是给模型看的指令:告诉它当前登录态不可用,以及该执行什么命令。
|
|
223
223
|
* 之所以写这么具体,是因为模型拿不到本文件的上下文,
|
|
224
|
-
*
|
|
224
|
+
* 只说「请登录」它不知道登录入口在哪、也不知道要等待人机操作。
|
|
225
|
+
*
|
|
226
|
+
* 注意:这里**不描述登录页上有什么**。验证码、密码策略、二次验证之类的差异
|
|
227
|
+
* 属于登录包和页面的事(由 protocol.adapter 与页面自己决定),而且页面本身
|
|
228
|
+
* 就有提示。桥接层写死「需要图形验证码」会让无验证码的系统(如 EBS-Plus)
|
|
229
|
+
* 收到错误指令,模型据此让人去点一个根本不存在的验证码。
|
|
225
230
|
*
|
|
226
231
|
* 命令里必须带 --home:同一个客户端可能同时接多套系统,各自一个配置目录。
|
|
227
|
-
* 只说 `
|
|
232
|
+
* 只说 `mcp-multi-login` 会让模型登到另一套系统去,那边看起来成功了、
|
|
228
233
|
* 这边的 token 却没变,表现是「登录了但还是未登录」,非常难查。
|
|
229
234
|
*
|
|
230
235
|
* @param {string} status 状态描述,如「未登录」/「登录已失效(code=613:token 已过期)」
|
|
@@ -253,7 +258,7 @@ ${L.loginCommand}${homeArg}${orgArg}
|
|
|
253
258
|
|
|
254
259
|
执行说明:
|
|
255
260
|
1. 该命令会启动一个临时登录页并在浏览器中打开
|
|
256
|
-
2.
|
|
261
|
+
2. 在页面上完成登录。需要填什么(账号密码、图形验证码等)以页面本身的提示为准,由人操作,AI 无法代替
|
|
257
262
|
3. 登录成功后 token 会自动写入本地文件,本服务**下一次调用即可生效,无需重启**
|
|
258
263
|
4. 命令会一直运行到登录完成才退出,**请以后台方式运行**(run_in_background),避免阻塞
|
|
259
264
|
5. \`--home\` 不能省:本服务读的是 \`${CONFIG_DIR}\`,命令指向别的目录会写错位置
|
|
@@ -642,6 +647,12 @@ async function main() {
|
|
|
642
647
|
});
|
|
643
648
|
|
|
644
649
|
const payload = extractPayload(result);
|
|
650
|
+
|
|
651
|
+
// 失效判定有两个维度:
|
|
652
|
+
// invalidCodes 业务码,绝大多数系统走这条(HTTP 200 + code)
|
|
653
|
+
// invalidHttpStatus 响应体里的 status 字段,给那些把认证失败兜成 HTTP 错误的系统用
|
|
654
|
+
// 两者字段不重叠:业务响应用 code,框架默认错误页用 status,
|
|
655
|
+
// 所以简单的 or 关系不会互相误伤。
|
|
645
656
|
if (payload && S.invalidCodes.includes(payload.code)) {
|
|
646
657
|
const why = S.invalidReasons[payload.code] || payload.message || '凭据不可用';
|
|
647
658
|
console.error(`[bridge] ${S.tenantLabel} ${org.key} 的凭据不可用(code=${payload.code})`);
|
|
@@ -650,6 +661,20 @@ async function main() {
|
|
|
650
661
|
true
|
|
651
662
|
);
|
|
652
663
|
}
|
|
664
|
+
if (payload && S.invalidHttpStatus.includes(payload.status)) {
|
|
665
|
+
const why = S.invalidReasons[payload.status] || 'HTTP ' + payload.status;
|
|
666
|
+
console.error(
|
|
667
|
+
`[bridge] ${S.tenantLabel} ${org.key} 的凭据不可用(HTTP ${payload.status})`
|
|
668
|
+
);
|
|
669
|
+
return textResult(
|
|
670
|
+
loginGuide(
|
|
671
|
+
`${S.systemName}${S.nameGap}登录已失效(HTTP ${payload.status}:${why})`,
|
|
672
|
+
org,
|
|
673
|
+
cfg
|
|
674
|
+
),
|
|
675
|
+
true
|
|
676
|
+
);
|
|
677
|
+
}
|
|
653
678
|
|
|
654
679
|
// 正常结果:附一条组织说明,让模型知道这份数据属于哪个组织
|
|
655
680
|
const L = S;
|
package/lib/settings.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* credentialField 注入到工具参数里的凭据字段名 默认 access_token
|
|
10
10
|
* hiddenArgs 对模型隐藏的参数(凭据与租户 ID 由本层填) 默认 access_token / orgId
|
|
11
11
|
* invalidCodes 表示登录态失效的业务错误码 默认 613/614/615/616
|
|
12
|
+
* invalidHttpStatus 表示登录态失效的 HTTP 状态码 默认空(不启用)
|
|
12
13
|
* loginCommand 登录引导里让模型执行的命令 默认 mcp-multi-login
|
|
13
14
|
*
|
|
14
15
|
* 全部有默认值,不配置时行为与改造前完全一致。
|
|
@@ -27,6 +28,16 @@ export const DEFAULT_TENANT_ID_FIELD = 'orgId';
|
|
|
27
28
|
export const DEFAULT_HIDDEN_ARGS = [DEFAULT_CREDENTIAL_FIELD, DEFAULT_TENANT_ID_FIELD];
|
|
28
29
|
/** 默认的登录失效错误码 */
|
|
29
30
|
export const DEFAULT_INVALID_CODES = [613, 614, 615, 616];
|
|
31
|
+
/**
|
|
32
|
+
* 默认的登录失效 HTTP 状态码
|
|
33
|
+
*
|
|
34
|
+
* 默认空数组——大多数系统(如 MES)认证失败也返回 HTTP 200 + 业务码,
|
|
35
|
+
* 靠 invalidCodes 判定就够了。默认开某个状态码会误伤正常的业务异常。
|
|
36
|
+
*
|
|
37
|
+
* 只有明确知道「某状态码在此系统上等价于认证失败」时才配。
|
|
38
|
+
* 典型场景:EBS-Plus 的网关把认证失败兜成了 500,拿不到业务码。
|
|
39
|
+
*/
|
|
40
|
+
export const DEFAULT_INVALID_HTTP_STATUS = [];
|
|
30
41
|
/**
|
|
31
42
|
* 默认登录命令
|
|
32
43
|
*
|
|
@@ -92,7 +103,7 @@ function reasonMap(v) {
|
|
|
92
103
|
* @returns {{
|
|
93
104
|
* systemName:string, tenantLabel:string, nameGap:string,
|
|
94
105
|
* credentialField:string, hiddenArgs:string[],
|
|
95
|
-
* invalidCodes:number[], invalidReasons:Record<number,string>,
|
|
106
|
+
* invalidCodes:number[], invalidHttpStatus:number[], invalidReasons:Record<number,string>,
|
|
96
107
|
* loginCommand:string
|
|
97
108
|
* }}
|
|
98
109
|
*/
|
|
@@ -119,6 +130,7 @@ export function settings(cfg) {
|
|
|
119
130
|
tenantIdField,
|
|
120
131
|
hiddenArgs,
|
|
121
132
|
invalidCodes: codeList(cfg?.invalidCodes, DEFAULT_INVALID_CODES),
|
|
133
|
+
invalidHttpStatus: codeList(cfg?.invalidHttpStatus, DEFAULT_INVALID_HTTP_STATUS),
|
|
122
134
|
invalidReasons: reasonMap(cfg?.invalidCodeReasons),
|
|
123
135
|
loginCommand: isNonEmptyString(cfg?.loginCommand) ? cfg.loginCommand.trim() : DEFAULT_LOGIN_COMMAND
|
|
124
136
|
};
|