@loop_ouroboros/mcp-hub-lite 1.2.1 → 1.2.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.
Files changed (96) hide show
  1. package/CHANGELOG.md +541 -366
  2. package/README.md +4 -0
  3. package/dist/client/assets/{HomeView-BBwvy1oj.js → HomeView-V1fKvWQ8.js} +1 -1
  4. package/dist/client/assets/{ResourceDetailView-CZ2aB73w.js → ResourceDetailView-DHGHssrh.js} +1 -1
  5. package/dist/client/assets/{ResourcesView-CN1NlhWs.js → ResourcesView-B1bvkmQD.js} +1 -1
  6. package/dist/client/assets/{ServerDashboard-k652Vw4Z.js → ServerDashboard-CZCByd7y.js} +1 -1
  7. package/dist/client/assets/{ServerDetail-BLQ-a4cO.js → ServerDetail-CI5UD8gj.js} +1 -1
  8. package/dist/client/assets/{ServerListView-BHrsFD5i.js → ServerListView-D8qv-xYg.js} +1 -1
  9. package/dist/client/assets/SettingsView-C-ae0-zz.js +1 -0
  10. package/dist/client/assets/{ToolCallDialog-BfPjLxfV.js → ToolCallDialog-BudOyGvS.js} +1 -1
  11. package/dist/client/assets/{ToolsView-CyuhYAE2.js → ToolsView-CbQkgTAu.js} +1 -1
  12. package/dist/client/assets/{_baseClone-DO5qfalW.js → _baseClone-e9R6V78L.js} +1 -1
  13. package/dist/client/assets/{el-form-item-CcGsD2K_.js → el-form-item-Dyx5MiWB.js} +1 -1
  14. package/dist/client/assets/{el-input-tYgeiaCT.js → el-input-CL9HPfdW.js} +1 -1
  15. package/dist/client/assets/{el-loading-Dwl9E_Vr.js → el-loading-2TW6JdfY.js} +1 -1
  16. package/dist/client/assets/{el-overlay-kqX_BABo.js → el-overlay-B5ZGCmXY.js} +1 -1
  17. package/dist/client/assets/{el-radio-group-D8aWBVOT.js → el-radio-group-Cr2ScjjJ.js} +1 -1
  18. package/dist/client/assets/{el-skeleton-item-BRwIFspE.js → el-skeleton-item-CdAfEgVR.js} +1 -1
  19. package/dist/client/assets/{el-switch-BF8c-xeU.js → el-switch-DnN1s0Wb.js} +1 -1
  20. package/dist/client/assets/{el-tab-pane-C4Ep94cd.js → el-tab-pane-BebZh0XF.js} +1 -1
  21. package/dist/client/assets/{el-table-column-Cog6uCh-.js → el-table-column-CV2zp3yI.js} +1 -1
  22. package/dist/client/assets/{index-ByNBhPAR.js → index-Ci5n5dA9.js} +1 -1
  23. package/dist/client/assets/index-DTZ9o3XO.js +2 -0
  24. package/dist/client/assets/{omit-CUnDT6sS.js → omit-DlmW8Yd6.js} +1 -1
  25. package/dist/client/assets/{raf-CmzeRPMd.js → raf-CeCd08aN.js} +1 -1
  26. package/dist/client/index.html +1 -1
  27. package/dist/server/shared/models/server.model.d.ts +22 -0
  28. package/dist/server/shared/models/server.model.d.ts.map +1 -1
  29. package/dist/server/shared/models/server.model.js +41 -5
  30. package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
  31. package/dist/server/src/api/mcp/gateway.js +13 -5
  32. package/dist/server/src/api/web/resources.d.ts.map +1 -1
  33. package/dist/server/src/api/web/resources.js +26 -2
  34. package/dist/server/src/cli/commands/install.d.ts +25 -0
  35. package/dist/server/src/cli/commands/install.d.ts.map +1 -0
  36. package/dist/server/src/cli/commands/install.js +274 -0
  37. package/dist/server/src/cli/commands/use-guide.d.ts +11 -0
  38. package/dist/server/src/cli/commands/use-guide.d.ts.map +1 -0
  39. package/dist/server/src/cli/commands/use-guide.js +175 -0
  40. package/dist/server/src/cli/index.d.ts.map +1 -1
  41. package/dist/server/src/cli/index.js +4 -0
  42. package/dist/server/src/cli/server.d.ts +71 -0
  43. package/dist/server/src/cli/server.d.ts.map +1 -1
  44. package/dist/server/src/cli/server.js +138 -0
  45. package/dist/server/src/cli/use-guide.md +156 -0
  46. package/dist/server/src/config/config-loader.js +1 -1
  47. package/dist/server/src/config/config-migrator.d.ts.map +1 -1
  48. package/dist/server/src/config/config-migrator.js +1 -0
  49. package/dist/server/src/index.js +2 -7
  50. package/dist/server/src/server/dev-server.js +9 -48
  51. package/dist/server/src/server/runner.d.ts +12 -24
  52. package/dist/server/src/server/runner.d.ts.map +1 -1
  53. package/dist/server/src/server/runner.js +29 -109
  54. package/dist/server/src/server/startup.d.ts +43 -0
  55. package/dist/server/src/server/startup.d.ts.map +1 -0
  56. package/dist/server/src/server/startup.js +89 -0
  57. package/dist/server/src/services/connection/connection-manager.d.ts +52 -0
  58. package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
  59. package/dist/server/src/services/connection/connection-manager.js +283 -193
  60. package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
  61. package/dist/server/src/services/gateway/gateway.service.js +31 -10
  62. package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -1
  63. package/dist/server/src/services/gateway/global-transport.js +11 -5
  64. package/dist/server/src/services/gateway/request-handlers/initialize-handler.d.ts.map +1 -1
  65. package/dist/server/src/services/gateway/request-handlers/initialize-handler.js +12 -5
  66. package/dist/server/src/services/hub-manager.service.d.ts +2 -0
  67. package/dist/server/src/services/hub-manager.service.d.ts.map +1 -1
  68. package/dist/server/src/services/hub-manager.service.js +3 -16
  69. package/dist/server/src/utils/json-utils.d.ts +7 -0
  70. package/dist/server/src/utils/json-utils.d.ts.map +1 -1
  71. package/dist/server/src/utils/json-utils.js +17 -0
  72. package/dist/server/src/utils/logger/log-modules.d.ts +3 -0
  73. package/dist/server/src/utils/logger/log-modules.d.ts.map +1 -1
  74. package/dist/server/src/utils/logger/log-modules.js +2 -0
  75. package/dist/server/src/utils/port-checker.d.ts +18 -0
  76. package/dist/server/src/utils/port-checker.d.ts.map +1 -1
  77. package/dist/server/src/utils/port-checker.js +38 -0
  78. package/dist/server/src/utils/transports/stdio-transport.d.ts +12 -0
  79. package/dist/server/src/utils/transports/stdio-transport.d.ts.map +1 -1
  80. package/dist/server/src/utils/transports/stdio-transport.js +51 -2
  81. package/dist/server/src/utils/transports/transport-factory.d.ts +5 -1
  82. package/dist/server/src/utils/transports/transport-factory.d.ts.map +1 -1
  83. package/dist/server/src/utils/transports/transport-factory.js +5 -2
  84. package/dist/server/tests/integration/gateway/fault-tolerance.test.js +13 -2
  85. package/dist/server/tests/integration/gateway/mcp-connection.test.js +13 -2
  86. package/dist/server/tests/unit/config/config-migrator.test.js +4 -2
  87. package/dist/server/tests/unit/config/config.schema.test.js +2 -1
  88. package/dist/server/tests/unit/server/runner.test.js +77 -92
  89. package/dist/server/tests/unit/services/hub-manager-service.test.js +3 -2
  90. package/dist/server/tests/unit/utils/config.test.js +14 -7
  91. package/dist/server/tests/unit/utils/json-utils.test.js +28 -14
  92. package/dist/server/vite.config.d.ts.map +1 -1
  93. package/dist/server/vite.config.js +1 -0
  94. package/package.json +1 -5
  95. package/dist/client/assets/SettingsView-CUOFNXrz.js +0 -1
  96. package/dist/client/assets/index-CTB6oe-9.js +0 -2
