@loop_ouroboros/mcp-hub-lite 1.2.0 → 1.2.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/CHANGELOG.md +23 -4
- package/README.md +12 -8
- package/dist/client/assets/{HomeView-BBwvy1oj.js → HomeView-V1fKvWQ8.js} +1 -1
- package/dist/client/assets/{ResourceDetailView-CZ2aB73w.js → ResourceDetailView-DHGHssrh.js} +1 -1
- package/dist/client/assets/{ResourcesView-CN1NlhWs.js → ResourcesView-B1bvkmQD.js} +1 -1
- package/dist/client/assets/{ServerDashboard-k652Vw4Z.js → ServerDashboard-CZCByd7y.js} +1 -1
- package/dist/client/assets/{ServerDetail-BLQ-a4cO.js → ServerDetail-CI5UD8gj.js} +1 -1
- package/dist/client/assets/{ServerListView-BHrsFD5i.js → ServerListView-D8qv-xYg.js} +1 -1
- package/dist/client/assets/SettingsView-C-ae0-zz.js +1 -0
- package/dist/client/assets/{ToolCallDialog-BfPjLxfV.js → ToolCallDialog-BudOyGvS.js} +1 -1
- package/dist/client/assets/{ToolsView-CyuhYAE2.js → ToolsView-CbQkgTAu.js} +1 -1
- package/dist/client/assets/{_baseClone-DO5qfalW.js → _baseClone-e9R6V78L.js} +1 -1
- package/dist/client/assets/{el-form-item-CcGsD2K_.js → el-form-item-Dyx5MiWB.js} +1 -1
- package/dist/client/assets/{el-input-tYgeiaCT.js → el-input-CL9HPfdW.js} +1 -1
- package/dist/client/assets/{el-loading-Dwl9E_Vr.js → el-loading-2TW6JdfY.js} +1 -1
- package/dist/client/assets/{el-overlay-kqX_BABo.js → el-overlay-B5ZGCmXY.js} +1 -1
- package/dist/client/assets/{el-radio-group-D8aWBVOT.js → el-radio-group-Cr2ScjjJ.js} +1 -1
- package/dist/client/assets/{el-skeleton-item-BRwIFspE.js → el-skeleton-item-CdAfEgVR.js} +1 -1
- package/dist/client/assets/{el-switch-BF8c-xeU.js → el-switch-DnN1s0Wb.js} +1 -1
- package/dist/client/assets/{el-tab-pane-C4Ep94cd.js → el-tab-pane-BebZh0XF.js} +1 -1
- package/dist/client/assets/{el-table-column-Cog6uCh-.js → el-table-column-CV2zp3yI.js} +1 -1
- package/dist/client/assets/{index-ByNBhPAR.js → index-Ci5n5dA9.js} +1 -1
- package/dist/client/assets/index-DTZ9o3XO.js +2 -0
- package/dist/client/assets/{omit-CUnDT6sS.js → omit-DlmW8Yd6.js} +1 -1
- package/dist/client/assets/{raf-CmzeRPMd.js → raf-CeCd08aN.js} +1 -1
- package/dist/client/index.html +1 -1
- package/dist/server/shared/models/server.model.d.ts +22 -0
- package/dist/server/shared/models/server.model.d.ts.map +1 -1
- package/dist/server/shared/models/server.model.js +41 -5
- package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
- package/dist/server/src/api/mcp/gateway.js +13 -5
- package/dist/server/src/api/web/resources.d.ts.map +1 -1
- package/dist/server/src/api/web/resources.js +26 -2
- package/dist/server/src/cli/index.js +1 -1
- package/dist/server/src/config/config-loader.js +1 -1
- package/dist/server/src/config/config-migrator.d.ts.map +1 -1
- package/dist/server/src/config/config-migrator.js +1 -0
- package/dist/server/src/index.js +2 -7
- package/dist/server/src/server/dev-server.js +9 -48
- package/dist/server/src/server/runner.d.ts +12 -24
- package/dist/server/src/server/runner.d.ts.map +1 -1
- package/dist/server/src/server/runner.js +29 -109
- package/dist/server/src/server/startup.d.ts +43 -0
- package/dist/server/src/server/startup.d.ts.map +1 -0
- package/dist/server/src/server/startup.js +89 -0
- package/dist/server/src/services/connection/connection-manager.d.ts +52 -0
- package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
- package/dist/server/src/services/connection/connection-manager.js +283 -193
- package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
- package/dist/server/src/services/gateway/gateway.service.js +31 -10
- package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -1
- package/dist/server/src/services/gateway/global-transport.js +11 -5
- package/dist/server/src/services/hub-manager.service.d.ts +2 -0
- package/dist/server/src/services/hub-manager.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-manager.service.js +3 -16
- package/dist/server/src/utils/json-utils.d.ts +7 -0
- package/dist/server/src/utils/json-utils.d.ts.map +1 -1
- package/dist/server/src/utils/json-utils.js +17 -0
- package/dist/server/src/utils/logger/log-modules.d.ts +3 -0
- package/dist/server/src/utils/logger/log-modules.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-modules.js +2 -0
- package/dist/server/src/utils/port-checker.d.ts +18 -0
- package/dist/server/src/utils/port-checker.d.ts.map +1 -1
- package/dist/server/src/utils/port-checker.js +38 -0
- package/dist/server/src/utils/transports/stdio-transport.d.ts +12 -0
- package/dist/server/src/utils/transports/stdio-transport.d.ts.map +1 -1
- package/dist/server/src/utils/transports/stdio-transport.js +51 -2
- package/dist/server/src/utils/transports/transport-factory.d.ts +5 -1
- package/dist/server/src/utils/transports/transport-factory.d.ts.map +1 -1
- package/dist/server/src/utils/transports/transport-factory.js +5 -2
- package/dist/server/tests/integration/gateway/fault-tolerance.test.js +13 -2
- package/dist/server/tests/integration/gateway/mcp-connection.test.js +13 -2
- package/dist/server/tests/unit/config/config-migrator.test.js +4 -2
- package/dist/server/tests/unit/config/config.schema.test.js +2 -1
- package/dist/server/tests/unit/server/runner.test.js +77 -92
- package/dist/server/tests/unit/services/hub-manager-service.test.js +3 -2
- package/dist/server/tests/unit/utils/config.test.js +14 -7
- package/dist/server/tests/unit/utils/json-utils.test.js +28 -14
- package/dist/server/vite.config.d.ts.map +1 -1
- package/dist/server/vite.config.js +1 -0
- package/package.json +1 -1
- package/dist/client/assets/SettingsView-CUOFNXrz.js +0 -1
- package/dist/client/assets/index-CTB6oe-9.js +0 -2
|
@@ -62,6 +62,8 @@ export declare class HubManagerService {
|
|
|
62
62
|
addServer(name: string, config: Partial<ServerTemplate>): Promise<ServerConfig>;
|
|
63
63
|
/**
|
|
64
64
|
* Adds a new instance to an existing server.
|
|
65
|
+
* Note: This method only creates the instance without auto-connect.
|
|
66
|
+
* Use connectServerInstances() explicitly to connect after adding instances.
|
|
65
67
|
*/
|
|
66
68
|
addServerInstance(name: string, instance: Partial<ServerInstance>): Promise<ServerInstance>;
|
|
67
69
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hub-manager.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-manager.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,YAAY,EACZ,cAAc,EACd,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EACV,mBAAmB,EACnB,yBAAyB,EAC1B,MAAM,gCAAgC,CAAC;AAKxC;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,GAAE,aAA6B;IAIlD;;OAEG;IACG,0BAA0B,CAC9B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC,GAChE,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,gCAAgC,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"hub-manager.service.d.ts","sourceRoot":"","sources":["../../../../src/services/hub-manager.service.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,YAAY,EACZ,cAAc,EACd,cAAc,EACf,MAAM,2BAA2B,CAAC;AAEnC,OAAO,KAAK,EACV,mBAAmB,EACnB,yBAAyB,EAC1B,MAAM,gCAAgC,CAAC;AAKxC;;;;;;GAMG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,aAAa,CAAgB;gBAEzB,OAAO,GAAE,aAA6B;IAIlD;;OAEG;IACG,0BAA0B,CAC9B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;KAAE,CAAC,GAChE,OAAO,CAAC,IAAI,CAAC;IAUhB;;OAEG;IACG,gCAAgC,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAM5E;;OAEG;IACG,sBAAsB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IA8BlE;;OAEG;IACH,aAAa,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,CAAC;IAI9D;;OAEG;IACH,aAAa,CACX,EAAE,EAAE,MAAM,GACT;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,YAAY,CAAC;QAAC,QAAQ,EAAE,cAAc,CAAA;KAAE,GAAG,SAAS;IAe/E;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,SAAS;IAIvD;;OAEG;IACH,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE;IAIxD;;OAEG;IACH,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC;IAStD;;OAEG;IACH,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,mBAAmB,GAAG,IAAI;IAQtF;;OAEG;IACG,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC;IAOrF;;;;OAIG;IACG,iBAAiB,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC;IAQ1B;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAkBhG;;OAEG;IACG,oBAAoB,CACxB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,OAAO,CAAC,cAAc,CAAC,GAC/B,OAAO,CAAC,IAAI,CAAC;IAShB;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiBlD;;OAEG;IACG,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAetE;;OAEG;IACG,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI7D;;OAEG;IACG,qCAAqC,CACzC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,yBAAyB,GAClC,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAwBhC;AAED,eAAO,MAAM,UAAU,mBAA0B,CAAC"}
|
|
@@ -32,10 +32,7 @@ export class HubManagerService {
|
|
|
32
32
|
*/
|
|
33
33
|
async addServerInstancesWithoutConnect(serverNames) {
|
|
34
34
|
for (const name of serverNames) {
|
|
35
|
-
await this.
|
|
36
|
-
const instances = this.getServerInstancesByName(name);
|
|
37
|
-
const lastInstance = instances[instances.length - 1];
|
|
38
|
-
eventBus.publish(EventTypes.SERVER_INSTANCE_ADDED, { name, instance: lastInstance });
|
|
35
|
+
await this.addServerInstance(name, {});
|
|
39
36
|
}
|
|
40
37
|
}
|
|
41
38
|
/**
|
|
@@ -133,22 +130,12 @@ export class HubManagerService {
|
|
|
133
130
|
}
|
|
134
131
|
/**
|
|
135
132
|
* Adds a new instance to an existing server.
|
|
133
|
+
* Note: This method only creates the instance without auto-connect.
|
|
134
|
+
* Use connectServerInstances() explicitly to connect after adding instances.
|
|
136
135
|
*/
|
|
137
136
|
async addServerInstance(name, instance) {
|
|
138
137
|
const newInstance = await this.configManager.addServerInstance(name, instance);
|
|
139
138
|
logger.info(`Server instance added for server: [${name}]`, LOG_MODULES.HUB_MANAGER);
|
|
140
|
-
const resolvedConfig = this.getResolvedServerConfig(name, newInstance.id);
|
|
141
|
-
if (resolvedConfig && resolvedConfig.enabled !== false) {
|
|
142
|
-
try {
|
|
143
|
-
await mcpConnectionManager.connect(name, newInstance.index ?? 0, {
|
|
144
|
-
...resolvedConfig,
|
|
145
|
-
id: newInstance.id
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
catch (error) {
|
|
149
|
-
logger.error(`Failed to auto-connect server instance for ${name}:`, error, LOG_MODULES.HUB_MANAGER);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
139
|
eventBus.publish(EventTypes.SERVER_INSTANCE_ADDED, { name, instance: newInstance });
|
|
153
140
|
return newInstance;
|
|
154
141
|
}
|
|
@@ -24,6 +24,7 @@ type ConfigGetter = () => {
|
|
|
24
24
|
jsonPretty: boolean;
|
|
25
25
|
mcpCommDebug: boolean;
|
|
26
26
|
apiDebug: boolean;
|
|
27
|
+
gatewayDebug: boolean;
|
|
27
28
|
};
|
|
28
29
|
};
|
|
29
30
|
};
|
|
@@ -65,6 +66,12 @@ export declare function getMcpCommDebugSetting(): boolean;
|
|
|
65
66
|
* @returns boolean indicating whether to enable API debug logging
|
|
66
67
|
*/
|
|
67
68
|
export declare function getApiDebugSetting(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Get Gateway debug setting from config getter.
|
|
71
|
+
*
|
|
72
|
+
* @returns boolean indicating whether to enable Gateway debug logging
|
|
73
|
+
*/
|
|
74
|
+
export declare function getGatewayDebugSetting(): boolean;
|
|
68
75
|
/**
|
|
69
76
|
* Stringify object for logging with dynamic pretty formatting based on LOG_JSON_PRETTY environment variable
|
|
70
77
|
* @param obj Object to stringify
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"json-utils.d.ts","sourceRoot":"","sources":["../../../../src/utils/json-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAiED;;GAEG;AACH,KAAK,YAAY,GAAG,MAAM;IACxB,MAAM,EAAE;QACN,OAAO,EAAE;YACP,UAAU,EAAE,OAAO,CAAC;YACpB,YAAY,EAAE,OAAO,CAAC;YACtB,QAAQ,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"json-utils.d.ts","sourceRoot":"","sources":["../../../../src/utils/json-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,OAAO,CAE1C;AAiED;;GAEG;AACH,KAAK,YAAY,GAAG,MAAM;IACxB,MAAM,EAAE;QACN,OAAO,EAAE;YACP,UAAU,EAAE,OAAO,CAAC;YACpB,YAAY,EAAE,OAAO,CAAC;YACtB,QAAQ,EAAE,OAAO,CAAC;YAClB,YAAY,EAAE,OAAO,CAAC;SACvB,CAAC;KACH,CAAC;CACH,CAAC;AAQF;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAE3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAU/E;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAAC,UAAU,EAAE,MAAM,EAAE,GAAG,MAAM,CAG1E;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAiB9C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAU5C;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,OAAO,CAUhD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAOxD;AAED;;;;;GAKG;AACH,wBAAgB,+BAA+B,CAC7C,GAAG,EAAE,OAAO,EACZ,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,GAClD,MAAM,CAOR"}
|
|
@@ -181,6 +181,23 @@ export function getApiDebugSetting() {
|
|
|
181
181
|
}
|
|
182
182
|
return getDefaultForDevMode(false);
|
|
183
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* Get Gateway debug setting from config getter.
|
|
186
|
+
*
|
|
187
|
+
* @returns boolean indicating whether to enable Gateway debug logging
|
|
188
|
+
*/
|
|
189
|
+
export function getGatewayDebugSetting() {
|
|
190
|
+
if (_configGetter) {
|
|
191
|
+
try {
|
|
192
|
+
const config = _configGetter();
|
|
193
|
+
return config.system.logging.gatewayDebug;
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
// Fall through to default if config getter fails
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return getDefaultForDevMode(false);
|
|
200
|
+
}
|
|
184
201
|
/**
|
|
185
202
|
* Stringify object for logging with dynamic pretty formatting based on LOG_JSON_PRETTY environment variable
|
|
186
203
|
* @param obj Object to stringify
|
|
@@ -117,6 +117,9 @@ export declare const LOG_MODULES: {
|
|
|
117
117
|
readonly NOTIFICATIONS_MESSAGE: {
|
|
118
118
|
module: string;
|
|
119
119
|
};
|
|
120
|
+
readonly STDERR: {
|
|
121
|
+
module: string;
|
|
122
|
+
};
|
|
120
123
|
/**
|
|
121
124
|
* Creates a dynamic log module for custom or runtime-generated module names.
|
|
122
125
|
* Use this for server-specific logging or other dynamic contexts.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"log-modules.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-modules.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW
|
|
1
|
+
{"version":3,"file":"log-modules.d.ts","sourceRoot":"","sources":["../../../../../src/utils/logger/log-modules.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAiEtB;;;;;;;;;;;OAWG;mCACmB,MAAM;;;CACpB,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,OAAO,WAAW,EAAE,SAAS,CAAC,CAAC;AAErE;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,YAAY,CAAC,CAAC"}
|
|
@@ -65,6 +65,8 @@ export const LOG_MODULES = {
|
|
|
65
65
|
MCP_STATUS: { module: 'MCPStatus' },
|
|
66
66
|
// Notifications
|
|
67
67
|
NOTIFICATIONS_MESSAGE: { module: 'notifications/message' },
|
|
68
|
+
// Stderr output
|
|
69
|
+
STDERR: { module: 'stderr' },
|
|
68
70
|
/**
|
|
69
71
|
* Creates a dynamic log module for custom or runtime-generated module names.
|
|
70
72
|
* Use this for server-specific logging or other dynamic contexts.
|
|
@@ -13,4 +13,22 @@ export interface PortCheckResult {
|
|
|
13
13
|
* Check if port is in use
|
|
14
14
|
*/
|
|
15
15
|
export declare function checkPort(port: number): Promise<PortCheckResult>;
|
|
16
|
+
/**
|
|
17
|
+
* Checks port availability and exits process if port is in use.
|
|
18
|
+
*
|
|
19
|
+
* This function checks if the specified port is already occupied and handles
|
|
20
|
+
* conflict scenarios with detailed error messages.
|
|
21
|
+
*
|
|
22
|
+
* @param port - The port number to check
|
|
23
|
+
* @returns Promise that resolves when port is available, never rejects
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```typescript
|
|
27
|
+
* await checkPortWithExit(7788);
|
|
28
|
+
* // If port is available, continues execution
|
|
29
|
+
* // If port is in use by this project, shows error and exits with code 1
|
|
30
|
+
* // If port is in use by another application, shows error and exits with code 1
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkPortWithExit(port: number): Promise<void>;
|
|
16
34
|
//# sourceMappingURL=port-checker.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port-checker.d.ts","sourceRoot":"","sources":["../../../../src/utils/port-checker.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"port-checker.d.ts","sourceRoot":"","sources":["../../../../src/utils/port-checker.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAatE;AAmPD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BnE"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { exec } from 'child_process';
|
|
6
6
|
import { promisify } from 'util';
|
|
7
7
|
import { PidManager } from '../pid/manager.js';
|
|
8
|
+
import { logger, LOG_MODULES } from './logger.js';
|
|
8
9
|
const execAsync = promisify(exec);
|
|
9
10
|
/**
|
|
10
11
|
* Check if port is in use
|
|
@@ -240,3 +241,40 @@ async function isSelfProjectProcess(pid, commandLine) {
|
|
|
240
241
|
];
|
|
241
242
|
return projectSignatures.some((signature) => commandLine.includes(signature));
|
|
242
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* Checks port availability and exits process if port is in use.
|
|
246
|
+
*
|
|
247
|
+
* This function checks if the specified port is already occupied and handles
|
|
248
|
+
* conflict scenarios with detailed error messages.
|
|
249
|
+
*
|
|
250
|
+
* @param port - The port number to check
|
|
251
|
+
* @returns Promise that resolves when port is available, never rejects
|
|
252
|
+
*
|
|
253
|
+
* @example
|
|
254
|
+
* ```typescript
|
|
255
|
+
* await checkPortWithExit(7788);
|
|
256
|
+
* // If port is available, continues execution
|
|
257
|
+
* // If port is in use by this project, shows error and exits with code 1
|
|
258
|
+
* // If port is in use by another application, shows error and exits with code 1
|
|
259
|
+
* ```
|
|
260
|
+
*/
|
|
261
|
+
export async function checkPortWithExit(port) {
|
|
262
|
+
const portCheck = await checkPort(port);
|
|
263
|
+
if (portCheck.inUse) {
|
|
264
|
+
if (portCheck.isSelfProject) {
|
|
265
|
+
logger.error(`MCP Hub Lite is already running on port ${port} (PID: ${portCheck.pid})`, LOG_MODULES.SERVER);
|
|
266
|
+
logger.error(`Use 'npm run stop' or 'mcp-hub-lite stop' to stop the running instance.`, LOG_MODULES.SERVER);
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
logger.error(`Port ${port} is already in use by another application:`, LOG_MODULES.SERVER);
|
|
270
|
+
if (portCheck.processName) {
|
|
271
|
+
logger.error(` Process: ${portCheck.processName} (PID: ${portCheck.pid})`, LOG_MODULES.SERVER);
|
|
272
|
+
}
|
|
273
|
+
if (portCheck.commandLine) {
|
|
274
|
+
logger.error(` Command: ${portCheck.commandLine}`, LOG_MODULES.SERVER);
|
|
275
|
+
}
|
|
276
|
+
logger.error(`Please stop the conflicting application or use a different port.`, LOG_MODULES.SERVER);
|
|
277
|
+
}
|
|
278
|
+
process.exit(1);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
@@ -6,6 +6,8 @@ import { PassThrough } from 'stream';
|
|
|
6
6
|
export interface StdioTransportOptions {
|
|
7
7
|
compositeKey?: string;
|
|
8
8
|
logStorage?: LogStorageService;
|
|
9
|
+
readyPatterns?: string[];
|
|
10
|
+
readyTimeout: number;
|
|
9
11
|
}
|
|
10
12
|
/**
|
|
11
13
|
* A transport implementation for communicating with MCP (Model Context Protocol) servers
|
|
@@ -30,6 +32,8 @@ export declare class StdioTransport implements Transport {
|
|
|
30
32
|
private _compositeKey?;
|
|
31
33
|
private _logStorage?;
|
|
32
34
|
private _stderrStream;
|
|
35
|
+
private _readyPatterns?;
|
|
36
|
+
private _readyTimeout;
|
|
33
37
|
onclose?: () => void;
|
|
34
38
|
onerror?: (error: Error) => void;
|
|
35
39
|
onmessage?: (message: JSONRPCMessage) => void;
|
|
@@ -56,6 +60,14 @@ export declare class StdioTransport implements Transport {
|
|
|
56
60
|
* @throws {Error} If the transport is already started
|
|
57
61
|
*/
|
|
58
62
|
start(): Promise<void>;
|
|
63
|
+
/**
|
|
64
|
+
* Waits for the server to emit a ready pattern in stderr.
|
|
65
|
+
*
|
|
66
|
+
* @param patterns - Array of string patterns to match (any match = ready)
|
|
67
|
+
* @param timeout - Timeout in milliseconds
|
|
68
|
+
* @returns Promise that resolves when a pattern is matched, or rejects on timeout
|
|
69
|
+
*/
|
|
70
|
+
private waitForReady;
|
|
59
71
|
/**
|
|
60
72
|
* Gets the stderr stream for the child process.
|
|
61
73
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stdio-transport.d.ts","sourceRoot":"","sources":["../../../../../src/utils/transports/stdio-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,qBAAqB,EACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"stdio-transport.d.ts","sourceRoot":"","sources":["../../../../../src/utils/transports/stdio-transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,qBAAqB,EACtB,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAC1E,OAAO,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEpE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAErC,MAAM,WAAW,qBAAqB;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,iBAAiB,CAAC;IAE/B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IAEzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,cAAe,YAAW,SAAS;IAC9C,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAoB;IACxC,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,cAAc,CAAC,CAAW;IAClC,OAAO,CAAC,aAAa,CAAkB;IAEhC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,CAAC;IAC9C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAEzC;;;;;;OAMG;gBACS,MAAM,EAAE,qBAAqB,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,qBAAqB;IAmB/F;;;;;;;;;;;OAWG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2D5B;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;IAgCpB;;;;;;OAMG;IACH,IAAI,MAAM,uBAET;IAED;;;;OAIG;IACH,IAAW,GAAG,IAAI,MAAM,GAAG,SAAS,CAEnC;IAED;;;;;;;;OAQG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5B;;;;;;;OAOG;IACG,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAGnD"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
|
|
2
|
-
import { logger } from '../logger.js';
|
|
2
|
+
import { logger, LOG_MODULES } from '../logger.js';
|
|
3
3
|
import { PassThrough } from 'stream';
|
|
4
4
|
/**
|
|
5
5
|
* A transport implementation for communicating with MCP (Model Context Protocol) servers
|
|
@@ -24,6 +24,8 @@ export class StdioTransport {
|
|
|
24
24
|
_compositeKey;
|
|
25
25
|
_logStorage;
|
|
26
26
|
_stderrStream = null;
|
|
27
|
+
_readyPatterns;
|
|
28
|
+
_readyTimeout = 120000;
|
|
27
29
|
onclose;
|
|
28
30
|
onerror;
|
|
29
31
|
onmessage;
|
|
@@ -49,6 +51,8 @@ export class StdioTransport {
|
|
|
49
51
|
this._serverName = serverName;
|
|
50
52
|
this._compositeKey = options?.compositeKey;
|
|
51
53
|
this._logStorage = options?.logStorage;
|
|
54
|
+
this._readyPatterns = options?.readyPatterns;
|
|
55
|
+
this._readyTimeout = options?.readyTimeout ?? 120000;
|
|
52
56
|
this._stderrStream = new PassThrough();
|
|
53
57
|
}
|
|
54
58
|
/**
|
|
@@ -76,6 +80,12 @@ export class StdioTransport {
|
|
|
76
80
|
};
|
|
77
81
|
// Start the underlying transport
|
|
78
82
|
await this._transport.start();
|
|
83
|
+
// Ready detection: wait for server to output ready pattern
|
|
84
|
+
if (this._readyPatterns && this._readyPatterns.length > 0) {
|
|
85
|
+
logger.info(`Waiting for server ready patterns: ${JSON.stringify(this._readyPatterns)}`, LOG_MODULES.STDIO_TRANSPORT);
|
|
86
|
+
await this.waitForReady(this._readyPatterns, this._readyTimeout);
|
|
87
|
+
logger.info(`Server ready pattern detected, proceeding with MCP handshake`, LOG_MODULES.STDIO_TRANSPORT);
|
|
88
|
+
}
|
|
79
89
|
// Handle stderr data by listening to the transport's stderr stream
|
|
80
90
|
if (this._transport.stderr) {
|
|
81
91
|
this._transport.stderr.on('data', (chunk) => {
|
|
@@ -86,7 +96,10 @@ export class StdioTransport {
|
|
|
86
96
|
this.onstderr?.(dataStr);
|
|
87
97
|
// Log stderr output (per MCP spec, stderr is not necessarily errors)
|
|
88
98
|
const serverIdentifier = this._compositeKey || this._serverName || 'Unknown Server';
|
|
89
|
-
logger.serverLog('info', serverIdentifier, dataStr, {
|
|
99
|
+
logger.serverLog('info', serverIdentifier, dataStr, {
|
|
100
|
+
pid: this.pid,
|
|
101
|
+
module: LOG_MODULES.STDERR.module
|
|
102
|
+
});
|
|
90
103
|
if (this._logStorage && this._compositeKey) {
|
|
91
104
|
this._logStorage.append(this._compositeKey, 'info', dataStr);
|
|
92
105
|
}
|
|
@@ -98,6 +111,42 @@ export class StdioTransport {
|
|
|
98
111
|
});
|
|
99
112
|
}
|
|
100
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Waits for the server to emit a ready pattern in stderr.
|
|
116
|
+
*
|
|
117
|
+
* @param patterns - Array of string patterns to match (any match = ready)
|
|
118
|
+
* @param timeout - Timeout in milliseconds
|
|
119
|
+
* @returns Promise that resolves when a pattern is matched, or rejects on timeout
|
|
120
|
+
*/
|
|
121
|
+
waitForReady(patterns, timeout) {
|
|
122
|
+
return new Promise((resolve, reject) => {
|
|
123
|
+
const timeoutId = setTimeout(() => {
|
|
124
|
+
reject(new Error(`Server did not emit any ready pattern within ${timeout}ms`));
|
|
125
|
+
}, timeout);
|
|
126
|
+
// Hook into stderr before it's set up in start()
|
|
127
|
+
// The ready detection needs to intercept stderr BEFORE the normal stderr handler
|
|
128
|
+
const readyStderrHandler = (chunk) => {
|
|
129
|
+
const dataStr = chunk.toString('utf8').trim();
|
|
130
|
+
if (!dataStr)
|
|
131
|
+
return;
|
|
132
|
+
// Check if any pattern matches
|
|
133
|
+
for (const pattern of patterns) {
|
|
134
|
+
if (dataStr.includes(pattern)) {
|
|
135
|
+
clearTimeout(timeoutId);
|
|
136
|
+
// Remove this listener - normal stderr handling will be set up in start()
|
|
137
|
+
this._transport.stderr?.off('data', readyStderrHandler);
|
|
138
|
+
logger.info(`Server ready pattern matched: "${pattern}"`, LOG_MODULES.STDIO_TRANSPORT);
|
|
139
|
+
resolve();
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
// Add the ready detection listener to stderr
|
|
145
|
+
if (this._transport.stderr) {
|
|
146
|
+
this._transport.stderr.on('data', readyStderrHandler);
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
}
|
|
101
150
|
/**
|
|
102
151
|
* Gets the stderr stream for the child process.
|
|
103
152
|
*
|
|
@@ -7,12 +7,16 @@ export declare class TransportFactory {
|
|
|
7
7
|
* Create transport client
|
|
8
8
|
* @param server Server configuration, including base configuration and instance configuration
|
|
9
9
|
* @param compositeKey Optional composite key (serverName-serverIndex) for log storage integration
|
|
10
|
+
* @param options Optional transport options including readyPatterns and readyTimeout
|
|
10
11
|
* @returns Transport client instance
|
|
11
12
|
* @throws Error if server type is not supported or configuration is invalid
|
|
12
13
|
*/
|
|
13
14
|
static createTransport(server: ServerRuntimeConfig & {
|
|
14
15
|
name: string;
|
|
15
|
-
}, compositeKey?: string
|
|
16
|
+
}, compositeKey?: string, options?: {
|
|
17
|
+
readyPatterns?: string[];
|
|
18
|
+
readyTimeout?: number;
|
|
19
|
+
}): import('@modelcontextprotocol/sdk/shared/transport.js').Transport;
|
|
16
20
|
/**
|
|
17
21
|
* Build system environment variables
|
|
18
22
|
* Add necessary system environment variables for stdio transport
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"transport-factory.d.ts","sourceRoot":"","sources":["../../../../../src/utils/transports/transport-factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E;;GAEG;AACH,qBAAa,gBAAgB;IAC3B
|
|
1
|
+
{"version":3,"file":"transport-factory.d.ts","sourceRoot":"","sources":["../../../../../src/utils/transports/transport-factory.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AAG1E;;GAEG;AACH,qBAAa,gBAAgB;IAC3B;;;;;;;OAOG;IACH,MAAM,CAAC,eAAe,CACpB,MAAM,EAAE,mBAAmB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAC9C,YAAY,CAAC,EAAE,MAAM,EACrB,OAAO,CAAC,EAAE;QACR,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;QACzB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,GACA,OAAO,+CAA+C,EAAE,SAAS;IA+DpE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAW7B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAW9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;CA8CxC"}
|
|
@@ -10,10 +10,11 @@ export class TransportFactory {
|
|
|
10
10
|
* Create transport client
|
|
11
11
|
* @param server Server configuration, including base configuration and instance configuration
|
|
12
12
|
* @param compositeKey Optional composite key (serverName-serverIndex) for log storage integration
|
|
13
|
+
* @param options Optional transport options including readyPatterns and readyTimeout
|
|
13
14
|
* @returns Transport client instance
|
|
14
15
|
* @throws Error if server type is not supported or configuration is invalid
|
|
15
16
|
*/
|
|
16
|
-
static createTransport(server, compositeKey) {
|
|
17
|
+
static createTransport(server, compositeKey, options) {
|
|
17
18
|
const transportConfig = this.validateAndConvertConfig(server);
|
|
18
19
|
// Use type assertion to ensure TypeScript can correctly infer types
|
|
19
20
|
const config = transportConfig;
|
|
@@ -30,7 +31,9 @@ export class TransportFactory {
|
|
|
30
31
|
stderr: 'pipe'
|
|
31
32
|
}, server.name, {
|
|
32
33
|
compositeKey,
|
|
33
|
-
logStorage: compositeKey ? logStorage : undefined
|
|
34
|
+
logStorage: compositeKey ? logStorage : undefined,
|
|
35
|
+
readyPatterns: options?.readyPatterns,
|
|
36
|
+
readyTimeout: options?.readyTimeout ?? 120000
|
|
34
37
|
});
|
|
35
38
|
case 'sse':
|
|
36
39
|
if (!config.url) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
|
2
2
|
import { mcpConnectionManager } from '../../../src/services/mcp-connection-manager.js';
|
|
3
3
|
import { hubManager } from '../../../src/services/hub-manager.service.js';
|
|
4
|
+
import { configManager } from '../../../src/config/config-manager.js';
|
|
4
5
|
import { resolveInstanceConfig } from '../../../src/config/config-migrator.js';
|
|
5
6
|
// Mock MCP SDK Client
|
|
6
7
|
const mockConnect = vi.fn();
|
|
@@ -32,8 +33,17 @@ vi.mock('@utils/transports/transport-factory.js', () => {
|
|
|
32
33
|
describe('Gateway Fault Tolerance', () => {
|
|
33
34
|
let mockServerInstance;
|
|
34
35
|
beforeEach(async () => {
|
|
35
|
-
// Clear
|
|
36
|
+
// Clear mock call history
|
|
36
37
|
vi.clearAllMocks();
|
|
38
|
+
// Mock config to reduce retry delay in tests (maxRetries: 1, delay: 10ms)
|
|
39
|
+
vi.spyOn(configManager, 'getConfig').mockReturnValue({
|
|
40
|
+
system: {
|
|
41
|
+
startup: {
|
|
42
|
+
maxConnectRetries: 1,
|
|
43
|
+
connectRetryDelay: 10
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
37
47
|
// Add test server (v1.1 format)
|
|
38
48
|
await hubManager.addServer('test-server', {
|
|
39
49
|
command: 'node',
|
|
@@ -51,7 +61,8 @@ describe('Gateway Fault Tolerance', () => {
|
|
|
51
61
|
};
|
|
52
62
|
});
|
|
53
63
|
it('should handle connection failure gracefully', async () => {
|
|
54
|
-
|
|
64
|
+
// Use mockRejectedValue instead of mockRejectedValueOnce to avoid retry delay
|
|
65
|
+
mockConnect.mockRejectedValue(new Error('Connection failed'));
|
|
55
66
|
// Directly use hubManager.getServerById to get complete server configuration
|
|
56
67
|
const serverInfo = hubManager.getServerById(mockServerInstance.id);
|
|
57
68
|
if (!serverInfo) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
|
2
2
|
import { mcpConnectionManager } from '../../../src/services/mcp-connection-manager.js';
|
|
3
3
|
import { hubManager } from '../../../src/services/hub-manager.service.js';
|
|
4
|
+
import { configManager } from '../../../src/config/config-manager.js';
|
|
4
5
|
import { resolveInstanceConfig } from '../../../src/config/config-migrator.js';
|
|
5
6
|
// Mock MCP SDK Client
|
|
6
7
|
const mockConnect = vi.fn();
|
|
@@ -34,8 +35,17 @@ describe('MCP Connection Integration', () => {
|
|
|
34
35
|
let serverId;
|
|
35
36
|
let serverIndex;
|
|
36
37
|
beforeEach(async () => {
|
|
37
|
-
// Clear
|
|
38
|
+
// Clear mock call history but keep implementations
|
|
38
39
|
vi.clearAllMocks();
|
|
40
|
+
// Mock config to reduce retry delay in tests (maxRetries: 1, delay: 10ms)
|
|
41
|
+
vi.spyOn(configManager, 'getConfig').mockReturnValue({
|
|
42
|
+
system: {
|
|
43
|
+
startup: {
|
|
44
|
+
maxConnectRetries: 1,
|
|
45
|
+
connectRetryDelay: 10
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
});
|
|
39
49
|
// Add test server (v1.1 format)
|
|
40
50
|
await hubManager.addServer(serverName, {
|
|
41
51
|
command: 'node',
|
|
@@ -74,7 +84,8 @@ describe('MCP Connection Integration', () => {
|
|
|
74
84
|
expect(status?.connected).toBe(true);
|
|
75
85
|
});
|
|
76
86
|
it('should handle connection errors properly', async () => {
|
|
77
|
-
|
|
87
|
+
// Use mockRejectedValue instead of mockRejectedValueOnce to avoid retry delay
|
|
88
|
+
mockConnect.mockRejectedValue(new Error('Connection refused'));
|
|
78
89
|
const serverInfo = hubManager.getServerById(serverId);
|
|
79
90
|
if (!serverInfo) {
|
|
80
91
|
throw new Error('Server not found');
|
|
@@ -45,7 +45,8 @@ describe('Config Migrator', () => {
|
|
|
45
45
|
rotationAge: '7d',
|
|
46
46
|
jsonPretty: true,
|
|
47
47
|
mcpCommDebug: false,
|
|
48
|
-
apiDebug: false
|
|
48
|
+
apiDebug: false,
|
|
49
|
+
gatewayDebug: false
|
|
49
50
|
}
|
|
50
51
|
},
|
|
51
52
|
security: {
|
|
@@ -111,7 +112,8 @@ describe('Config Migrator', () => {
|
|
|
111
112
|
rotationAge: '7d',
|
|
112
113
|
jsonPretty: true,
|
|
113
114
|
mcpCommDebug: false,
|
|
114
|
-
apiDebug: false
|
|
115
|
+
apiDebug: false,
|
|
116
|
+
gatewayDebug: false
|
|
115
117
|
}
|
|
116
118
|
},
|
|
117
119
|
security: {
|