dominds 1.19.2 → 1.19.3
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/dist/cli/team-definition-audit.d.ts +2 -1
- package/dist/cli/team-definition-audit.js +20 -8
- package/dist/cli/validate-team-def.js +3 -3
- package/dist/docs/mcp-support.md +11 -0
- package/dist/docs/mcp-support.zh.md +7 -0
- package/dist/docs/team_mgmt-toolset.md +5 -2
- package/dist/docs/team_mgmt-toolset.zh.md +4 -2
- package/dist/docs/tool-availability-protocol.md +4 -2
- package/dist/mcp/config.d.ts +1 -0
- package/dist/mcp/config.js +16 -0
- package/dist/mcp/supervisor.d.ts +7 -1
- package/dist/mcp/supervisor.js +298 -16
- package/dist/minds/load.js +5 -0
- package/dist/minds/system-prompt.d.ts +1 -0
- package/dist/minds/system-prompt.js +14 -6
- package/dist/tools/builtins.js +2 -0
- package/dist/tools/env.js +10 -58
- package/dist/tools/manual/render.js +4 -0
- package/dist/tools/mcp.d.ts +1 -0
- package/dist/tools/mcp.js +55 -5
- package/dist/tools/prompts/mcp_admin/en/errors.md +0 -14
- package/dist/tools/prompts/mcp_admin/en/index.md +5 -3
- package/dist/tools/prompts/mcp_admin/en/principles.md +11 -5
- package/dist/tools/prompts/mcp_admin/en/scenarios.md +19 -3
- package/dist/tools/prompts/mcp_admin/en/tools.md +85 -21
- package/dist/tools/prompts/mcp_admin/zh/errors.md +0 -14
- package/dist/tools/prompts/mcp_admin/zh/index.md +5 -3
- package/dist/tools/prompts/mcp_admin/zh/principles.md +11 -5
- package/dist/tools/prompts/mcp_admin/zh/scenarios.md +19 -3
- package/dist/tools/prompts/mcp_admin/zh/tools.md +85 -21
- package/dist/tools/prompts/os/en/errors.md +0 -28
- package/dist/tools/prompts/os/en/scenarios.md +1 -1
- package/dist/tools/prompts/os/en/tools.md +8 -17
- package/dist/tools/prompts/os/zh/errors.md +0 -28
- package/dist/tools/prompts/os/zh/scenarios.md +1 -1
- package/dist/tools/prompts/os/zh/tools.md +8 -17
- package/dist/tools/registry.d.ts +5 -0
- package/dist/tools/team_mgmt-mcp-manual.d.ts +2 -2
- package/dist/tools/team_mgmt-mcp-manual.js +57 -16
- package/dist/tools/team_mgmt.js +4 -4
- package/package.json +3 -3
- package/webapp/dist/assets/{_basePickBy-B7M9Q0Fa.js → _basePickBy-Dnh413xT.js} +3 -3
- package/webapp/dist/assets/_basePickBy-Dnh413xT.js.map +1 -0
- package/webapp/dist/assets/{_baseUniq-DAeYoL6j.js → _baseUniq-DWzYqpN_.js} +2 -2
- package/webapp/dist/assets/_baseUniq-DWzYqpN_.js.map +1 -0
- package/webapp/dist/assets/{arc-Bh4nDbNR.js → arc-vfBkNCOx.js} +2 -2
- package/webapp/dist/assets/arc-vfBkNCOx.js.map +1 -0
- package/webapp/dist/assets/{architectureDiagram-2XIMDMQ5-CxqmdsIm.js → architectureDiagram-VXUJARFQ-DiUEBXOa.js} +8 -26
- package/webapp/dist/assets/architectureDiagram-VXUJARFQ-DiUEBXOa.js.map +1 -0
- package/webapp/dist/assets/{blockDiagram-WCTKOSBZ-CxIWLtpt.js → blockDiagram-VD42YOAC-BqK1KM2m.js} +170 -187
- package/webapp/dist/assets/blockDiagram-VD42YOAC-BqK1KM2m.js.map +1 -0
- package/webapp/dist/assets/{c4Diagram-IC4MRINW-1qErOIgG.js → c4Diagram-YG6GDRKO-ClHNu1Uo.js} +4 -4
- package/webapp/dist/assets/c4Diagram-YG6GDRKO-ClHNu1Uo.js.map +1 -0
- package/webapp/dist/assets/{channel-DkgZHNUe.js → channel-BbWLVc8W.js} +2 -2
- package/webapp/dist/assets/channel-BbWLVc8W.js.map +1 -0
- package/webapp/dist/assets/{chunk-4BX2VUAB-BmdMbU9v.js → chunk-4BX2VUAB-CItdSmZH.js} +2 -2
- package/webapp/dist/assets/chunk-4BX2VUAB-CItdSmZH.js.map +1 -0
- package/webapp/dist/assets/{chunk-55IACEB6-D6LDTDBy.js → chunk-55IACEB6-DSCX9WCf.js} +2 -2
- package/webapp/dist/assets/chunk-55IACEB6-DSCX9WCf.js.map +1 -0
- package/webapp/dist/assets/{chunk-WL4C6EOR-B-Pk44be.js → chunk-B4BG7PRW-5CRXFeD9.js} +121 -171
- package/webapp/dist/assets/chunk-B4BG7PRW-5CRXFeD9.js.map +1 -0
- package/webapp/dist/assets/{chunk-NQ4KR5QH-wlvxalE3.js → chunk-DI55MBZ5-CRMf6XZu.js} +7 -9
- package/webapp/dist/assets/chunk-DI55MBZ5-CRMf6XZu.js.map +1 -0
- package/webapp/dist/assets/{chunk-FMBD7UC4-C-BdCe4C.js → chunk-FMBD7UC4-BJ1vT2se.js} +2 -2
- package/webapp/dist/assets/chunk-FMBD7UC4-BJ1vT2se.js.map +1 -0
- package/webapp/dist/assets/{chunk-KX2RTZJC-CA7sDJO5.js → chunk-QN33PNHL-CGyezTSD.js} +2 -2
- package/webapp/dist/assets/chunk-QN33PNHL-CGyezTSD.js.map +1 -0
- package/webapp/dist/assets/{chunk-QZHKN3VN-Bo1VMcph.js → chunk-QZHKN3VN-9xs15j8C.js} +2 -2
- package/webapp/dist/assets/chunk-QZHKN3VN-9xs15j8C.js.map +1 -0
- package/webapp/dist/assets/{chunk-JSJVCQXG-WA_BLIm9.js → chunk-TZMSLE5B-D2g6Tj7Z.js} +6 -14
- package/webapp/dist/assets/chunk-TZMSLE5B-D2g6Tj7Z.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-VBA2DB6C-BqKuyb49.js → classDiagram-2ON5EDUG-BQFGGJNm.js} +6 -7
- package/webapp/dist/assets/classDiagram-2ON5EDUG-BQFGGJNm.js.map +1 -0
- package/webapp/dist/assets/{classDiagram-v2-RAHNMMFH-BqKuyb49.js → classDiagram-v2-WZHVMYZB-BQFGGJNm.js} +6 -7
- package/webapp/dist/assets/classDiagram-v2-WZHVMYZB-BQFGGJNm.js.map +1 -0
- package/webapp/dist/assets/{clone-BX5z8WVZ.js → clone-DOfPd4cz.js} +2 -2
- package/webapp/dist/assets/clone-DOfPd4cz.js.map +1 -0
- package/webapp/dist/assets/{cose-bilkent-S5V4N54A-B-s11SgN.js → cose-bilkent-S5V4N54A-BYN-vqm8.js} +2 -2
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-BYN-vqm8.js.map +1 -0
- package/webapp/dist/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -1
- package/webapp/dist/assets/{dagre-KLK3FWXG-DmQFV2qK.js → dagre-6UL2VRFP-ClEaFABE.js} +7 -7
- package/webapp/dist/assets/dagre-6UL2VRFP-ClEaFABE.js.map +1 -0
- package/webapp/dist/assets/defaultLocale-B2RvLBDe.js.map +1 -1
- package/webapp/dist/assets/{diagram-E7M64L7V-QRaBfST8.js → diagram-PSM6KHXK-CM4hLE_0.js} +10 -10
- package/webapp/dist/assets/diagram-PSM6KHXK-CM4hLE_0.js.map +1 -0
- package/webapp/dist/assets/{diagram-IFDJBPK2-lrWn1Obo.js → diagram-QEK2KX5R-BZjGFX-2.js} +8 -9
- package/webapp/dist/assets/diagram-QEK2KX5R-BZjGFX-2.js.map +1 -0
- package/webapp/dist/assets/{diagram-P4PSJMXO-sTU7Hh-Y.js → diagram-S2PKOQOG-Bvw01OOG.js} +8 -8
- package/webapp/dist/assets/diagram-S2PKOQOG-Bvw01OOG.js.map +1 -0
- package/webapp/dist/assets/{erDiagram-INFDFZHY-Cx6jc9Wq.js → erDiagram-Q2GNP2WA-ctHu5zQL.js} +75 -96
- package/webapp/dist/assets/erDiagram-Q2GNP2WA-ctHu5zQL.js.map +1 -0
- package/webapp/dist/assets/{flowDiagram-PKNHOUZH-DfGI49Dz.js → flowDiagram-NV44I4VS-m7ofIhri.js} +81 -98
- package/webapp/dist/assets/flowDiagram-NV44I4VS-m7ofIhri.js.map +1 -0
- package/webapp/dist/assets/{ganttDiagram-A5KZAMGK-nrcHWWaM.js → ganttDiagram-JELNMOA3-D9wS5Veb.js} +3 -28
- package/webapp/dist/assets/ganttDiagram-JELNMOA3-D9wS5Veb.js.map +1 -0
- package/webapp/dist/assets/{gitGraphDiagram-K3NZZRJ6-D8ivAqd6.js → gitGraphDiagram-V2S2FVAM-B86qqJx7.js} +46 -38
- package/webapp/dist/assets/gitGraphDiagram-V2S2FVAM-B86qqJx7.js.map +1 -0
- package/webapp/dist/assets/graph-u844GGQC.js +425 -0
- package/webapp/dist/assets/graph-u844GGQC.js.map +1 -0
- package/webapp/dist/assets/{index-DZFkLLVz.css → index-BGdI3lWA.css} +1 -1
- package/webapp/dist/assets/{index--fy89xGh.js → index-tinPEZoH.js} +1059 -1034
- package/webapp/dist/assets/{index--fy89xGh.js.map → index-tinPEZoH.js.map} +1 -1
- package/webapp/dist/assets/{infoDiagram-LFFYTUFH-PIoZHr7s.js → infoDiagram-HS3SLOUP-DwRPUctP.js} +7 -7
- package/webapp/dist/assets/infoDiagram-HS3SLOUP-DwRPUctP.js.map +1 -0
- package/webapp/dist/assets/init-ZxktEp_H.js.map +1 -1
- package/webapp/dist/assets/{journeyDiagram-4ABVD52K-C2qidjQ5.js → journeyDiagram-XKPGCS4Q-B91ZO-ec.js} +5 -5
- package/webapp/dist/assets/journeyDiagram-XKPGCS4Q-B91ZO-ec.js.map +1 -0
- package/webapp/dist/assets/{kanban-definition-K7BYSVSG-Du0TC8WS.js → kanban-definition-3W4ZIXB7-CoogrZ07.js} +3 -5
- package/webapp/dist/assets/kanban-definition-3W4ZIXB7-CoogrZ07.js.map +1 -0
- package/webapp/dist/assets/{layout-VmEo1OEB.js → layout-BrzQmqFJ.js} +5 -5
- package/webapp/dist/assets/layout-BrzQmqFJ.js.map +1 -0
- package/webapp/dist/assets/{linear-B662YHAc.js → linear-C6H7K9Zy.js} +2 -2
- package/webapp/dist/assets/linear-C6H7K9Zy.js.map +1 -0
- package/webapp/dist/assets/{mindmap-definition-YRQLILUH-D7arZj95.js → mindmap-definition-VGOIOE7T-UDHZQkNZ.js} +5 -7
- package/webapp/dist/assets/mindmap-definition-VGOIOE7T-UDHZQkNZ.js.map +1 -0
- package/webapp/dist/assets/ordinal-CxptdPJm.js.map +1 -1
- package/webapp/dist/assets/{pieDiagram-SKSYHLDU-DvjPP4PA.js → pieDiagram-ADFJNKIX-M81uyQ1J.js} +8 -8
- package/webapp/dist/assets/pieDiagram-ADFJNKIX-M81uyQ1J.js.map +1 -0
- package/webapp/dist/assets/{quadrantDiagram-337W2JSQ-B_JUGMj_.js → quadrantDiagram-AYHSOK5B-ClzIh9Gb.js} +3 -3
- package/webapp/dist/assets/quadrantDiagram-AYHSOK5B-ClzIh9Gb.js.map +1 -0
- package/webapp/dist/assets/{requirementDiagram-Z7DCOOCP-DF0mpvE3.js → requirementDiagram-UZGBJVZJ-DLK3A-pn.js} +6 -16
- package/webapp/dist/assets/requirementDiagram-UZGBJVZJ-DLK3A-pn.js.map +1 -0
- package/webapp/dist/assets/{sankeyDiagram-WA2Y5GQK-CoXlxv00.js → sankeyDiagram-TZEHDZUN-CYqju8I1.js} +2 -2
- package/webapp/dist/assets/sankeyDiagram-TZEHDZUN-CYqju8I1.js.map +1 -0
- package/webapp/dist/assets/{sequenceDiagram-2WXFIKYE-DYqT5Pg7.js → sequenceDiagram-WL72ISMW-2guv6eOd.js} +201 -601
- package/webapp/dist/assets/sequenceDiagram-WL72ISMW-2guv6eOd.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-RAJIS63D-D9b1mN8-.js → stateDiagram-FKZM4ZOC-iujqSp0X.js} +9 -9
- package/webapp/dist/assets/stateDiagram-FKZM4ZOC-iujqSp0X.js.map +1 -0
- package/webapp/dist/assets/{stateDiagram-v2-FVOUBMTO-DNzgudL_.js → stateDiagram-v2-4FDKWEC3-BxzY81ky.js} +5 -5
- package/webapp/dist/assets/stateDiagram-v2-4FDKWEC3-BxzY81ky.js.map +1 -0
- package/webapp/dist/assets/{timeline-definition-YZTLITO2-CkyKUY7A.js → timeline-definition-IT6M3QCI-DjCFSC8d.js} +3 -3
- package/webapp/dist/assets/timeline-definition-IT6M3QCI-DjCFSC8d.js.map +1 -0
- package/webapp/dist/assets/{treemap-KZPCXAKY-CZd09kF-.js → treemap-GDKQZRPO-iaBzDWCP.js} +24 -37
- package/webapp/dist/assets/treemap-GDKQZRPO-iaBzDWCP.js.map +1 -0
- package/webapp/dist/assets/{xychartDiagram-JWTSCODW-BRwRloPc.js → xychartDiagram-PRI3JC2R-R6Jl1c89.js} +4 -4
- package/webapp/dist/assets/xychartDiagram-PRI3JC2R-R6Jl1c89.js.map +1 -0
- package/webapp/dist/index.html +2 -2
- package/webapp/dist/assets/_basePickBy-B7M9Q0Fa.js.map +0 -1
- package/webapp/dist/assets/_baseUniq-DAeYoL6j.js.map +0 -1
- package/webapp/dist/assets/arc-Bh4nDbNR.js.map +0 -1
- package/webapp/dist/assets/architectureDiagram-2XIMDMQ5-CxqmdsIm.js.map +0 -1
- package/webapp/dist/assets/blockDiagram-WCTKOSBZ-CxIWLtpt.js.map +0 -1
- package/webapp/dist/assets/c4Diagram-IC4MRINW-1qErOIgG.js.map +0 -1
- package/webapp/dist/assets/channel-DkgZHNUe.js.map +0 -1
- package/webapp/dist/assets/chunk-4BX2VUAB-BmdMbU9v.js.map +0 -1
- package/webapp/dist/assets/chunk-55IACEB6-D6LDTDBy.js.map +0 -1
- package/webapp/dist/assets/chunk-FMBD7UC4-C-BdCe4C.js.map +0 -1
- package/webapp/dist/assets/chunk-JSJVCQXG-WA_BLIm9.js.map +0 -1
- package/webapp/dist/assets/chunk-KX2RTZJC-CA7sDJO5.js.map +0 -1
- package/webapp/dist/assets/chunk-NQ4KR5QH-wlvxalE3.js.map +0 -1
- package/webapp/dist/assets/chunk-QZHKN3VN-Bo1VMcph.js.map +0 -1
- package/webapp/dist/assets/chunk-WL4C6EOR-B-Pk44be.js.map +0 -1
- package/webapp/dist/assets/classDiagram-VBA2DB6C-BqKuyb49.js.map +0 -1
- package/webapp/dist/assets/classDiagram-v2-RAHNMMFH-BqKuyb49.js.map +0 -1
- package/webapp/dist/assets/clone-BX5z8WVZ.js.map +0 -1
- package/webapp/dist/assets/cose-bilkent-S5V4N54A-B-s11SgN.js.map +0 -1
- package/webapp/dist/assets/dagre-KLK3FWXG-DmQFV2qK.js.map +0 -1
- package/webapp/dist/assets/diagram-E7M64L7V-QRaBfST8.js.map +0 -1
- package/webapp/dist/assets/diagram-IFDJBPK2-lrWn1Obo.js.map +0 -1
- package/webapp/dist/assets/diagram-P4PSJMXO-sTU7Hh-Y.js.map +0 -1
- package/webapp/dist/assets/erDiagram-INFDFZHY-Cx6jc9Wq.js.map +0 -1
- package/webapp/dist/assets/flowDiagram-PKNHOUZH-DfGI49Dz.js.map +0 -1
- package/webapp/dist/assets/ganttDiagram-A5KZAMGK-nrcHWWaM.js.map +0 -1
- package/webapp/dist/assets/gitGraphDiagram-K3NZZRJ6-D8ivAqd6.js.map +0 -1
- package/webapp/dist/assets/graph-R5G-y8tB.js +0 -782
- package/webapp/dist/assets/graph-R5G-y8tB.js.map +0 -1
- package/webapp/dist/assets/infoDiagram-LFFYTUFH-PIoZHr7s.js.map +0 -1
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-oCM-LYk1.js +0 -966
- package/webapp/dist/assets/ishikawaDiagram-PHBUUO56-oCM-LYk1.js.map +0 -1
- package/webapp/dist/assets/journeyDiagram-4ABVD52K-C2qidjQ5.js.map +0 -1
- package/webapp/dist/assets/kanban-definition-K7BYSVSG-Du0TC8WS.js.map +0 -1
- package/webapp/dist/assets/layout-VmEo1OEB.js.map +0 -1
- package/webapp/dist/assets/linear-B662YHAc.js.map +0 -1
- package/webapp/dist/assets/mindmap-definition-YRQLILUH-D7arZj95.js.map +0 -1
- package/webapp/dist/assets/pieDiagram-SKSYHLDU-DvjPP4PA.js.map +0 -1
- package/webapp/dist/assets/quadrantDiagram-337W2JSQ-B_JUGMj_.js.map +0 -1
- package/webapp/dist/assets/requirementDiagram-Z7DCOOCP-DF0mpvE3.js.map +0 -1
- package/webapp/dist/assets/sankeyDiagram-WA2Y5GQK-CoXlxv00.js.map +0 -1
- package/webapp/dist/assets/sequenceDiagram-2WXFIKYE-DYqT5Pg7.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-RAJIS63D-D9b1mN8-.js.map +0 -1
- package/webapp/dist/assets/stateDiagram-v2-FVOUBMTO-DNzgudL_.js.map +0 -1
- package/webapp/dist/assets/timeline-definition-YZTLITO2-CkyKUY7A.js.map +0 -1
- package/webapp/dist/assets/treemap-KZPCXAKY-CZd09kF-.js.map +0 -1
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-BxVF5Olo.js +0 -2487
- package/webapp/dist/assets/vennDiagram-LZ73GAT5-BxVF5Olo.js.map +0 -1
- package/webapp/dist/assets/xychartDiagram-JWTSCODW-BRwRloPc.js.map +0 -1
package/dist/mcp/supervisor.js
CHANGED
|
@@ -40,12 +40,14 @@ exports.getMcpDeclaredServerRuntimeStatuses = getMcpDeclaredServerRuntimeStatuse
|
|
|
40
40
|
exports.startMcpSupervisor = startMcpSupervisor;
|
|
41
41
|
exports.stopMcpSupervisor = stopMcpSupervisor;
|
|
42
42
|
exports.requestMcpServerRestart = requestMcpServerRestart;
|
|
43
|
+
exports.requestMcpServerDisable = requestMcpServerDisable;
|
|
43
44
|
exports.requestMcpConfigReload = requestMcpConfigReload;
|
|
44
45
|
exports.buildHttpHeaders = buildHttpHeaders;
|
|
45
46
|
const time_1 = require("@longrun-ai/kernel/utils/time");
|
|
46
47
|
const fs = __importStar(require("fs"));
|
|
47
48
|
const node_crypto_1 = require("node:crypto");
|
|
48
49
|
const path = __importStar(require("path"));
|
|
50
|
+
const yaml_1 = __importStar(require("yaml"));
|
|
49
51
|
const log_1 = require("../log");
|
|
50
52
|
const persistence_1 = require("../persistence");
|
|
51
53
|
const problems_1 = require("../problems");
|
|
@@ -151,6 +153,7 @@ class McpServerDispatch {
|
|
|
151
153
|
for (const rt of this.leasesByDialogKey.values()) {
|
|
152
154
|
rt.requestStop({ forceKillAfterMs: 3000 });
|
|
153
155
|
}
|
|
156
|
+
this.leasesByDialogKey.clear();
|
|
154
157
|
for (const [dialogKey, init] of this.leaseInitByDialogKey.entries()) {
|
|
155
158
|
this.canceledLeaseDialogs.add(dialogKey);
|
|
156
159
|
void init
|
|
@@ -159,6 +162,7 @@ class McpServerDispatch {
|
|
|
159
162
|
// ignore
|
|
160
163
|
});
|
|
161
164
|
}
|
|
165
|
+
this.leaseInitByDialogKey.clear();
|
|
162
166
|
}
|
|
163
167
|
async callToolForDialog(dlg, mcpToolName, args) {
|
|
164
168
|
const serverId = this.serverId;
|
|
@@ -323,6 +327,13 @@ function getMcpDeclaredServerRuntimeStatuses() {
|
|
|
323
327
|
errorText: catalogEntry.configErrorText,
|
|
324
328
|
};
|
|
325
329
|
}
|
|
330
|
+
if (catalogEntry?.disabled) {
|
|
331
|
+
return {
|
|
332
|
+
serverId,
|
|
333
|
+
transport: catalogEntry.transport,
|
|
334
|
+
status: 'disabled',
|
|
335
|
+
};
|
|
336
|
+
}
|
|
326
337
|
if (serverStateById.has(serverId)) {
|
|
327
338
|
return {
|
|
328
339
|
serverId,
|
|
@@ -435,6 +446,27 @@ function requestMcpServerRestart(serverId) {
|
|
|
435
446
|
});
|
|
436
447
|
});
|
|
437
448
|
}
|
|
449
|
+
function requestMcpServerDisable(serverId) {
|
|
450
|
+
return new Promise((resolve) => {
|
|
451
|
+
reloadChain = reloadChain
|
|
452
|
+
.then(async () => {
|
|
453
|
+
try {
|
|
454
|
+
const res = await disableServerNow(serverId);
|
|
455
|
+
resolve(res);
|
|
456
|
+
}
|
|
457
|
+
catch (err) {
|
|
458
|
+
const errorText = err instanceof Error ? err.message : String(err);
|
|
459
|
+
log.warn(`MCP server disable failed`, err, { serverId });
|
|
460
|
+
resolve({ ok: false, errorText });
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
.catch((err) => {
|
|
464
|
+
const errorText = err instanceof Error ? err.message : String(err);
|
|
465
|
+
log.warn(`MCP server disable enqueue failed`, err, { serverId });
|
|
466
|
+
resolve({ ok: false, errorText });
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
}
|
|
438
470
|
function requestMcpConfigReload(reason = 'manual') {
|
|
439
471
|
const normalizedReason = reason.trim() === '' ? 'manual' : reason.trim();
|
|
440
472
|
return new Promise((resolve) => {
|
|
@@ -554,7 +586,7 @@ async function reloadNow(reason) {
|
|
|
554
586
|
const code = isRecord(err) && 'code' in err ? err.code : undefined;
|
|
555
587
|
if (code === 'ENOENT') {
|
|
556
588
|
// Deletion is treated as empty config.
|
|
557
|
-
await applyWorkspaceConfig({ version: 1, servers: {} }, [], [], [], `missing file (${reason})`);
|
|
589
|
+
await applyWorkspaceConfig({ version: 1, servers: {} }, [], [], [], [], null, `missing file (${reason})`);
|
|
558
590
|
clearWorkspaceConfigProblem();
|
|
559
591
|
await reconcileMcpManualProblemsForRuntime([], null);
|
|
560
592
|
return;
|
|
@@ -572,10 +604,19 @@ async function reloadNow(reason) {
|
|
|
572
604
|
return;
|
|
573
605
|
}
|
|
574
606
|
clearWorkspaceConfigProblem();
|
|
575
|
-
await applyWorkspaceConfig(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder, parsed.validServerIdsInYamlOrder, reason);
|
|
607
|
+
await applyWorkspaceConfig(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder, parsed.validServerIdsInYamlOrder, parsed.disabledServerIdsInYamlOrder, rawText, reason);
|
|
576
608
|
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
577
609
|
}
|
|
578
610
|
async function restartServerNow(serverId) {
|
|
611
|
+
let removedPlaceholder = false;
|
|
612
|
+
const notifyPlaceholderRemovalOnFailure = (trigger) => {
|
|
613
|
+
if (!removedPlaceholder)
|
|
614
|
+
return;
|
|
615
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRegistryMaybeChanged)({
|
|
616
|
+
reason: 'registry_changed',
|
|
617
|
+
trigger,
|
|
618
|
+
});
|
|
619
|
+
};
|
|
579
620
|
let rawText;
|
|
580
621
|
try {
|
|
581
622
|
rawText = await fs.promises.readFile(MCP_YAML_PATH, 'utf8');
|
|
@@ -592,23 +633,51 @@ async function restartServerNow(serverId) {
|
|
|
592
633
|
upsertWorkspaceConfigProblem(`Failed to read ${MCP_YAML_PATH}: ${String(err)}`);
|
|
593
634
|
return { ok: false, errorText: `Failed to read ${MCP_YAML_PATH}: ${String(err)}` };
|
|
594
635
|
}
|
|
595
|
-
|
|
636
|
+
let activeRawText = rawText;
|
|
637
|
+
let parsed = (0, config_1.parseMcpYaml)(activeRawText);
|
|
596
638
|
if (!parsed.ok) {
|
|
597
639
|
await reconcileMcpManualProblemsForRuntime([], null);
|
|
598
640
|
upsertWorkspaceConfigProblem(parsed.errorText);
|
|
599
641
|
return { ok: false, errorText: parsed.errorText };
|
|
600
642
|
}
|
|
601
643
|
clearWorkspaceConfigProblem();
|
|
644
|
+
const disabledServer = parsed.serverIdsInYamlOrder.includes(serverId) &&
|
|
645
|
+
parsed.invalidServers.every((s) => s.serverId !== serverId) &&
|
|
646
|
+
parsed.config.servers[serverId] === undefined;
|
|
647
|
+
if (disabledServer) {
|
|
648
|
+
const enableRes = setServerEnabledInMcpYaml(rawText, serverId, true);
|
|
649
|
+
if (!enableRes.ok) {
|
|
650
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, rawText);
|
|
651
|
+
return { ok: false, errorText: enableRes.errorText };
|
|
652
|
+
}
|
|
653
|
+
if (enableRes.changed) {
|
|
654
|
+
await fs.promises.writeFile(MCP_YAML_PATH, enableRes.rawText, 'utf8');
|
|
655
|
+
lastSeenMcpYamlSig = await readMcpYamlSig();
|
|
656
|
+
removedPlaceholder = unregisterMcpToolsetPlaceholder(serverId) || removedPlaceholder;
|
|
657
|
+
}
|
|
658
|
+
activeRawText = enableRes.rawText;
|
|
659
|
+
parsed = (0, config_1.parseMcpYaml)(activeRawText);
|
|
660
|
+
if (!parsed.ok) {
|
|
661
|
+
clearDeclaredServerRuntimeCatalog();
|
|
662
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
663
|
+
upsertWorkspaceConfigProblem(parsed.errorText);
|
|
664
|
+
notifyPlaceholderRemovalOnFailure(`mcp:restart:${serverId}:parse-failed`);
|
|
665
|
+
return { ok: false, errorText: parsed.errorText };
|
|
666
|
+
}
|
|
667
|
+
clearWorkspaceConfigProblem();
|
|
668
|
+
}
|
|
602
669
|
const invalid = parsed.invalidServers.find((s) => s.serverId === serverId);
|
|
603
670
|
if (invalid) {
|
|
604
|
-
replaceDeclaredServerRuntimeCatalog(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder);
|
|
605
|
-
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder,
|
|
671
|
+
replaceDeclaredServerRuntimeCatalog(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder, parsed.disabledServerIdsInYamlOrder);
|
|
672
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, activeRawText);
|
|
606
673
|
upsertMcpServerConfigInvalidProblem(serverId, invalid.errorText);
|
|
674
|
+
notifyPlaceholderRemovalOnFailure(`mcp:restart:${serverId}:config-invalid`);
|
|
607
675
|
return { ok: false, errorText: invalid.errorText };
|
|
608
676
|
}
|
|
609
677
|
const serverCfg = parsed.config.servers[serverId];
|
|
610
678
|
if (!serverCfg) {
|
|
611
|
-
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder,
|
|
679
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, activeRawText);
|
|
680
|
+
notifyPlaceholderRemovalOnFailure(`mcp:restart:${serverId}:not-configured`);
|
|
612
681
|
return {
|
|
613
682
|
ok: false,
|
|
614
683
|
errorText: `MCP server '${serverId}' is not configured in ${MCP_YAML_PATH}`,
|
|
@@ -618,25 +687,28 @@ async function restartServerNow(serverId) {
|
|
|
618
687
|
const fingerprint = fingerprintServerConfig(serverCfg);
|
|
619
688
|
const existing = serverStateById.get(serverId);
|
|
620
689
|
const runtimeLeaseChanged = existing !== undefined;
|
|
621
|
-
replaceDeclaredServerRuntimeCatalog(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder);
|
|
690
|
+
replaceDeclaredServerRuntimeCatalog(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder, parsed.disabledServerIdsInYamlOrder);
|
|
691
|
+
if (!existing) {
|
|
692
|
+
removedPlaceholder = unregisterMcpToolsetPlaceholder(serverId) || removedPlaceholder;
|
|
693
|
+
}
|
|
622
694
|
const res = await tryBuildServerState(serverCfg, desiredToolsetName, fingerprint);
|
|
623
695
|
if (!res.ok) {
|
|
624
|
-
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder,
|
|
696
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, activeRawText);
|
|
625
697
|
upsertDeclaredServerRuntimeError(serverId, res.errorText);
|
|
626
698
|
upsertMcpServerRuntimeUnavailableProblem(serverId, res.errorText, res.detailTextI18n);
|
|
699
|
+
notifyPlaceholderRemovalOnFailure(`mcp:restart:${serverId}:runtime-unavailable`);
|
|
627
700
|
return { ok: false, errorText: res.errorText };
|
|
628
701
|
}
|
|
629
702
|
clearDeclaredServerRuntimeError(serverId);
|
|
630
703
|
(0, problems_1.removeProblemsByPrefix)(`${problemPrefixForServer(serverId)}server_error`);
|
|
631
704
|
if (existing) {
|
|
632
|
-
|
|
633
|
-
existing.dispatch.requestStop();
|
|
705
|
+
stopLoadedServer(serverId);
|
|
634
706
|
}
|
|
635
707
|
registerServer(res.state);
|
|
636
708
|
serverStateById.set(serverId, res.state);
|
|
637
709
|
(0, problems_1.reconcileProblemsByPrefix)(problemPrefixForServer(serverId), res.state.problems);
|
|
638
710
|
reorderMcpToolsetsInRegistry(parsed.serverIdsInYamlOrder);
|
|
639
|
-
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder,
|
|
711
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, activeRawText);
|
|
640
712
|
(0, tool_availability_updates_1.notifyToolAvailabilityRegistryMaybeChanged)({
|
|
641
713
|
reason: 'registry_changed',
|
|
642
714
|
trigger: `mcp:restart:${serverId}`,
|
|
@@ -646,6 +718,119 @@ async function restartServerNow(serverId) {
|
|
|
646
718
|
}
|
|
647
719
|
return { ok: true };
|
|
648
720
|
}
|
|
721
|
+
async function disableServerNow(serverId) {
|
|
722
|
+
const stoppedExisting = stopLoadedServer(serverId);
|
|
723
|
+
let rawText;
|
|
724
|
+
try {
|
|
725
|
+
rawText = await fs.promises.readFile(MCP_YAML_PATH, 'utf8');
|
|
726
|
+
}
|
|
727
|
+
catch (err) {
|
|
728
|
+
const code = isRecord(err) && 'code' in err ? err.code : undefined;
|
|
729
|
+
if (stoppedExisting) {
|
|
730
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRegistryMaybeChanged)({
|
|
731
|
+
reason: 'registry_changed',
|
|
732
|
+
trigger: `mcp:disable:${serverId}:read-failed`,
|
|
733
|
+
});
|
|
734
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRuntimeLeaseChanged)(`mcp:disable:${serverId}:read-failed`);
|
|
735
|
+
}
|
|
736
|
+
if (code === 'ENOENT') {
|
|
737
|
+
return { ok: false, errorText: `Cannot disable '${serverId}': ${MCP_YAML_PATH} is missing` };
|
|
738
|
+
}
|
|
739
|
+
return { ok: false, errorText: `Failed to read ${MCP_YAML_PATH}: ${String(err)}` };
|
|
740
|
+
}
|
|
741
|
+
const disableRes = setServerEnabledInMcpYaml(rawText, serverId, false);
|
|
742
|
+
if (!disableRes.ok) {
|
|
743
|
+
if (stoppedExisting) {
|
|
744
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRegistryMaybeChanged)({
|
|
745
|
+
reason: 'registry_changed',
|
|
746
|
+
trigger: `mcp:disable:${serverId}:disable-failed`,
|
|
747
|
+
});
|
|
748
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRuntimeLeaseChanged)(`mcp:disable:${serverId}:disable-failed`);
|
|
749
|
+
}
|
|
750
|
+
return { ok: false, errorText: disableRes.errorText };
|
|
751
|
+
}
|
|
752
|
+
if (disableRes.changed) {
|
|
753
|
+
await fs.promises.writeFile(MCP_YAML_PATH, disableRes.rawText, 'utf8');
|
|
754
|
+
lastSeenMcpYamlSig = await readMcpYamlSig();
|
|
755
|
+
}
|
|
756
|
+
const parsed = (0, config_1.parseMcpYaml)(disableRes.rawText);
|
|
757
|
+
if (!parsed.ok) {
|
|
758
|
+
clearDeclaredServerRuntimeCatalog();
|
|
759
|
+
await reconcileMcpManualProblemsForRuntime([], null);
|
|
760
|
+
upsertWorkspaceConfigProblem(parsed.errorText);
|
|
761
|
+
if (stoppedExisting) {
|
|
762
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRegistryMaybeChanged)({
|
|
763
|
+
reason: 'registry_changed',
|
|
764
|
+
trigger: `mcp:disable:${serverId}:parse-failed`,
|
|
765
|
+
});
|
|
766
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRuntimeLeaseChanged)(`mcp:disable:${serverId}:parse-failed`);
|
|
767
|
+
}
|
|
768
|
+
return { ok: false, errorText: parsed.errorText };
|
|
769
|
+
}
|
|
770
|
+
clearWorkspaceConfigProblem();
|
|
771
|
+
await applyWorkspaceConfig(parsed.config, parsed.invalidServers, parsed.serverIdsInYamlOrder, parsed.validServerIdsInYamlOrder, parsed.disabledServerIdsInYamlOrder, disableRes.rawText, `mcp_disable:${serverId}`);
|
|
772
|
+
await reconcileMcpManualProblemsForRuntime(parsed.serverIdsInYamlOrder, disableRes.rawText);
|
|
773
|
+
if (stoppedExisting) {
|
|
774
|
+
(0, tool_availability_updates_1.notifyToolAvailabilityRuntimeLeaseChanged)(`mcp:disable:${serverId}`);
|
|
775
|
+
}
|
|
776
|
+
return { ok: true };
|
|
777
|
+
}
|
|
778
|
+
function setServerEnabledInMcpYaml(rawText, serverId, enabled) {
|
|
779
|
+
const doc = yaml_1.default.parseDocument(rawText, { prettyErrors: true });
|
|
780
|
+
if (doc.errors.length > 0) {
|
|
781
|
+
return { ok: false, errorText: doc.errors.map((e) => String(e)).join('\n') };
|
|
782
|
+
}
|
|
783
|
+
const parsed = doc.toJS();
|
|
784
|
+
if (!isRecord(parsed)) {
|
|
785
|
+
return { ok: false, errorText: `Invalid mcp.yaml: expected object at mcp.yaml root` };
|
|
786
|
+
}
|
|
787
|
+
if (parsed.version !== 1) {
|
|
788
|
+
return { ok: false, errorText: `Invalid mcp.yaml: expected version: 1` };
|
|
789
|
+
}
|
|
790
|
+
const servers = parsed.servers;
|
|
791
|
+
const server = isRecord(servers) ? servers[serverId] : undefined;
|
|
792
|
+
if (!isRecord(server)) {
|
|
793
|
+
return {
|
|
794
|
+
ok: false,
|
|
795
|
+
errorText: `MCP server '${serverId}' is not configured in ${MCP_YAML_PATH}`,
|
|
796
|
+
};
|
|
797
|
+
}
|
|
798
|
+
const currentEnabled = server.enabled;
|
|
799
|
+
if (currentEnabled !== undefined && typeof currentEnabled !== 'boolean') {
|
|
800
|
+
return {
|
|
801
|
+
ok: false,
|
|
802
|
+
errorText: `Invalid mcp.yaml: servers.${serverId}.enabled must be a boolean`,
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
if (currentEnabled === enabled) {
|
|
806
|
+
return { ok: true, rawText, changed: false };
|
|
807
|
+
}
|
|
808
|
+
const serverNode = doc.getIn(['servers', serverId], true);
|
|
809
|
+
if (!(0, yaml_1.isMap)(serverNode)) {
|
|
810
|
+
return {
|
|
811
|
+
ok: false,
|
|
812
|
+
errorText: `Invalid mcp.yaml: servers.${serverId} must be an object`,
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
const existingEnabledPair = serverNode.items.find((pair) => (0, yaml_1.isScalar)(pair.key) && pair.key.value === 'enabled');
|
|
816
|
+
if (existingEnabledPair) {
|
|
817
|
+
existingEnabledPair.value = doc.createNode(enabled);
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
serverNode.items.unshift(doc.createPair('enabled', enabled));
|
|
821
|
+
}
|
|
822
|
+
return { ok: true, rawText: String(doc), changed: true };
|
|
823
|
+
}
|
|
824
|
+
function stopLoadedServer(serverId) {
|
|
825
|
+
const existing = serverStateById.get(serverId);
|
|
826
|
+
if (!existing)
|
|
827
|
+
return false;
|
|
828
|
+
unregisterServer(existing);
|
|
829
|
+
existing.dispatch.requestStop();
|
|
830
|
+
serverStateById.delete(serverId);
|
|
831
|
+
(0, problems_1.reconcileProblemsByPrefix)(problemPrefixForServer(serverId), []);
|
|
832
|
+
return true;
|
|
833
|
+
}
|
|
649
834
|
async function reconcileMcpManualProblemsForRuntime(serverIdsInYamlOrder, rawText) {
|
|
650
835
|
const manualInfo = rawText === null ? (0, manual_problems_1.emptyMcpToolsetManualByServer)() : (0, manual_problems_1.parseMcpManualByServer)(rawText);
|
|
651
836
|
await (0, manual_problems_1.reconcileMcpToolsetManualProblems)({
|
|
@@ -711,13 +896,15 @@ function upsertMcpToolCallProblem(args) {
|
|
|
711
896
|
const hintLines = workLanguage === 'zh'
|
|
712
897
|
? [
|
|
713
898
|
'建议排查:',
|
|
714
|
-
`-
|
|
899
|
+
`- 如果需要全局重建该 MCP server,直接调用 mcp_restart({"serverId":"${args.serverId}"});它成功后会清理旧 runtime 的全部 lease`,
|
|
900
|
+
`- 如果只想丢弃当前对话的连接,再调用 mcp_release({"serverId":"${args.serverId}"})`,
|
|
715
901
|
`- 重新打开/关闭浏览器窗口,避免 Playwright persistent context 残留`,
|
|
716
902
|
`- 查看 ${MCP_YAML_PATH} 是否已加载且配置正确(Problems 面板 / 后端日志)`,
|
|
717
903
|
]
|
|
718
904
|
: [
|
|
719
905
|
'Suggested checks:',
|
|
720
|
-
`-
|
|
906
|
+
`- To rebuild this MCP server globally, call mcp_restart({"serverId":"${args.serverId}"}) directly; a successful restart clears all leases on the old runtime`,
|
|
907
|
+
`- To discard only this dialog's connection, call mcp_release({"serverId":"${args.serverId}"})`,
|
|
721
908
|
`- Close/reopen browser windows to avoid leftover Playwright persistent contexts`,
|
|
722
909
|
`- Verify ${MCP_YAML_PATH} is loaded and valid (Problems panel / backend logs)`,
|
|
723
910
|
];
|
|
@@ -746,12 +933,13 @@ function upsertMcpToolCallProblem(args) {
|
|
|
746
933
|
function clearMcpToolCallProblem(serverId) {
|
|
747
934
|
(0, problems_1.removeProblemsByPrefix)(`${MCP_TOOL_CALL_PROBLEM_PREFIX}${sanitizePathSegment(serverId)}`);
|
|
748
935
|
}
|
|
749
|
-
async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder, validServerIdsInYamlOrder, reason) {
|
|
936
|
+
async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder, validServerIdsInYamlOrder, disabledServerIdsInYamlOrder, rawText, reason) {
|
|
750
937
|
log.info(`Applying MCP rtws config (${reason})`);
|
|
751
|
-
replaceDeclaredServerRuntimeCatalog(config, invalidServers, serverIdsInYamlOrder);
|
|
938
|
+
replaceDeclaredServerRuntimeCatalog(config, invalidServers, serverIdsInYamlOrder, disabledServerIdsInYamlOrder);
|
|
752
939
|
let runtimeLeaseChanged = false;
|
|
753
940
|
const invalidIds = new Set(invalidServers.map((s) => s.serverId));
|
|
754
941
|
const desiredIds = new Set([...Object.keys(config.servers), ...invalidIds]);
|
|
942
|
+
const declaredIds = new Set(serverIdsInYamlOrder);
|
|
755
943
|
// Remove deleted servers first.
|
|
756
944
|
for (const [serverId, state] of serverStateById.entries()) {
|
|
757
945
|
if (desiredIds.has(serverId))
|
|
@@ -762,8 +950,18 @@ async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder
|
|
|
762
950
|
serverStateById.delete(serverId);
|
|
763
951
|
(0, problems_1.reconcileProblemsByPrefix)(problemPrefixForServer(serverId), []);
|
|
764
952
|
}
|
|
953
|
+
// Remove disabled/deleted MCP placeholders that are no longer declared.
|
|
954
|
+
for (const [toolsetName, owner] of Array.from(toolsetOwnerByName.entries())) {
|
|
955
|
+
if (owner.kind !== 'mcp')
|
|
956
|
+
continue;
|
|
957
|
+
if (declaredIds.has(owner.serverId))
|
|
958
|
+
continue;
|
|
959
|
+
(0, registry_1.unregisterToolset)(toolsetName);
|
|
960
|
+
toolsetOwnerByName.delete(toolsetName);
|
|
961
|
+
}
|
|
765
962
|
// Surface invalid server config errors (while keeping last-known-good runtimes registered).
|
|
766
963
|
for (const s of invalidServers) {
|
|
964
|
+
unregisterMcpToolsetPlaceholder(s.serverId);
|
|
767
965
|
upsertMcpServerConfigInvalidProblem(s.serverId, s.errorText);
|
|
768
966
|
}
|
|
769
967
|
// Apply desired servers independently (deterministic order).
|
|
@@ -775,6 +973,9 @@ async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder
|
|
|
775
973
|
const fingerprint = fingerprintServerConfig(serverCfg);
|
|
776
974
|
const existing = serverStateById.get(serverId);
|
|
777
975
|
if (!existing || existing.configFingerprint !== fingerprint) {
|
|
976
|
+
if (!existing) {
|
|
977
|
+
unregisterMcpToolsetPlaceholder(serverId);
|
|
978
|
+
}
|
|
778
979
|
const res = await tryBuildServerState(serverCfg, desiredToolsetName, fingerprint);
|
|
779
980
|
if (!res.ok) {
|
|
780
981
|
upsertDeclaredServerRuntimeError(serverId, res.errorText);
|
|
@@ -827,6 +1028,11 @@ async function applyWorkspaceConfig(config, invalidServers, serverIdsInYamlOrder
|
|
|
827
1028
|
if (!changed)
|
|
828
1029
|
break;
|
|
829
1030
|
}
|
|
1031
|
+
const manualInfo = rawText === null ? (0, manual_problems_1.emptyMcpToolsetManualByServer)() : (0, manual_problems_1.parseMcpManualByServer)(rawText);
|
|
1032
|
+
for (const serverId of disabledServerIdsInYamlOrder) {
|
|
1033
|
+
(0, problems_1.reconcileProblemsByPrefix)(problemPrefixForServer(serverId), []);
|
|
1034
|
+
registerDisabledServerToolset(serverId, manualInfo);
|
|
1035
|
+
}
|
|
830
1036
|
reorderMcpToolsetsInRegistry(serverIdsInYamlOrder);
|
|
831
1037
|
(0, tool_availability_updates_1.notifyToolAvailabilityRegistryMaybeChanged)({
|
|
832
1038
|
reason: 'registry_changed',
|
|
@@ -849,7 +1055,7 @@ function clearDeclaredServerRuntimeCatalog() {
|
|
|
849
1055
|
declaredServerIdsInYamlOrder = [];
|
|
850
1056
|
declaredServerRuntimeCatalogById.clear();
|
|
851
1057
|
}
|
|
852
|
-
function replaceDeclaredServerRuntimeCatalog(config, invalidServers, serverIdsInYamlOrder) {
|
|
1058
|
+
function replaceDeclaredServerRuntimeCatalog(config, invalidServers, serverIdsInYamlOrder, disabledServerIdsInYamlOrder) {
|
|
853
1059
|
const previousRuntimeErrors = new Map();
|
|
854
1060
|
for (const [serverId, entry] of declaredServerRuntimeCatalogById.entries()) {
|
|
855
1061
|
if (typeof entry.runtimeErrorText === 'string' && entry.runtimeErrorText.trim() !== '') {
|
|
@@ -858,7 +1064,15 @@ function replaceDeclaredServerRuntimeCatalog(config, invalidServers, serverIdsIn
|
|
|
858
1064
|
}
|
|
859
1065
|
declaredServerIdsInYamlOrder = [...serverIdsInYamlOrder];
|
|
860
1066
|
declaredServerRuntimeCatalogById.clear();
|
|
1067
|
+
const disabledIds = new Set(disabledServerIdsInYamlOrder);
|
|
861
1068
|
for (const serverId of serverIdsInYamlOrder) {
|
|
1069
|
+
if (disabledIds.has(serverId)) {
|
|
1070
|
+
declaredServerRuntimeCatalogById.set(serverId, {
|
|
1071
|
+
transport: 'unknown',
|
|
1072
|
+
disabled: true,
|
|
1073
|
+
});
|
|
1074
|
+
continue;
|
|
1075
|
+
}
|
|
862
1076
|
const cfg = config.servers[serverId];
|
|
863
1077
|
if (!cfg)
|
|
864
1078
|
continue;
|
|
@@ -945,6 +1159,74 @@ function registerServer(state) {
|
|
|
945
1159
|
});
|
|
946
1160
|
toolsetOwnerByName.set(state.toolsetName, { kind: 'mcp', serverId: state.serverId });
|
|
947
1161
|
}
|
|
1162
|
+
function registerDisabledServerToolset(serverId, manualInfo) {
|
|
1163
|
+
const existingToolset = registry_1.toolsetsRegistry.get(serverId);
|
|
1164
|
+
const existingOwner = toolsetOwnerByName.get(serverId);
|
|
1165
|
+
if (existingToolset && (!existingOwner || existingOwner.serverId !== serverId)) {
|
|
1166
|
+
upsertMcpServerConfigInvalidProblem(serverId, `Toolset name collision: ${serverId}`);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
(0, registry_1.registerToolset)(serverId, []);
|
|
1170
|
+
const manual = manualInfo.manualByServerId.get(serverId);
|
|
1171
|
+
const manualSpec = manual?.contentFile
|
|
1172
|
+
? (0, spec_1.buildMcpManualSpec)(manual.contentFile)
|
|
1173
|
+
: {
|
|
1174
|
+
topics: ['index'],
|
|
1175
|
+
warnOnMissing: false,
|
|
1176
|
+
includeSchemaToolsSection: false,
|
|
1177
|
+
};
|
|
1178
|
+
const inlineManual = manual ? renderInlineMcpToolsetManual(manual) : '';
|
|
1179
|
+
const disabledNoticeEn = [
|
|
1180
|
+
`This MCP server is configured but disabled in \`.minds/mcp.yaml\` (\`enabled: false\`).`,
|
|
1181
|
+
`It intentionally exposes zero tools until an MCP administrator enables it with \`mcp_restart({"serverId":"${serverId}"})\`.`,
|
|
1182
|
+
inlineManual,
|
|
1183
|
+
]
|
|
1184
|
+
.filter((part) => part.trim() !== '')
|
|
1185
|
+
.join('\n\n');
|
|
1186
|
+
const disabledNoticeZh = [
|
|
1187
|
+
`该 MCP server 已在 \`.minds/mcp.yaml\` 中配置,但当前为禁用状态(\`enabled: false\`)。`,
|
|
1188
|
+
`它会刻意暴露为 0 工具的 toolset;需要 MCP 排障/管理员用 \`mcp_restart({"serverId":"${serverId}"})\` 启用后才会加载工具。`,
|
|
1189
|
+
inlineManual,
|
|
1190
|
+
]
|
|
1191
|
+
.filter((part) => part.trim() !== '')
|
|
1192
|
+
.join('\n\n');
|
|
1193
|
+
(0, registry_1.setToolsetMeta)(serverId, {
|
|
1194
|
+
source: 'mcp',
|
|
1195
|
+
descriptionI18n: {
|
|
1196
|
+
en: `MCP server: ${serverId} (disabled)`,
|
|
1197
|
+
zh: `MCP 服务器:${serverId}(已禁用)`,
|
|
1198
|
+
},
|
|
1199
|
+
manualNoticeI18n: {
|
|
1200
|
+
en: disabledNoticeEn,
|
|
1201
|
+
zh: disabledNoticeZh,
|
|
1202
|
+
},
|
|
1203
|
+
...(manualSpec !== undefined ? { manualSpec } : {}),
|
|
1204
|
+
});
|
|
1205
|
+
toolsetOwnerByName.set(serverId, { kind: 'mcp', serverId });
|
|
1206
|
+
}
|
|
1207
|
+
function renderInlineMcpToolsetManual(manual) {
|
|
1208
|
+
const parts = [];
|
|
1209
|
+
if (manual.content) {
|
|
1210
|
+
parts.push(manual.content);
|
|
1211
|
+
}
|
|
1212
|
+
for (const section of manual.sections) {
|
|
1213
|
+
parts.push(`#### ${section.title}\n\n${section.content}`);
|
|
1214
|
+
}
|
|
1215
|
+
return parts.join('\n\n');
|
|
1216
|
+
}
|
|
1217
|
+
function unregisterMcpToolsetPlaceholder(serverId) {
|
|
1218
|
+
if (serverStateById.has(serverId))
|
|
1219
|
+
return false;
|
|
1220
|
+
const owner = toolsetOwnerByName.get(serverId);
|
|
1221
|
+
if (owner?.kind !== 'mcp' || owner.serverId !== serverId)
|
|
1222
|
+
return false;
|
|
1223
|
+
const tools = registry_1.toolsetsRegistry.get(serverId);
|
|
1224
|
+
if (tools && tools.length > 0)
|
|
1225
|
+
return false;
|
|
1226
|
+
(0, registry_1.unregisterToolset)(serverId);
|
|
1227
|
+
toolsetOwnerByName.delete(serverId);
|
|
1228
|
+
return true;
|
|
1229
|
+
}
|
|
948
1230
|
function unregisterServer(state) {
|
|
949
1231
|
// Unregister toolset first so Team.Member.listTools doesn't resolve stale tools.
|
|
950
1232
|
if (toolsetOwnerByName.get(state.toolsetName)?.serverId === state.serverId) {
|
package/dist/minds/load.js
CHANGED
|
@@ -116,6 +116,11 @@ function buildAgentMcpToolsetRuntimeNotices(params) {
|
|
|
116
116
|
notices.push({
|
|
117
117
|
toolsetName,
|
|
118
118
|
transport: runtimeStatus?.transport ?? 'unknown',
|
|
119
|
+
status: runtimeStatus?.status === 'disabled'
|
|
120
|
+
? 'disabled'
|
|
121
|
+
: runtimeStatus?.status === 'config_invalid'
|
|
122
|
+
? 'config_invalid'
|
|
123
|
+
: 'temporarily_unavailable',
|
|
119
124
|
errorText: runtimeStatus?.errorText,
|
|
120
125
|
});
|
|
121
126
|
}
|
|
@@ -22,6 +22,7 @@ export type BuildSystemPromptInput = {
|
|
|
22
22
|
export type McpToolsetRuntimeNotice = Readonly<{
|
|
23
23
|
toolsetName: string;
|
|
24
24
|
transport: 'stdio' | 'streamable_http' | 'invalid' | 'unknown';
|
|
25
|
+
status: 'temporarily_unavailable' | 'config_invalid' | 'disabled';
|
|
25
26
|
errorText?: string;
|
|
26
27
|
}>;
|
|
27
28
|
export declare function formatMcpToolsetRuntimeNote(language: LanguageCode, notices: readonly McpToolsetRuntimeNotice[]): string;
|
|
@@ -312,24 +312,32 @@ function formatMcpToolsetRuntimeNote(language, notices) {
|
|
|
312
312
|
return '';
|
|
313
313
|
const lines = language === 'zh'
|
|
314
314
|
? [
|
|
315
|
-
'以下 MCP toolset 已配置给你,且在 `.minds/mcp.yaml`
|
|
316
|
-
'
|
|
315
|
+
'以下 MCP toolset 已配置给你,且在 `.minds/mcp.yaml` 中有声明,但当前不提供可调用的运行时 MCP 工具。',
|
|
316
|
+
'其中有些可能是暂时不可达(例如 stdio transport 进程启动失败,或 streamable HTTP transport 当前无法连接),有些可能是被明确禁用;这不代表你的权限被撤销,也不应视为系统级功能降级。',
|
|
317
317
|
...notices.map((notice) => {
|
|
318
|
+
if (notice.status === 'disabled') {
|
|
319
|
+
return `- \`${notice.toolsetName}\`:状态=已禁用;这是一个已配置但当前刻意暴露为 0 工具的 MCP toolset。如任务依赖它,请按团队职责速查表联系 MCP 排障/管理员处理。`;
|
|
320
|
+
}
|
|
318
321
|
const reason = typeof notice.errorText === 'string' && notice.errorText.trim() !== ''
|
|
319
322
|
? `;最近错误:${notice.errorText}`
|
|
320
323
|
: '';
|
|
321
|
-
|
|
324
|
+
const status = notice.status === 'config_invalid' ? '配置无效' : '暂时不可达';
|
|
325
|
+
return `- \`${notice.toolsetName}\`:transport=${formatTransportLabel(language, notice.transport)};状态=${status}${reason}`;
|
|
322
326
|
}),
|
|
323
327
|
'若当前任务依赖这些能力,应明确说明对应 MCP toolset 眼下不可用,并优先继续使用其余可用工具/路径推进。',
|
|
324
328
|
]
|
|
325
329
|
: [
|
|
326
|
-
'The following MCP toolsets are assigned to you and declared in `.minds/mcp.yaml`, but they
|
|
327
|
-
'
|
|
330
|
+
'The following MCP toolsets are assigned to you and declared in `.minds/mcp.yaml`, but they do not currently provide callable runtime MCP tools.',
|
|
331
|
+
'Some may be temporarily unavailable (for example a stdio transport process failing to start right now, or a streamable HTTP transport being unreachable right now), and some may be explicitly disabled. This does not mean your permission was revoked, and it should not be treated as a system-level capability downgrade.',
|
|
328
332
|
...notices.map((notice) => {
|
|
333
|
+
if (notice.status === 'disabled') {
|
|
334
|
+
return `- \`${notice.toolsetName}\`: status=disabled; this is a configured MCP toolset intentionally exposed with zero tools. If the task depends on it, use the team responsibility quick table to contact the MCP troubleshooter or administrator.`;
|
|
335
|
+
}
|
|
329
336
|
const reason = typeof notice.errorText === 'string' && notice.errorText.trim() !== ''
|
|
330
337
|
? `; latest error: ${notice.errorText}`
|
|
331
338
|
: '';
|
|
332
|
-
|
|
339
|
+
const status = notice.status === 'config_invalid' ? 'config invalid' : 'temporarily unavailable';
|
|
340
|
+
return `- \`${notice.toolsetName}\`: transport=${formatTransportLabel(language, notice.transport)}; status=${status}${reason}`;
|
|
333
341
|
}),
|
|
334
342
|
'If the current task depends on one of these capabilities, say that the corresponding MCP toolset is unavailable right now and continue with other available tools or paths first.',
|
|
335
343
|
];
|
package/dist/tools/builtins.js
CHANGED
|
@@ -81,6 +81,7 @@ function manualSpecFor(toolsetId) {
|
|
|
81
81
|
// MCP tools (local testing/ops)
|
|
82
82
|
(0, registry_1.registerTool)(mcp_1.mcpRestartTool);
|
|
83
83
|
(0, registry_1.registerTool)(mcp_1.mcpReleaseTool);
|
|
84
|
+
(0, registry_1.registerTool)(mcp_1.mcpDisableTool);
|
|
84
85
|
// Memory tools
|
|
85
86
|
(0, registry_1.registerTool)(mem_1.addPersonalMemoryTool);
|
|
86
87
|
(0, registry_1.registerTool)(mem_1.dropPersonalMemoryTool);
|
|
@@ -169,6 +170,7 @@ for (const tool of team_mgmt_1.teamMgmtTools) {
|
|
|
169
170
|
(0, registry_1.registerToolset)('mcp_admin', [
|
|
170
171
|
mcp_1.mcpRestartTool,
|
|
171
172
|
mcp_1.mcpReleaseTool,
|
|
173
|
+
mcp_1.mcpDisableTool,
|
|
172
174
|
env_1.envGetTool,
|
|
173
175
|
env_1.envSetTool,
|
|
174
176
|
env_1.envUnsetTool,
|