@@ -1 +1 @@
1
- {"version":3,"file":"initialize-handler.d.ts","sourceRoot":"","sources":["../../../../../../src/services/gateway/request-handlers/initialize-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAWpE;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA+DlE"}
1
+ {"version":3,"file":"initialize-handler.d.ts","sourceRoot":"","sources":["../../../../../../src/services/gateway/request-handlers/initialize-handler.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAYpE;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAqElE"}
@@ -1,4 +1,5 @@
1
1
  import { logger, LOG_MODULES } from '../../../utils/logger/index.js';
2
+ import { getGatewayDebugSetting } from '../../../utils/json-utils.js';
2
3
  import { MCP_HUB_LITE_SERVER } from '../../../models/system-tools.constants.js';
3
4
  import { getAppVersion, getProtocolVersion } from '../../../utils/version.js';
4
5
  import { InitializedNotificationSchema, InitializeRequestSchema, PingRequestSchema } from './initialize.constants.js';
@@ -13,8 +14,10 @@ export function registerInitializeHandlers(server) {
13
14
  const { name, version } = request.params.clientInfo;
14
15
  const protocolVersion = request.params?.protocolVersion || getProtocolVersion();
15
16
  const clientCapabilities = request.params?.capabilities;
16
- logger.debug(`Initialized client: Name=${name}, Version=${version}, ProtocolVersion=${protocolVersion}`, LOG_MODULES.GATEWAY);
17
- if (clientCapabilities?.roots) {
17
+ if (getGatewayDebugSetting()) {
18
+ logger.debug(`Initialized client: Name=${name}, Version=${version}, ProtocolVersion=${protocolVersion}`, LOG_MODULES.GATEWAY);
19
+ }
20
+ if (getGatewayDebugSetting() && clientCapabilities?.roots) {
18
21
  logger.debug(`Client ${name} supports roots capability`, LOG_MODULES.GATEWAY);
19
22
  }
20
23
  }
@@ -41,11 +44,15 @@ export function registerInitializeHandlers(server) {
41
44
  return { pong: true };
42
45
  });
43
46
  server.server.setNotificationHandler(InitializedNotificationSchema, async (notification) => {
44
- logger.debug('Received initialized notification from client', LOG_MODULES.GATEWAY);
45
- logger.debug(`Initialized notification details: ${JSON.stringify(notification)}`, LOG_MODULES.GATEWAY);
47
+ if (getGatewayDebugSetting()) {
48
+ logger.debug('Received initialized notification from client', LOG_MODULES.GATEWAY);
49
+ logger.debug(`Initialized notification details: ${JSON.stringify(notification)}`, LOG_MODULES.GATEWAY);
50
+ }
46
51
  try {
47
52
  // Process the notification
48
- logger.debug('Successfully processed initialized notification', LOG_MODULES.GATEWAY);
53
+ if (getGatewayDebugSetting()) {
54
+ logger.debug('Successfully processed initialized notification', LOG_MODULES.GATEWAY);
55
+ }
49
56
  }
50
57
  catch (error) {
51
58
  const errorMessage = error instanceof Error ? error.message : String(error);
@@ -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;IAS5E;;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;;OAEG;IACG,iBAAiB,CACrB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,CAAC,cAAc,CAAC,GAChC,OAAO,CAAC,cAAc,CAAC;IAwB1B;;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"}
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.configManager.addServerInstance(name, {});
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;SACnB,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,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"}
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IA8DtB;;;;;;;;;;;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"}
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;AAQH,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"}
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;CAChC;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;IAE1C,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;IAiB/F;;;;;;;;;;;OAWG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IA2C5B;;;;;;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
+ {"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, { pid: this.pid });
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): import('@modelcontextprotocol/sdk/shared/transport.js').Transport;
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;;;;;;OAMG;IACH,MAAM,CAAC,eAAe,CACpB,MAAM,EAAE,mBAAmB,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,EAC9C,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,+CAA+C,EAAE,SAAS;IA6DpE;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAW7B;;;OAGG;IACH,OAAO,CAAC,MAAM,CAAC,eAAe;IAW9B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAC,wBAAwB;CA8CxC"}
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 all mocks
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
- mockConnect.mockRejectedValueOnce(new Error('Connection failed'));
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 all mocks
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
- mockConnect.mockRejectedValueOnce(new Error('Connection refused'));
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: {
@@ -217,7 +217,8 @@ describe('Config Schema (v1.1)', () => {
217
217
  rotationAge: '7d',
218
218
  jsonPretty: true,
219
219
  mcpCommDebug: false,
220
- apiDebug: false
220
+ apiDebug: false,
221
+ gatewayDebug: false
221
222
  }
222
223
  },
223
224
  security: {