@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.
- package/CHANGELOG.md +541 -366
- package/README.md +4 -0
- 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/commands/install.d.ts +25 -0
- package/dist/server/src/cli/commands/install.d.ts.map +1 -0
- package/dist/server/src/cli/commands/install.js +274 -0
- package/dist/server/src/cli/commands/use-guide.d.ts +11 -0
- package/dist/server/src/cli/commands/use-guide.d.ts.map +1 -0
- package/dist/server/src/cli/commands/use-guide.js +175 -0
- package/dist/server/src/cli/index.d.ts.map +1 -1
- package/dist/server/src/cli/index.js +4 -0
- package/dist/server/src/cli/server.d.ts +71 -0
- package/dist/server/src/cli/server.d.ts.map +1 -1
- package/dist/server/src/cli/server.js +138 -0
- package/dist/server/src/cli/use-guide.md +156 -0
- 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/gateway/request-handlers/initialize-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/initialize-handler.js +12 -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 -5
- package/dist/client/assets/SettingsView-CUOFNXrz.js +0 -1
- package/dist/client/assets/index-CTB6oe-9.js +0 -2
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { buildApp } from '../app.js';
|
|
2
2
|
import { configManager } from '../config/config-manager.js';
|
|
3
|
-
import { resolveInstanceConfig } from '../config/config-migrator.js';
|
|
4
3
|
import { logger, LOG_MODULES } from '../utils/logger.js';
|
|
5
4
|
import { mcpConnectionManager } from '../services/mcp-connection-manager.js';
|
|
6
5
|
import { PidManager } from '../pid/manager.js';
|
|
6
|
+
import { collectConnectTasks, executeConnectTasks, ensureServerInstances } from './startup.js';
|
|
7
7
|
// Set log level to debug for development server
|
|
8
8
|
logger.setLevel('debug');
|
|
9
9
|
// Enable dev logging to file (this also enables communication debug logging)
|
|
@@ -17,7 +17,6 @@ let app = null;
|
|
|
17
17
|
* - Debug-level logging enabled for detailed development insights
|
|
18
18
|
* - Development log file output for persistent debugging information
|
|
19
19
|
* - Automatic connection to all enabled MCP servers configured in the system
|
|
20
|
-
* - OpenTelemetry tracing initialization for observability
|
|
21
20
|
* - PID file management for process tracking
|
|
22
21
|
* - Graceful shutdown handling for SIGTERM and SIGINT signals
|
|
23
22
|
*
|
|
@@ -55,7 +54,6 @@ let app = null;
|
|
|
55
54
|
* @see {@link buildApp} - Creates the Fastify application instance
|
|
56
55
|
* @see {@link configManager} - Manages server configuration and MCP server instances
|
|
57
56
|
* @see {@link mcpConnectionManager} - Handles MCP server connections and communication
|
|
58
|
-
* @see {@link telemetryManager} - Manages OpenTelemetry tracing and observability
|
|
59
57
|
* @see {@link PidManager} - Handles PID file creation and cleanup
|
|
60
58
|
*/
|
|
61
59
|
async function startDevServer() {
|
|
@@ -67,50 +65,7 @@ async function startDevServer() {
|
|
|
67
65
|
logger.info('------------------------------------------------', LOG_MODULES.DEV_SERVER);
|
|
68
66
|
app = await buildApp();
|
|
69
67
|
const config = configManager.getConfig();
|
|
70
|
-
//
|
|
71
|
-
logger.info('Initializing server connections...', LOG_MODULES.DEV_SERVER);
|
|
72
|
-
const serverConfigs = configManager.getServers();
|
|
73
|
-
for (const { name: serverName, config: serverConfig } of serverConfigs) {
|
|
74
|
-
// Check if there are existing instances
|
|
75
|
-
const existingInstances = configManager.getServerInstancesByName(serverName);
|
|
76
|
-
if (existingInstances.length === 0) {
|
|
77
|
-
// Auto-create instance for enabled servers
|
|
78
|
-
try {
|
|
79
|
-
const newInstance = await configManager.addServerInstance(serverName, {});
|
|
80
|
-
// Connect the new instance
|
|
81
|
-
const resolvedConfig = resolveInstanceConfig(serverConfig, newInstance.id);
|
|
82
|
-
if (resolvedConfig && resolvedConfig.enabled !== false) {
|
|
83
|
-
mcpConnectionManager
|
|
84
|
-
.connect(serverName, newInstance.index ?? 0, {
|
|
85
|
-
...resolvedConfig,
|
|
86
|
-
id: newInstance.id
|
|
87
|
-
})
|
|
88
|
-
.catch((err) => {
|
|
89
|
-
logger.error(`Failed to auto-connect to ${serverName}:`, err, LOG_MODULES.DEV_SERVER);
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
catch (err) {
|
|
94
|
-
logger.error(`Failed to create instance for ${serverName}:`, err, LOG_MODULES.DEV_SERVER);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
// Connect existing instances
|
|
99
|
-
existingInstances.forEach((instance) => {
|
|
100
|
-
if (instance.enabled !== false) {
|
|
101
|
-
const resolvedConfig = resolveInstanceConfig(serverConfig, instance.id);
|
|
102
|
-
if (resolvedConfig) {
|
|
103
|
-
mcpConnectionManager
|
|
104
|
-
.connect(serverName, instance.index ?? 0, { ...resolvedConfig, id: instance.id })
|
|
105
|
-
.catch((err) => {
|
|
106
|
-
logger.error(`Failed to auto-connect to ${serverName}:`, err, LOG_MODULES.DEV_SERVER);
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
// Listen on configured port
|
|
68
|
+
// Start listening FIRST, then trigger connection tasks
|
|
114
69
|
await app.listen({
|
|
115
70
|
port: config.system.port,
|
|
116
71
|
host: config.system.host
|
|
@@ -118,6 +73,13 @@ async function startDevServer() {
|
|
|
118
73
|
logger.info(`MCP Hub Lite Dev Server running at http://${config.system.host}:${config.system.port}`, LOG_MODULES.DEV_SERVER);
|
|
119
74
|
// Write PID file after server starts successfully
|
|
120
75
|
PidManager.writePid();
|
|
76
|
+
// Auto-create instances for enabled servers without existing instances
|
|
77
|
+
await ensureServerInstances(LOG_MODULES.DEV_SERVER);
|
|
78
|
+
// Trigger connection tasks (fire-and-forget, with sequential delay)
|
|
79
|
+
logger.info('Initializing server connections...', LOG_MODULES.DEV_SERVER);
|
|
80
|
+
const tasks = collectConnectTasks();
|
|
81
|
+
const baseDelay = config.system.startup?.startupDelay ?? 3000;
|
|
82
|
+
executeConnectTasks(tasks, baseDelay, LOG_MODULES.DEV_SERVER);
|
|
121
83
|
}
|
|
122
84
|
catch (err) {
|
|
123
85
|
logger.error('Failed to start dev server:', err, LOG_MODULES.DEV_SERVER);
|
|
@@ -132,7 +94,6 @@ async function startDevServer() {
|
|
|
132
94
|
* This function performs a clean shutdown sequence to ensure:
|
|
133
95
|
* - All MCP server connections are properly disconnected
|
|
134
96
|
* - The Fastify HTTP server is closed gracefully
|
|
135
|
-
* - OpenTelemetry tracing resources are properly shut down
|
|
136
97
|
* - PID file is removed to prevent stale process detection
|
|
137
98
|
* - All resources are cleaned up before process exit
|
|
138
99
|
*
|
|
@@ -1,27 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Starts the MCP Hub Lite server
|
|
2
|
+
* Starts the MCP Hub Lite server.
|
|
3
3
|
*
|
|
4
4
|
* This function is the main entry point for running the MCP Hub Lite server in production.
|
|
5
|
-
* It handles
|
|
6
|
-
*
|
|
7
|
-
* 1. **HTTP Server Mode** (default): Runs a full Fastify HTTP server with REST API,
|
|
8
|
-
* WebSocket support, and web interface on the specified host and port.
|
|
9
|
-
*
|
|
10
|
-
* 2. **Stdio MCP Gateway Mode**: Runs as an MCP (Model Context Protocol) gateway
|
|
11
|
-
* that communicates via stdin/stdout streams, suitable for integration with
|
|
12
|
-
* MCP-compatible clients like IDEs or AI assistants.
|
|
5
|
+
* It handles the HTTP server mode with REST API, WebSocket support, and web interface
|
|
6
|
+
* on the specified host and port.
|
|
13
7
|
*
|
|
14
8
|
* The function performs the following key operations:
|
|
15
|
-
* - Validates and checks port availability
|
|
16
|
-
* -
|
|
9
|
+
* - Validates and checks port availability
|
|
10
|
+
* - Starts the Fastify HTTP server
|
|
11
|
+
* - Triggers connection to all enabled MCP servers from configuration
|
|
17
12
|
* - Sets up graceful shutdown handlers for SIGTERM and SIGINT signals
|
|
18
13
|
* - Manages PID file creation and cleanup for process tracking
|
|
19
14
|
* - Handles both successful startup and error scenarios with appropriate logging
|
|
20
15
|
*
|
|
21
16
|
* @param options - Configuration options for server startup
|
|
22
|
-
* @param options.
|
|
23
|
-
* @param options.
|
|
24
|
-
* @param options.host - Override the configured host address (HTTP mode only)
|
|
17
|
+
* @param options.port - Override the configured port number
|
|
18
|
+
* @param options.host - Override the configured host address
|
|
25
19
|
*
|
|
26
20
|
* @returns Promise that resolves when the server is successfully started,
|
|
27
21
|
* or rejects with an error if startup fails
|
|
@@ -30,27 +24,21 @@
|
|
|
30
24
|
* or other critical issues. The process will exit with code 1 in such cases.
|
|
31
25
|
*
|
|
32
26
|
* @example
|
|
33
|
-
* // Start
|
|
27
|
+
* // Start with default config
|
|
34
28
|
* await runServer();
|
|
35
29
|
*
|
|
36
30
|
* @example
|
|
37
|
-
* // Start
|
|
38
|
-
* await runServer({ stdio: true });
|
|
39
|
-
*
|
|
40
|
-
* @example
|
|
41
|
-
* // Start HTTP server on custom port and host
|
|
31
|
+
* // Start on custom port and host
|
|
42
32
|
* await runServer({ port: 8080, host: '0.0.0.0' });
|
|
43
33
|
*
|
|
44
34
|
* @remarks
|
|
45
|
-
* -
|
|
46
|
-
*
|
|
47
|
-
* - In stdio mode, port checking is skipped as no network ports are used
|
|
35
|
+
* - The function will check if the specified port is already in use and provide
|
|
36
|
+
* detailed error messages for port conflicts
|
|
48
37
|
* - The function automatically connects to all enabled servers configured in .mcp-hub.json
|
|
49
38
|
* - Graceful shutdown ensures proper cleanup of connections and PID files when receiving termination signals
|
|
50
39
|
* - This function is typically called from the CLI entry point (`src/index.ts`)
|
|
51
40
|
*/
|
|
52
41
|
export declare function runServer(options?: {
|
|
53
|
-
stdio?: boolean;
|
|
54
42
|
port?: number;
|
|
55
43
|
host?: string;
|
|
56
44
|
}): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../src/server/runner.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../src/server/runner.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuCG;AACH,wBAAsB,SAAS,CAAC,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,iBAuD7E"}
|
|
@@ -1,37 +1,30 @@
|
|
|
1
1
|
import { buildApp } from '../app.js';
|
|
2
2
|
import { configManager } from '../config/config-manager.js';
|
|
3
|
-
import { resolveInstanceConfig } from '../config/config-migrator.js';
|
|
4
3
|
import { logger } from '../utils/logger.js';
|
|
5
4
|
import { LOG_MODULES } from '../utils/logger/log-modules.js';
|
|
6
5
|
import { setJsonPrettyConfigGetter } from '../utils/json-utils.js';
|
|
7
6
|
import { mcpConnectionManager } from '../services/mcp-connection-manager.js';
|
|
8
|
-
import { gateway } from '../services/gateway.service.js';
|
|
9
7
|
import { PidManager } from '../pid/manager.js';
|
|
10
|
-
import {
|
|
8
|
+
import { checkPortWithExit } from '../utils/port-checker.js';
|
|
9
|
+
import { collectConnectTasks, executeConnectTasks, ensureServerInstances } from './startup.js';
|
|
11
10
|
/**
|
|
12
|
-
* Starts the MCP Hub Lite server
|
|
11
|
+
* Starts the MCP Hub Lite server.
|
|
13
12
|
*
|
|
14
13
|
* This function is the main entry point for running the MCP Hub Lite server in production.
|
|
15
|
-
* It handles
|
|
16
|
-
*
|
|
17
|
-
* 1. **HTTP Server Mode** (default): Runs a full Fastify HTTP server with REST API,
|
|
18
|
-
* WebSocket support, and web interface on the specified host and port.
|
|
19
|
-
*
|
|
20
|
-
* 2. **Stdio MCP Gateway Mode**: Runs as an MCP (Model Context Protocol) gateway
|
|
21
|
-
* that communicates via stdin/stdout streams, suitable for integration with
|
|
22
|
-
* MCP-compatible clients like IDEs or AI assistants.
|
|
14
|
+
* It handles the HTTP server mode with REST API, WebSocket support, and web interface
|
|
15
|
+
* on the specified host and port.
|
|
23
16
|
*
|
|
24
17
|
* The function performs the following key operations:
|
|
25
|
-
* - Validates and checks port availability
|
|
26
|
-
* -
|
|
18
|
+
* - Validates and checks port availability
|
|
19
|
+
* - Starts the Fastify HTTP server
|
|
20
|
+
* - Triggers connection to all enabled MCP servers from configuration
|
|
27
21
|
* - Sets up graceful shutdown handlers for SIGTERM and SIGINT signals
|
|
28
22
|
* - Manages PID file creation and cleanup for process tracking
|
|
29
23
|
* - Handles both successful startup and error scenarios with appropriate logging
|
|
30
24
|
*
|
|
31
25
|
* @param options - Configuration options for server startup
|
|
32
|
-
* @param options.
|
|
33
|
-
* @param options.
|
|
34
|
-
* @param options.host - Override the configured host address (HTTP mode only)
|
|
26
|
+
* @param options.port - Override the configured port number
|
|
27
|
+
* @param options.host - Override the configured host address
|
|
35
28
|
*
|
|
36
29
|
* @returns Promise that resolves when the server is successfully started,
|
|
37
30
|
* or rejects with an error if startup fails
|
|
@@ -40,110 +33,37 @@ import { checkPort } from '../utils/port-checker.js';
|
|
|
40
33
|
* or other critical issues. The process will exit with code 1 in such cases.
|
|
41
34
|
*
|
|
42
35
|
* @example
|
|
43
|
-
* // Start
|
|
36
|
+
* // Start with default config
|
|
44
37
|
* await runServer();
|
|
45
38
|
*
|
|
46
39
|
* @example
|
|
47
|
-
* // Start
|
|
48
|
-
* await runServer({ stdio: true });
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* // Start HTTP server on custom port and host
|
|
40
|
+
* // Start on custom port and host
|
|
52
41
|
* await runServer({ port: 8080, host: '0.0.0.0' });
|
|
53
42
|
*
|
|
54
43
|
* @remarks
|
|
55
|
-
* -
|
|
56
|
-
*
|
|
57
|
-
* - In stdio mode, port checking is skipped as no network ports are used
|
|
44
|
+
* - The function will check if the specified port is already in use and provide
|
|
45
|
+
* detailed error messages for port conflicts
|
|
58
46
|
* - The function automatically connects to all enabled servers configured in .mcp-hub.json
|
|
59
47
|
* - Graceful shutdown ensures proper cleanup of connections and PID files when receiving termination signals
|
|
60
48
|
* - This function is typically called from the CLI entry point (`src/index.ts`)
|
|
61
49
|
*/
|
|
62
50
|
export async function runServer(options = {}) {
|
|
63
51
|
try {
|
|
64
|
-
const isStdio = options.stdio || false;
|
|
65
|
-
if (isStdio) {
|
|
66
|
-
logger.setUseStderr(true);
|
|
67
|
-
logger.info('Starting in MCP Gateway mode (stdio)...', LOG_MODULES.SERVER);
|
|
68
|
-
}
|
|
69
52
|
const config = configManager.getConfig();
|
|
70
53
|
// Set config getter for json-utils to use config from configManager
|
|
71
54
|
setJsonPrettyConfigGetter(() => configManager.getConfig());
|
|
72
|
-
const app =
|
|
55
|
+
const app = await buildApp();
|
|
73
56
|
// Override config with options if provided
|
|
74
57
|
const host = options.host || config.system.host;
|
|
75
58
|
const port = options.port || config.system.port;
|
|
76
|
-
// Check if port is already in use
|
|
77
|
-
|
|
78
|
-
const portCheck = await checkPort(port);
|
|
79
|
-
if (portCheck.inUse) {
|
|
80
|
-
if (portCheck.isSelfProject) {
|
|
81
|
-
// This project is already running
|
|
82
|
-
logger.error(`MCP Hub Lite is already running on port ${port} (PID: ${portCheck.pid})`, LOG_MODULES.SERVER);
|
|
83
|
-
logger.error(`Use 'npm run stop' or 'mcp-hub-lite stop' to stop the running instance.`, LOG_MODULES.SERVER);
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
// Port is occupied by another application
|
|
88
|
-
logger.error(`Port ${port} is already in use by another application:`, LOG_MODULES.SERVER);
|
|
89
|
-
logger.error(` Process: ${portCheck.processName} (PID: ${portCheck.pid})`, LOG_MODULES.SERVER);
|
|
90
|
-
if (portCheck.commandLine) {
|
|
91
|
-
logger.error(` Command: ${portCheck.commandLine}`, LOG_MODULES.SERVER);
|
|
92
|
-
}
|
|
93
|
-
logger.error(`Please stop the conflicting application or use a different port.`, LOG_MODULES.SERVER);
|
|
94
|
-
process.exit(1);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// Auto-connect to enabled servers
|
|
99
|
-
logger.info('Initializing server connections...', LOG_MODULES.SERVER);
|
|
100
|
-
const serverConfigs = configManager.getServers();
|
|
101
|
-
for (const { name: serverName, config: serverConfig } of serverConfigs) {
|
|
102
|
-
// Check if there are existing instances
|
|
103
|
-
const existingInstances = configManager.getServerInstancesByName(serverName);
|
|
104
|
-
if (existingInstances.length === 0) {
|
|
105
|
-
// Auto-create instance for enabled servers
|
|
106
|
-
try {
|
|
107
|
-
const newInstance = await configManager.addServerInstance(serverName, {});
|
|
108
|
-
// Connect the new instance
|
|
109
|
-
const resolvedConfig = resolveInstanceConfig(serverConfig, newInstance.id);
|
|
110
|
-
if (resolvedConfig && resolvedConfig.enabled !== false) {
|
|
111
|
-
mcpConnectionManager
|
|
112
|
-
.connect(serverName, newInstance.index ?? 0, {
|
|
113
|
-
...resolvedConfig,
|
|
114
|
-
id: newInstance.id
|
|
115
|
-
})
|
|
116
|
-
.catch((err) => {
|
|
117
|
-
logger.error(`Failed to auto-connect to ${serverName}:`, err, LOG_MODULES.SERVER);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
catch (err) {
|
|
122
|
-
logger.error(`Failed to create instance for ${serverName}:`, err, LOG_MODULES.SERVER);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else {
|
|
126
|
-
// Connect existing instances
|
|
127
|
-
existingInstances.forEach((instance) => {
|
|
128
|
-
if (instance.enabled !== false) {
|
|
129
|
-
const resolvedConfig = resolveInstanceConfig(serverConfig, instance.id);
|
|
130
|
-
if (resolvedConfig) {
|
|
131
|
-
mcpConnectionManager
|
|
132
|
-
.connect(serverName, instance.index ?? 0, { ...resolvedConfig, id: instance.id })
|
|
133
|
-
.catch((err) => {
|
|
134
|
-
logger.error(`Failed to auto-connect to ${serverName}:`, err, LOG_MODULES.SERVER);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
}
|
|
140
|
-
}
|
|
59
|
+
// Check if port is already in use
|
|
60
|
+
await checkPortWithExit(port);
|
|
141
61
|
// Setup signal handlers for graceful shutdown
|
|
142
62
|
const shutdown = async (signal) => {
|
|
143
63
|
logger.info(`Received ${signal}, shutting down...`, LOG_MODULES.SERVER);
|
|
144
64
|
try {
|
|
145
65
|
await mcpConnectionManager.disconnectAll();
|
|
146
|
-
if (
|
|
66
|
+
if (app) {
|
|
147
67
|
await app.close();
|
|
148
68
|
}
|
|
149
69
|
PidManager.removePid();
|
|
@@ -157,17 +77,17 @@ export async function runServer(options = {}) {
|
|
|
157
77
|
};
|
|
158
78
|
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
159
79
|
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
80
|
+
// Start listening FIRST, then trigger connection tasks
|
|
81
|
+
await app.listen({ port, host });
|
|
82
|
+
logger.info(`MCP Hub Lite Server running at http://${host}:${port}`, LOG_MODULES.SERVER);
|
|
83
|
+
// Write PID after server starts successfully
|
|
84
|
+
PidManager.writePid();
|
|
85
|
+
// Auto-create instances for enabled servers without existing instances
|
|
86
|
+
await ensureServerInstances(LOG_MODULES.SERVER);
|
|
87
|
+
// Trigger connection tasks (fire-and-forget, with sequential delay)
|
|
88
|
+
const tasks = collectConnectTasks();
|
|
89
|
+
const baseDelay = config.system.startup?.startupDelay ?? 3000;
|
|
90
|
+
executeConnectTasks(tasks, baseDelay, LOG_MODULES.SERVER);
|
|
171
91
|
}
|
|
172
92
|
catch (err) {
|
|
173
93
|
logger.error('Failed to start server:', err, LOG_MODULES.SERVER);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server startup shared utilities
|
|
3
|
+
*
|
|
4
|
+
* This module provides shared connection task collection and execution logic
|
|
5
|
+
* used by both production runner and development server.
|
|
6
|
+
*/
|
|
7
|
+
import type { LogModule } from '../utils/logger/log-modules.js';
|
|
8
|
+
/**
|
|
9
|
+
* Shared connection task structure
|
|
10
|
+
*/
|
|
11
|
+
export interface ConnectTask {
|
|
12
|
+
serverName: string;
|
|
13
|
+
instanceId: string;
|
|
14
|
+
instanceIndex: number;
|
|
15
|
+
connectFn: () => Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Ensures all configured servers have at least one instance.
|
|
19
|
+
* Creates a default instance for any server that doesn't have one yet.
|
|
20
|
+
*
|
|
21
|
+
* This should be called before collectConnectTasks() to ensure all
|
|
22
|
+
* servers have at least one instance to connect to.
|
|
23
|
+
*
|
|
24
|
+
* @param logModule - The log module to use for error logging
|
|
25
|
+
*/
|
|
26
|
+
export declare function ensureServerInstances(logModule: LogModule): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Collects all server connection tasks from config
|
|
29
|
+
* - Collects existing instances that are enabled
|
|
30
|
+
*
|
|
31
|
+
* Note: Instance creation is handled by the caller via configManager.addServerInstance()
|
|
32
|
+
* before calling this function.
|
|
33
|
+
*
|
|
34
|
+
* @returns Array of connection tasks ready for execution
|
|
35
|
+
*/
|
|
36
|
+
export declare function collectConnectTasks(): ConnectTask[];
|
|
37
|
+
/**
|
|
38
|
+
* Executes connection tasks with sequential delay (fire-and-forget)
|
|
39
|
+
* - First task executes immediately
|
|
40
|
+
* - Subsequent tasks wait baseDelay before execution
|
|
41
|
+
*/
|
|
42
|
+
export declare function executeConnectTasks(tasks: ConnectTask[], baseDelay: number, logModule: LogModule): Promise<void>;
|
|
43
|
+
//# sourceMappingURL=startup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup.d.ts","sourceRoot":"","sources":["../../../../src/server/startup.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACnC;AAED;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAY/E;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,IAAI,WAAW,EAAE,CAiCnD;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,WAAW,EAAE,EACpB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,IAAI,CAAC,CAiBf"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server startup shared utilities
|
|
3
|
+
*
|
|
4
|
+
* This module provides shared connection task collection and execution logic
|
|
5
|
+
* used by both production runner and development server.
|
|
6
|
+
*/
|
|
7
|
+
import { configManager } from '../config/config-manager.js';
|
|
8
|
+
import { resolveInstanceConfig } from '../config/config-migrator.js';
|
|
9
|
+
import { mcpConnectionManager } from '../services/mcp-connection-manager.js';
|
|
10
|
+
import { logger } from '../utils/logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* Ensures all configured servers have at least one instance.
|
|
13
|
+
* Creates a default instance for any server that doesn't have one yet.
|
|
14
|
+
*
|
|
15
|
+
* This should be called before collectConnectTasks() to ensure all
|
|
16
|
+
* servers have at least one instance to connect to.
|
|
17
|
+
*
|
|
18
|
+
* @param logModule - The log module to use for error logging
|
|
19
|
+
*/
|
|
20
|
+
export async function ensureServerInstances(logModule) {
|
|
21
|
+
const serverConfigs = configManager.getServers();
|
|
22
|
+
for (const { name: serverName } of serverConfigs) {
|
|
23
|
+
const existingInstances = configManager.getServerInstancesByName(serverName);
|
|
24
|
+
if (existingInstances.length === 0) {
|
|
25
|
+
try {
|
|
26
|
+
await configManager.addServerInstance(serverName, {});
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
logger.error(`Failed to create instance for ${serverName}:`, err, logModule);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Collects all server connection tasks from config
|
|
36
|
+
* - Collects existing instances that are enabled
|
|
37
|
+
*
|
|
38
|
+
* Note: Instance creation is handled by the caller via configManager.addServerInstance()
|
|
39
|
+
* before calling this function.
|
|
40
|
+
*
|
|
41
|
+
* @returns Array of connection tasks ready for execution
|
|
42
|
+
*/
|
|
43
|
+
export function collectConnectTasks() {
|
|
44
|
+
const tasks = [];
|
|
45
|
+
const serverConfigs = configManager.getServers();
|
|
46
|
+
for (const { name: serverName, config: serverConfig } of serverConfigs) {
|
|
47
|
+
const existingInstances = configManager.getServerInstancesByName(serverName);
|
|
48
|
+
if (existingInstances.length === 0) {
|
|
49
|
+
// No instances - skip (caller should have created instances via addServerInstance)
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
// Collect existing enabled instances
|
|
53
|
+
for (const instance of existingInstances) {
|
|
54
|
+
if (instance.enabled !== false) {
|
|
55
|
+
const resolvedConfig = resolveInstanceConfig(serverConfig, instance.id);
|
|
56
|
+
if (resolvedConfig) {
|
|
57
|
+
tasks.push({
|
|
58
|
+
serverName,
|
|
59
|
+
instanceId: instance.id,
|
|
60
|
+
instanceIndex: instance.index ?? 0,
|
|
61
|
+
connectFn: () => mcpConnectionManager.connect(serverName, instance.index ?? 0, {
|
|
62
|
+
...resolvedConfig,
|
|
63
|
+
id: instance.id
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return tasks;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Executes connection tasks with sequential delay (fire-and-forget)
|
|
74
|
+
* - First task executes immediately
|
|
75
|
+
* - Subsequent tasks wait baseDelay before execution
|
|
76
|
+
*/
|
|
77
|
+
export async function executeConnectTasks(tasks, baseDelay, logModule) {
|
|
78
|
+
for (let i = 0; i < tasks.length; i++) {
|
|
79
|
+
const task = tasks[i];
|
|
80
|
+
if (i > 0) {
|
|
81
|
+
logger.info(`Delaying next server instance startup by ${baseDelay}ms (${i + 1}/${tasks.length})`, logModule);
|
|
82
|
+
await new Promise((resolve) => setTimeout(resolve, baseDelay));
|
|
83
|
+
}
|
|
84
|
+
// Fire-and-forget: don't wait for connection completion
|
|
85
|
+
task.connectFn().catch((err) => {
|
|
86
|
+
logger.error(`Failed to auto-connect to ${task.serverName}:`, err, logModule);
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -73,6 +73,58 @@ export declare class McpConnectionManager {
|
|
|
73
73
|
* ```
|
|
74
74
|
*/
|
|
75
75
|
connect(serverName: string, serverIndex: number, server: ServerRuntimeConfig & Partial<ServerInstanceConfig>): Promise<boolean>;
|
|
76
|
+
/**
|
|
77
|
+
* Gets retry configuration from system settings.
|
|
78
|
+
*/
|
|
79
|
+
private getRetryConfig;
|
|
80
|
+
/**
|
|
81
|
+
* Validates server configuration before connection.
|
|
82
|
+
*/
|
|
83
|
+
private validateServerConfig;
|
|
84
|
+
/**
|
|
85
|
+
* Logs connection attempt information.
|
|
86
|
+
*/
|
|
87
|
+
private logConnectionAttempt;
|
|
88
|
+
/**
|
|
89
|
+
* Initializes server status to starting state.
|
|
90
|
+
*/
|
|
91
|
+
private initializeServerStatus;
|
|
92
|
+
/**
|
|
93
|
+
* Gets server info by ID from hub manager.
|
|
94
|
+
*/
|
|
95
|
+
private getServerInfo;
|
|
96
|
+
/**
|
|
97
|
+
* Creates transport and sets up all callbacks.
|
|
98
|
+
*/
|
|
99
|
+
private initializeTransport;
|
|
100
|
+
/**
|
|
101
|
+
* Creates Client and connects to transport.
|
|
102
|
+
*/
|
|
103
|
+
private establishClientConnection;
|
|
104
|
+
/**
|
|
105
|
+
* Registers client, transport, and updates name mappings.
|
|
106
|
+
*/
|
|
107
|
+
private registerConnection;
|
|
108
|
+
/**
|
|
109
|
+
* Updates server status to connected state.
|
|
110
|
+
*/
|
|
111
|
+
private updateConnectedStatus;
|
|
112
|
+
/**
|
|
113
|
+
* Publishes connection events.
|
|
114
|
+
*/
|
|
115
|
+
private publishConnectionEvents;
|
|
116
|
+
/**
|
|
117
|
+
* Refreshes server tools and resources (only for bidirectional transports).
|
|
118
|
+
*/
|
|
119
|
+
private refreshServerResources;
|
|
120
|
+
/**
|
|
121
|
+
* Handles connection error with logging and retry delay.
|
|
122
|
+
*/
|
|
123
|
+
private handleConnectionError;
|
|
124
|
+
/**
|
|
125
|
+
* Handles final failure after all retries exhausted.
|
|
126
|
+
*/
|
|
127
|
+
private handleFinalFailure;
|
|
76
128
|
/**
|
|
77
129
|
* Disconnects from an MCP server and cleans up all associated resources.
|
|
78
130
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../../../src/services/connection/connection-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAWnE,OAAO,KAAK,EAAE,IAAI,EAAc,MAAM,8BAA8B,CAAC;AACrE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kCAAkC,CAAC;AAKjE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"connection-manager.d.ts","sourceRoot":"","sources":["../../../../../src/services/connection/connection-manager.ts"],"names":[],"mappings":"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"}
|