@loop_ouroboros/mcp-hub-lite 1.3.0 → 1.3.1
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 +49 -0
- package/README.md +405 -331
- package/dist/client/assets/{HomeView-Bi2bkUKf.js → HomeView-DplI3V-h.js} +1 -1
- package/dist/client/assets/{ResourceDetailView-DyuSovH9.js → ResourceDetailView-CeHPn99Y.js} +1 -1
- package/dist/client/assets/ResourcesView-C1ObRhYS.js +1 -0
- package/dist/client/assets/{ServerDashboard-BGyyZAti.js → ServerDashboard-D7wG4Gvt.js} +1 -1
- package/dist/client/assets/ServerDetail-G23phOcJ.js +2 -0
- package/dist/client/assets/{ServerListView-yQPVJFHG.js → ServerListView-BFiZLtPO.js} +1 -1
- package/dist/client/assets/{ServerStatusTags.vue_vue_type_script_setup_true_lang-C8gQlxGE.js → ServerStatusTags.vue_vue_type_script_setup_true_lang-Deb_SbFw.js} +1 -1
- package/dist/client/assets/SettingsView-QBFLZ6fP.js +1 -0
- package/dist/client/assets/ToolCallDialog-DYS-ADCL.js +1 -0
- package/dist/client/assets/ToolsView-DYwgtm7W.js +1 -0
- package/dist/client/assets/_baseClone-DQno9YO3.js +1 -0
- package/dist/client/assets/{el-form-item-DfWq_kSy.js → el-form-item-DF0zzQdH.js} +2 -2
- package/dist/client/assets/el-input-C_p2Qw42.js +1 -0
- package/dist/client/assets/el-loading-BaenpNzU.js +1 -0
- package/dist/client/assets/el-overlay-MbIUXSQ7.js +1 -0
- package/dist/client/assets/el-radio-group-COnCjCcz.js +1 -0
- package/dist/client/assets/el-skeleton-item-qj0eQP4s.js +1 -0
- package/dist/client/assets/el-switch-BZbXqB3_.js +1 -0
- package/dist/client/assets/el-tab-pane-w7RltRLd.js +1 -0
- package/dist/client/assets/el-table-column-OD8zhFcD.js +1 -0
- package/dist/client/assets/index-DwhULJXZ.js +2 -0
- package/dist/client/assets/{index-Bzz3tYbS.css → index-UtsV0Cvh.css} +1 -1
- package/dist/client/assets/{omit-BIIebEYo.js → omit-BAJQlviJ.js} +1 -1
- package/dist/client/assets/raf-B1Ry7ruA.js +1 -0
- package/dist/client/assets/{vue-vendor-Dwcr0jep.js → vue-vendor-ClSvefnQ.js} +1 -1
- package/dist/client/index.html +3 -3
- package/dist/server/shared/models/constants.d.ts +5 -0
- package/dist/server/shared/models/constants.d.ts.map +1 -1
- package/dist/server/shared/models/constants.js +4 -0
- package/dist/server/shared/models/server.model.d.ts +14 -0
- package/dist/server/shared/models/server.model.d.ts.map +1 -1
- package/dist/server/shared/models/server.model.js +27 -4
- package/dist/server/src/api/mcp/gateway.d.ts +10 -6
- package/dist/server/src/api/mcp/gateway.d.ts.map +1 -1
- package/dist/server/src/api/mcp/gateway.js +235 -69
- package/dist/server/src/api/web/sessions.d.ts +1 -27
- package/dist/server/src/api/web/sessions.d.ts.map +1 -1
- package/dist/server/src/api/web/sessions.js +8 -97
- package/dist/server/src/app.d.ts.map +1 -1
- package/dist/server/src/app.js +5 -0
- package/dist/server/src/cli/commands/status.js +39 -1
- package/dist/server/src/cli/commands/use-guide.d.ts +0 -8
- package/dist/server/src/cli/commands/use-guide.d.ts.map +1 -1
- package/dist/server/src/cli/commands/use-guide.js +28 -170
- package/dist/server/src/cli/server.d.ts +10 -0
- package/dist/server/src/cli/server.d.ts.map +1 -1
- package/dist/server/src/cli/server.js +31 -1
- package/dist/server/src/server/dev-server.js +2 -0
- package/dist/server/src/server/runner.d.ts.map +1 -1
- package/dist/server/src/server/runner.js +2 -0
- package/dist/server/src/services/connection/connection-manager.d.ts +2 -0
- package/dist/server/src/services/connection/connection-manager.d.ts.map +1 -1
- package/dist/server/src/services/connection/connection-manager.js +14 -7
- package/dist/server/src/services/gateway/gateway.service.d.ts +13 -0
- package/dist/server/src/services/gateway/gateway.service.d.ts.map +1 -1
- package/dist/server/src/services/gateway/gateway.service.js +72 -0
- package/dist/server/src/services/gateway/global-transport.d.ts +20 -10
- package/dist/server/src/services/gateway/global-transport.d.ts.map +1 -1
- package/dist/server/src/services/gateway/global-transport.js +50 -34
- 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 +22 -6
- package/dist/server/src/services/gateway/request-handlers/resources-handler.d.ts.map +1 -1
- package/dist/server/src/services/gateway/request-handlers/resources-handler.js +5 -1
- package/dist/server/src/services/gateway/session-manager.d.ts +101 -0
- package/dist/server/src/services/gateway/session-manager.d.ts.map +1 -0
- package/dist/server/src/services/gateway/session-manager.js +256 -0
- package/dist/server/src/services/hub-tools/resource-generator.d.ts +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools/resource-generator.js +11 -9
- package/dist/server/src/services/hub-tools.service.d.ts.map +1 -1
- package/dist/server/src/services/hub-tools.service.js +3 -1
- package/dist/server/src/utils/json-utils.d.ts +9 -0
- package/dist/server/src/utils/json-utils.d.ts.map +1 -1
- package/dist/server/src/utils/json-utils.js +19 -0
- package/dist/server/src/utils/logger/index.d.ts +1 -1
- package/dist/server/src/utils/logger/index.d.ts.map +1 -1
- package/dist/server/src/utils/logger/index.js +1 -1
- package/dist/server/src/utils/logger/log-context.d.ts +1 -0
- package/dist/server/src/utils/logger/log-context.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-formatter.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-formatter.js +25 -11
- package/dist/server/src/utils/logger/log-output.d.ts +17 -1
- package/dist/server/src/utils/logger/log-output.d.ts.map +1 -1
- package/dist/server/src/utils/logger/log-output.js +46 -40
- package/dist/server/src/utils/logger/logger.d.ts.map +1 -1
- package/dist/server/src/utils/logger/logger.js +18 -2
- package/dist/server/src/utils/request-context.d.ts +8 -70
- package/dist/server/src/utils/request-context.d.ts.map +1 -1
- package/dist/server/src/utils/request-context.js +11 -70
- package/dist/server/tests/unit/config/config.schema.test.js +2 -1
- package/dist/server/tests/unit/server/runner.test.js +14 -7
- package/dist/server/tests/unit/services/gateway-session-mode.test.d.ts +2 -0
- package/dist/server/tests/unit/services/gateway-session-mode.test.d.ts.map +1 -0
- package/dist/server/tests/unit/services/gateway-session-mode.test.js +174 -0
- package/dist/server/tests/unit/services/hub-tools.service.test.js +4 -4
- package/dist/server/tests/unit/utils/config.test.js +14 -7
- package/dist/server/tests/unit/utils/log-output.test.d.ts +2 -0
- package/dist/server/tests/unit/utils/log-output.test.d.ts.map +1 -0
- package/dist/server/tests/unit/utils/log-output.test.js +198 -0
- package/dist/server/vitest.config.d.ts.map +1 -1
- package/dist/server/vitest.config.js +0 -2
- package/package.json +1 -1
- package/dist/client/assets/ResourcesView-CU0VbNy5.js +0 -1
- package/dist/client/assets/ServerDetail-bcQ8BVXR.js +0 -2
- package/dist/client/assets/SettingsView-B1DxbFP3.js +0 -1
- package/dist/client/assets/ToolCallDialog-DEapCO06.js +0 -1
- package/dist/client/assets/ToolsView-DA0u_bCw.js +0 -1
- package/dist/client/assets/_baseClone-B991Lvrt.js +0 -1
- package/dist/client/assets/el-input-5YzZrwir.js +0 -1
- package/dist/client/assets/el-loading-DE3FcxNH.js +0 -1
- package/dist/client/assets/el-overlay-BTeTueuN.js +0 -1
- package/dist/client/assets/el-radio-group-Y1E2bxIW.js +0 -1
- package/dist/client/assets/el-skeleton-item-DhgR50Jx.js +0 -1
- package/dist/client/assets/el-switch-fF--nMSD.js +0 -1
- package/dist/client/assets/el-tab-pane-rvS_KTwP.js +0 -1
- package/dist/client/assets/el-table-column-B1O8mY47.js +0 -1
- package/dist/client/assets/index-DkqV9kH4.js +0 -2
- package/dist/client/assets/raf-Cj-gATZv.js +0 -1
package/dist/client/index.html
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
<link rel="icon" href="/favicon.ico" />
|
|
6
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
7
|
<title>MCP Server Manager</title>
|
|
8
|
-
<script type="module" crossorigin src="/assets/index-
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-
|
|
10
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
8
|
+
<script type="module" crossorigin src="/assets/index-DwhULJXZ.js"></script>
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/vue-vendor-ClSvefnQ.js">
|
|
10
|
+
<link rel="stylesheet" crossorigin href="/assets/index-UtsV0Cvh.css">
|
|
11
11
|
</head>
|
|
12
12
|
<body>
|
|
13
13
|
<div id="app"></div>
|
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
/** MCP Hub Lite gateway server name — used for system tool identification and gateway naming */
|
|
2
2
|
export declare const MCP_HUB_LITE_SERVER = "mcp-hub-lite";
|
|
3
|
+
/** Session mode constants for gateway transport selection */
|
|
4
|
+
export declare const SESSION_MODE_STATELESS: "stateless";
|
|
5
|
+
export declare const SESSION_MODE_STATEFUL: "stateful";
|
|
6
|
+
export declare const SESSION_MODE_VALUES: readonly ["stateless", "stateful"];
|
|
7
|
+
export type SessionMode = (typeof SESSION_MODE_VALUES)[number];
|
|
3
8
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../shared/models/constants.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,eAAO,MAAM,mBAAmB,iBAAiB,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../shared/models/constants.ts"],"names":[],"mappings":"AAAA,gGAAgG;AAChG,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAElD,6DAA6D;AAC7D,eAAO,MAAM,sBAAsB,EAAG,WAAoB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,EAAG,UAAmB,CAAC;AACzD,eAAO,MAAM,mBAAmB,oCAA2D,CAAC;AAC5F,MAAM,MAAM,WAAW,GAAG,CAAC,OAAO,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC"}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
1
|
/** MCP Hub Lite gateway server name — used for system tool identification and gateway naming */
|
|
2
2
|
export const MCP_HUB_LITE_SERVER = 'mcp-hub-lite';
|
|
3
|
+
/** Session mode constants for gateway transport selection */
|
|
4
|
+
export const SESSION_MODE_STATELESS = 'stateless';
|
|
5
|
+
export const SESSION_MODE_STATEFUL = 'stateful';
|
|
6
|
+
export const SESSION_MODE_VALUES = [SESSION_MODE_STATELESS, SESSION_MODE_STATEFUL];
|
|
@@ -232,6 +232,7 @@ export declare const LoggingConfigSchema: z.ZodDefault<z.ZodObject<{
|
|
|
232
232
|
mcpCommDebug: z.ZodDefault<z.ZodBoolean>;
|
|
233
233
|
apiDebug: z.ZodDefault<z.ZodBoolean>;
|
|
234
234
|
gatewayDebug: z.ZodDefault<z.ZodBoolean>;
|
|
235
|
+
showTraceContext: z.ZodDefault<z.ZodBoolean>;
|
|
235
236
|
}, z.core.$strip>>;
|
|
236
237
|
export type LoggingConfig = z.infer<typeof LoggingConfigSchema>;
|
|
237
238
|
/**
|
|
@@ -280,6 +281,7 @@ export declare const SystemConfigSchema: z.ZodObject<{
|
|
|
280
281
|
mcpCommDebug: z.ZodDefault<z.ZodBoolean>;
|
|
281
282
|
apiDebug: z.ZodDefault<z.ZodBoolean>;
|
|
282
283
|
gatewayDebug: z.ZodDefault<z.ZodBoolean>;
|
|
284
|
+
showTraceContext: z.ZodDefault<z.ZodBoolean>;
|
|
283
285
|
}, z.core.$strip>>;
|
|
284
286
|
startup: z.ZodOptional<z.ZodDefault<z.ZodObject<{
|
|
285
287
|
startupDelay: z.ZodDefault<z.ZodNumber>;
|
|
@@ -287,6 +289,16 @@ export declare const SystemConfigSchema: z.ZodObject<{
|
|
|
287
289
|
maxConnectRetries: z.ZodDefault<z.ZodNumber>;
|
|
288
290
|
connectRetryDelay: z.ZodDefault<z.ZodNumber>;
|
|
289
291
|
}, z.core.$strip>>>;
|
|
292
|
+
session: z.ZodOptional<z.ZodObject<{
|
|
293
|
+
sessionModeRules: z.ZodDefault<z.ZodOptional<z.ZodObject<{
|
|
294
|
+
stateful: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
295
|
+
stateless: z.ZodDefault<z.ZodOptional<z.ZodArray<z.ZodString>>>;
|
|
296
|
+
}, z.core.$strip>>>;
|
|
297
|
+
defaultSessionMode: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
298
|
+
stateless: "stateless";
|
|
299
|
+
stateful: "stateful";
|
|
300
|
+
}>>>;
|
|
301
|
+
}, z.core.$strip>>;
|
|
290
302
|
}, z.core.$strip>>;
|
|
291
303
|
security: z.ZodDefault<z.ZodObject<{
|
|
292
304
|
allowedNetworks: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
@@ -362,6 +374,8 @@ export declare const SystemConfigSchema: z.ZodObject<{
|
|
|
362
374
|
}, z.core.$strip>>>;
|
|
363
375
|
}, z.core.$strip>;
|
|
364
376
|
export type SystemConfig = z.infer<typeof SystemConfigSchema>;
|
|
377
|
+
/** Session configuration extracted from SystemConfig.system.session */
|
|
378
|
+
export type GatewayConfig = SystemConfig['system']['session'];
|
|
365
379
|
/**
|
|
366
380
|
* Server instance runtime configuration (for connection manager)
|
|
367
381
|
* Contains runtime-specific fields like timestamp, pid, etc.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.model.d.ts","sourceRoot":"","sources":["../../../../shared/models/server.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"server.model.d.ts","sourceRoot":"","sources":["../../../../shared/models/server.model.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { SESSION_MODE_VALUES, SESSION_MODE_STATEFUL } from './constants.js';
|
|
2
3
|
// ====== v1.1 Configuration Schema (Server Template + Instance Model) ======
|
|
3
4
|
/**
|
|
4
5
|
* Instance selection strategy constants for multi-instance servers
|
|
@@ -155,7 +156,8 @@ export const LoggingConfigSchema = z
|
|
|
155
156
|
jsonPretty: z.boolean().default(true),
|
|
156
157
|
mcpCommDebug: z.boolean().default(false),
|
|
157
158
|
apiDebug: z.boolean().default(false),
|
|
158
|
-
gatewayDebug: z.boolean().default(false)
|
|
159
|
+
gatewayDebug: z.boolean().default(false),
|
|
160
|
+
showTraceContext: z.boolean().default(true)
|
|
159
161
|
})
|
|
160
162
|
.default({
|
|
161
163
|
level: 'info',
|
|
@@ -163,7 +165,8 @@ export const LoggingConfigSchema = z
|
|
|
163
165
|
jsonPretty: true,
|
|
164
166
|
mcpCommDebug: false,
|
|
165
167
|
apiDebug: false,
|
|
166
|
-
gatewayDebug: false
|
|
168
|
+
gatewayDebug: false,
|
|
169
|
+
showTraceContext: true
|
|
167
170
|
});
|
|
168
171
|
// ====== Security Configuration Schema ======
|
|
169
172
|
/**
|
|
@@ -222,7 +225,19 @@ export const SystemConfigSchema = z.object({
|
|
|
222
225
|
theme: z.enum(['light', 'dark', 'system']).default('system'),
|
|
223
226
|
logging: LoggingConfigSchema,
|
|
224
227
|
// Using .optional() without .default() - code should use startup ?? {defaults} for default value
|
|
225
|
-
startup: StartupConfigSchema.optional()
|
|
228
|
+
startup: StartupConfigSchema.optional(),
|
|
229
|
+
session: z
|
|
230
|
+
.object({
|
|
231
|
+
sessionModeRules: z
|
|
232
|
+
.object({
|
|
233
|
+
stateful: z.array(z.string()).optional().default([]),
|
|
234
|
+
stateless: z.array(z.string()).optional().default([])
|
|
235
|
+
})
|
|
236
|
+
.optional()
|
|
237
|
+
.default({ stateful: [], stateless: [] }),
|
|
238
|
+
defaultSessionMode: z.enum(SESSION_MODE_VALUES).optional().default(SESSION_MODE_STATEFUL)
|
|
239
|
+
})
|
|
240
|
+
.optional()
|
|
226
241
|
})
|
|
227
242
|
.default({
|
|
228
243
|
host: 'localhost',
|
|
@@ -235,13 +250,21 @@ export const SystemConfigSchema = z.object({
|
|
|
235
250
|
jsonPretty: true,
|
|
236
251
|
mcpCommDebug: false,
|
|
237
252
|
apiDebug: false,
|
|
238
|
-
gatewayDebug: false
|
|
253
|
+
gatewayDebug: false,
|
|
254
|
+
showTraceContext: true
|
|
239
255
|
},
|
|
240
256
|
startup: {
|
|
241
257
|
startupDelay: 3000,
|
|
242
258
|
readyTimeout: 120000,
|
|
243
259
|
maxConnectRetries: 3,
|
|
244
260
|
connectRetryDelay: 5000
|
|
261
|
+
},
|
|
262
|
+
session: {
|
|
263
|
+
sessionModeRules: {
|
|
264
|
+
stateful: [],
|
|
265
|
+
stateless: []
|
|
266
|
+
},
|
|
267
|
+
defaultSessionMode: SESSION_MODE_STATEFUL
|
|
245
268
|
}
|
|
246
269
|
}),
|
|
247
270
|
security: SecurityConfigSchema,
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MCP Gateway endpoint using Streamable HTTP Transport
|
|
3
|
-
*
|
|
2
|
+
* MCP Gateway endpoint using stateful Streamable HTTP Transport.
|
|
3
|
+
*
|
|
4
|
+
* Each client session gets its own transport+server pair, identified by mcp-session-id header.
|
|
5
|
+
* POST without sessionId creates a new session.
|
|
6
|
+
* POST/GET/DELETE with sessionId routes to the existing session transport.
|
|
4
7
|
*/
|
|
5
|
-
import type { FastifyInstance } from 'fastify';
|
|
8
|
+
import type { FastifyInstance, FastifyRequest } from 'fastify';
|
|
9
|
+
import type { SessionMode } from '../../../shared/models/constants.js';
|
|
6
10
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* @param fastify - Fastify instance to register routes on
|
|
11
|
+
* Resolves the effective session mode for a request.
|
|
12
|
+
* Priority: request header > UA keyword match > default (SESSION_MODE_STATEFUL).
|
|
10
13
|
*/
|
|
14
|
+
export declare function resolveSessionMode(request: FastifyRequest): SessionMode;
|
|
11
15
|
export declare function mcpGatewayRoutes(fastify: FastifyInstance): Promise<void>;
|
|
12
16
|
//# sourceMappingURL=gateway.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../../../src/api/mcp/gateway.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"gateway.d.ts","sourceRoot":"","sources":["../../../../../src/api/mcp/gateway.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAgB,MAAM,SAAS,CAAC;AAmB7E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAK/D;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAsBvE;AAgBD,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,eAAe,iBAiP9D"}
|
|
@@ -1,93 +1,259 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* MCP Gateway endpoint using Streamable HTTP Transport
|
|
3
|
-
*
|
|
2
|
+
* MCP Gateway endpoint using stateful Streamable HTTP Transport.
|
|
3
|
+
*
|
|
4
|
+
* Each client session gets its own transport+server pair, identified by mcp-session-id header.
|
|
5
|
+
* POST without sessionId creates a new session.
|
|
6
|
+
* POST/GET/DELETE with sessionId routes to the existing session transport.
|
|
4
7
|
*/
|
|
8
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
9
|
+
import { randomUUID } from 'crypto';
|
|
5
10
|
import { logger, LOG_MODULES } from '../../utils/logger/index.js';
|
|
6
11
|
import { stringifyForLogging, getMcpCommDebugSetting, getGatewayDebugSetting } from '../../utils/json-utils.js';
|
|
7
12
|
import { wrapReplyForDebug } from './debug-response-wrapper.js';
|
|
8
|
-
import {
|
|
13
|
+
import { setupTransportLogging, createPerRequestTransport } from '../../services/gateway/global-transport.js';
|
|
14
|
+
import { sessionManager } from '../../services/gateway/session-manager.js';
|
|
15
|
+
import { gateway } from '../../services/gateway/gateway.service.js';
|
|
16
|
+
import { runWithRequestContext } from '../../utils/request-context.js';
|
|
17
|
+
import { configManager } from '../../config/config-manager.js';
|
|
18
|
+
import { SESSION_MODE_STATEFUL, SESSION_MODE_STATELESS } from '../../../shared/models/constants.js';
|
|
19
|
+
const MCP_SESSION_ID = 'mcp-session-id';
|
|
20
|
+
const MCP_SESSION_MODE = 'x-mcp-session-mode';
|
|
9
21
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
22
|
+
* Resolves the effective session mode for a request.
|
|
23
|
+
* Priority: request header > UA keyword match > default (SESSION_MODE_STATEFUL).
|
|
24
|
+
*/
|
|
25
|
+
export function resolveSessionMode(request) {
|
|
26
|
+
// 1. Request header override (highest priority)
|
|
27
|
+
const header = request.headers[MCP_SESSION_MODE];
|
|
28
|
+
if (header === SESSION_MODE_STATELESS || header === SESSION_MODE_STATEFUL)
|
|
29
|
+
return header;
|
|
30
|
+
// 2. UA keyword matching (case-insensitive)
|
|
31
|
+
const ua = request.headers['user-agent'] || '';
|
|
32
|
+
const config = configManager.getConfig();
|
|
33
|
+
const rules = config?.system?.session?.sessionModeRules;
|
|
34
|
+
if (rules && ua) {
|
|
35
|
+
const uaLower = ua.toLowerCase();
|
|
36
|
+
for (const pattern of rules.stateless || []) {
|
|
37
|
+
if (uaLower.includes(pattern.toLowerCase()))
|
|
38
|
+
return SESSION_MODE_STATELESS;
|
|
39
|
+
}
|
|
40
|
+
for (const pattern of rules.stateful || []) {
|
|
41
|
+
if (uaLower.includes(pattern.toLowerCase()))
|
|
42
|
+
return SESSION_MODE_STATEFUL;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// 3. Default fallback
|
|
46
|
+
return config?.system?.session?.defaultSessionMode ?? SESSION_MODE_STATEFUL;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Inject trace context into transport so that deferred send/onmessage wrappers
|
|
50
|
+
* can read it when ALS context is lost (MCP SDK defers send() calls internally).
|
|
13
51
|
*/
|
|
52
|
+
function injectTransportTrace(transport, sessionId, traceId) {
|
|
53
|
+
const ctx = transport;
|
|
54
|
+
ctx._traceSessionId = sessionId || undefined;
|
|
55
|
+
ctx._traceId = traceId;
|
|
56
|
+
}
|
|
14
57
|
export async function mcpGatewayRoutes(fastify) {
|
|
15
|
-
|
|
16
|
-
fastify.get('/mcp', (_request, reply) => {
|
|
17
|
-
reply.code(405).send({
|
|
18
|
-
jsonrpc: '2.0',
|
|
19
|
-
error: {
|
|
20
|
-
code: -32000,
|
|
21
|
-
message: 'GET /mcp is not supported. This is a Streamable HTTP MCP server — send POST /mcp with JSON-RPC requests directly.'
|
|
22
|
-
},
|
|
23
|
-
id: null
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
// POST /mcp — JSON-RPC request handling
|
|
27
|
-
const handlePostRequest = async (request, reply) => {
|
|
58
|
+
const logRequest = (request) => {
|
|
28
59
|
if (getMcpCommDebugSetting()) {
|
|
29
|
-
let
|
|
30
|
-
|
|
60
|
+
let msg = `MCP Gateway ${request.method} ${request.url}`;
|
|
61
|
+
msg += `\nRequest headers: ${stringifyForLogging(request.headers)}`;
|
|
31
62
|
if (request.body) {
|
|
32
63
|
try {
|
|
33
|
-
|
|
34
|
-
initialLogMsg += `\nBody: ${preview}`;
|
|
64
|
+
msg += `\nBody: ${stringifyForLogging(request.body)}`;
|
|
35
65
|
}
|
|
36
66
|
catch {
|
|
37
|
-
|
|
67
|
+
msg += '\nBody: [Unserializable]';
|
|
38
68
|
}
|
|
39
69
|
}
|
|
40
|
-
logger.debug(
|
|
70
|
+
logger.debug(msg, LOG_MODULES.COMMUNICATION);
|
|
41
71
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
reply.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
72
|
+
};
|
|
73
|
+
const sendError = (reply, statusCode, code, message, id = null) => {
|
|
74
|
+
if (!reply.raw.headersSent) {
|
|
75
|
+
reply.raw.writeHead(statusCode, { 'Content-Type': 'application/json' });
|
|
76
|
+
reply.raw.end(JSON.stringify({ jsonrpc: '2.0', error: { code, message }, id }));
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
fastify.all('/mcp', {
|
|
80
|
+
bodyLimit: 10 * 1024 * 1024,
|
|
81
|
+
handler: async (request, reply) => {
|
|
82
|
+
const sessionId = request.headers[MCP_SESSION_ID] || '';
|
|
83
|
+
const traceId = randomUUID();
|
|
84
|
+
await runWithRequestContext({ sessionId: sessionId || undefined, traceId }, async () => {
|
|
85
|
+
logRequest(request);
|
|
86
|
+
reply.header('Content-Type', 'application/json');
|
|
87
|
+
wrapReplyForDebug(reply, sessionId);
|
|
88
|
+
reply.hijack();
|
|
89
|
+
const sessionMode = resolveSessionMode(request);
|
|
90
|
+
if (sessionMode === SESSION_MODE_STATELESS) {
|
|
91
|
+
// Stateless mode: per-request transport, no session tracking, no SSE
|
|
92
|
+
if (request.method !== 'POST') {
|
|
93
|
+
sendError(reply, 405, -32000, 'GET/DELETE not supported in stateless session mode');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
const { transport } = await createPerRequestTransport();
|
|
98
|
+
injectTransportTrace(transport, undefined, traceId);
|
|
99
|
+
await transport.handleRequest(request.raw, reply.raw, request.body);
|
|
100
|
+
if (getGatewayDebugSetting()) {
|
|
101
|
+
logger.debug('Handled MCP request in stateless mode', LOG_MODULES.GATEWAY);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
106
|
+
const stack = error instanceof Error ? error.stack : 'No stack available';
|
|
107
|
+
logger.error(`Stateless MCP error: ${msg}`, LOG_MODULES.GATEWAY);
|
|
108
|
+
logger.error(`Stack: ${stack}`, LOG_MODULES.GATEWAY);
|
|
109
|
+
if (!reply.raw.headersSent) {
|
|
110
|
+
reply.raw.writeHead(500, { 'Content-Type': 'application/json' });
|
|
111
|
+
reply.raw.end(JSON.stringify({
|
|
112
|
+
jsonrpc: '2.0',
|
|
113
|
+
error: { code: -32000, message: 'Internal Server Error' },
|
|
114
|
+
id: null
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
57
119
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
120
|
+
try {
|
|
121
|
+
// Existing session — route to its transport
|
|
122
|
+
if (sessionId) {
|
|
123
|
+
const session = sessionManager.getSession(sessionId);
|
|
124
|
+
if (!session) {
|
|
125
|
+
sendError(reply, 404, -32001, 'Session not found');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
sessionManager.updateSessionMethod(sessionId, request.method);
|
|
129
|
+
// Track SSE stream to prevent stale cleanup while GET is active
|
|
130
|
+
if (request.method === 'GET') {
|
|
131
|
+
sessionManager.markSseOpened(sessionId);
|
|
132
|
+
}
|
|
133
|
+
injectTransportTrace(session.transport, sessionId, traceId);
|
|
134
|
+
await session.transport.handleRequest(request.raw, reply.raw, request.method === 'POST' ? request.body : undefined);
|
|
135
|
+
if (request.method === 'GET') {
|
|
136
|
+
sessionManager.markSseClosed(sessionId);
|
|
137
|
+
}
|
|
138
|
+
if (getGatewayDebugSetting()) {
|
|
139
|
+
logger.debug(`Handled MCP ${request.method} for session ${sessionId}`, LOG_MODULES.GATEWAY);
|
|
140
|
+
}
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
// New session — POST only (initialize)
|
|
144
|
+
if (request.method !== 'POST') {
|
|
145
|
+
sendError(reply, 400, -32000, 'Missing mcp-session-id header');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
// Create new stateful transport for this session
|
|
149
|
+
const transport = new StreamableHTTPServerTransport({
|
|
150
|
+
sessionIdGenerator: () => randomUUID(),
|
|
151
|
+
onsessionclosed: (id) => {
|
|
152
|
+
sessionManager.removeSession(id);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
setupTransportLogging(transport);
|
|
156
|
+
const server = gateway.createConnectionServer();
|
|
157
|
+
await server.connect(transport);
|
|
158
|
+
injectTransportTrace(transport, sessionId || undefined, traceId);
|
|
159
|
+
await transport.handleRequest(request.raw, reply.raw, request.body);
|
|
160
|
+
// After handleRequest completes, sessionId is available if init succeeded
|
|
161
|
+
const newSessionId = transport.sessionId;
|
|
162
|
+
if (newSessionId) {
|
|
163
|
+
sessionManager.addSession(newSessionId, transport, server);
|
|
164
|
+
}
|
|
165
|
+
if (getGatewayDebugSetting()) {
|
|
166
|
+
logger.debug(`Created new session ${newSessionId} via MCP POST`, LOG_MODULES.GATEWAY);
|
|
167
|
+
}
|
|
62
168
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
id: null
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
171
|
+
const errorStack = error instanceof Error ? error.stack : 'No stack available';
|
|
172
|
+
logger.error(`Error handling MCP request: ${errorMessage}`, LOG_MODULES.GATEWAY);
|
|
173
|
+
logger.error(`Full error stack: ${errorStack}`, LOG_MODULES.GATEWAY);
|
|
174
|
+
logger.error(`Request body: ${stringifyForLogging(request.body)}`, LOG_MODULES.GATEWAY);
|
|
175
|
+
if (!reply.raw.headersSent) {
|
|
176
|
+
reply.raw.writeHead(500, { 'Content-Type': 'application/json' });
|
|
177
|
+
reply.raw.end(JSON.stringify({
|
|
178
|
+
jsonrpc: '2.0',
|
|
179
|
+
error: { code: -32000, message: 'Internal Server Error' },
|
|
180
|
+
id: null
|
|
181
|
+
}));
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
});
|
|
82
185
|
}
|
|
83
|
-
};
|
|
84
|
-
fastify.post('/mcp', {
|
|
85
|
-
bodyLimit: 10 * 1024 * 1024, // 10MB limit
|
|
86
|
-
handler: handlePostRequest
|
|
87
186
|
});
|
|
88
187
|
// Subpath fallback
|
|
89
|
-
fastify.
|
|
188
|
+
fastify.all('/mcp/*', {
|
|
90
189
|
bodyLimit: 10 * 1024 * 1024,
|
|
91
|
-
handler:
|
|
190
|
+
handler: async (request, reply) => {
|
|
191
|
+
const sessionId = request.headers[MCP_SESSION_ID] || '';
|
|
192
|
+
const traceId = randomUUID();
|
|
193
|
+
await runWithRequestContext({ sessionId: sessionId || undefined, traceId }, async () => {
|
|
194
|
+
logRequest(request);
|
|
195
|
+
reply.header('Content-Type', 'application/json');
|
|
196
|
+
wrapReplyForDebug(reply, sessionId);
|
|
197
|
+
reply.hijack();
|
|
198
|
+
const sessionMode = resolveSessionMode(request);
|
|
199
|
+
if (sessionMode === SESSION_MODE_STATELESS) {
|
|
200
|
+
if (request.method !== 'POST') {
|
|
201
|
+
sendError(reply, 405, -32000, 'GET/DELETE not supported in stateless session mode');
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
try {
|
|
205
|
+
const { transport } = await createPerRequestTransport();
|
|
206
|
+
injectTransportTrace(transport, undefined, traceId);
|
|
207
|
+
await transport.handleRequest(request.raw, reply.raw, request.body);
|
|
208
|
+
}
|
|
209
|
+
catch (error) {
|
|
210
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
211
|
+
logger.error(`Stateless MCP subpath error: ${msg}`, LOG_MODULES.GATEWAY);
|
|
212
|
+
sendError(reply, 500, -32000, 'Internal Server Error');
|
|
213
|
+
}
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
if (!sessionId) {
|
|
217
|
+
if (!reply.raw.headersSent) {
|
|
218
|
+
reply.raw.writeHead(400, { 'Content-Type': 'application/json' });
|
|
219
|
+
reply.raw.end(JSON.stringify({
|
|
220
|
+
jsonrpc: '2.0',
|
|
221
|
+
error: { code: -32000, message: 'Missing mcp-session-id header' },
|
|
222
|
+
id: null
|
|
223
|
+
}));
|
|
224
|
+
}
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const session = sessionManager.getSession(sessionId);
|
|
228
|
+
if (!session) {
|
|
229
|
+
if (!reply.raw.headersSent) {
|
|
230
|
+
reply.raw.writeHead(404, { 'Content-Type': 'application/json' });
|
|
231
|
+
reply.raw.end(JSON.stringify({
|
|
232
|
+
jsonrpc: '2.0',
|
|
233
|
+
error: { code: -32001, message: 'Session not found' },
|
|
234
|
+
id: null
|
|
235
|
+
}));
|
|
236
|
+
}
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
sessionManager.updateSessionMethod(sessionId, request.method);
|
|
241
|
+
injectTransportTrace(session.transport, sessionId, traceId);
|
|
242
|
+
await session.transport.handleRequest(request.raw, reply.raw, request.method === 'POST' ? request.body : undefined);
|
|
243
|
+
}
|
|
244
|
+
catch (error) {
|
|
245
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
246
|
+
logger.error(`Error handling MCP subpath request: ${errorMessage}`, LOG_MODULES.GATEWAY);
|
|
247
|
+
if (!reply.raw.headersSent) {
|
|
248
|
+
reply.raw.writeHead(500, { 'Content-Type': 'application/json' });
|
|
249
|
+
reply.raw.end(JSON.stringify({
|
|
250
|
+
jsonrpc: '2.0',
|
|
251
|
+
error: { code: -32000, message: 'Internal Server Error' },
|
|
252
|
+
id: null
|
|
253
|
+
}));
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
});
|
|
257
|
+
}
|
|
92
258
|
});
|
|
93
259
|
}
|
|
@@ -1,29 +1,3 @@
|
|
|
1
1
|
import { FastifyInstance } from 'fastify';
|
|
2
|
-
|
|
3
|
-
* Session Management API Routes
|
|
4
|
-
*
|
|
5
|
-
* Provides comprehensive session management endpoints for the MCP Hub Lite system's persistent session storage.
|
|
6
|
-
* This module enables administrators and clients to monitor, inspect, and manage active and persisted sessions
|
|
7
|
-
* that maintain client connection state across service restarts.
|
|
8
|
-
*
|
|
9
|
-
* Sessions store critical client context including connection metadata, working directories, project information,
|
|
10
|
-
* and other state that enables seamless reconnection and continuity of operations. The session persistence
|
|
11
|
-
* feature ensures that client connections can be restored even after service interruptions.
|
|
12
|
-
*
|
|
13
|
-
* Key features include:
|
|
14
|
-
* - Listing all persisted sessions with metadata
|
|
15
|
-
* - Detailed session inspection by session ID
|
|
16
|
-
* - Session deletion for cleanup and maintenance
|
|
17
|
-
* - Integration with the MCP session manager for consistency
|
|
18
|
-
*
|
|
19
|
-
* @param fastify - The Fastify instance to register routes on
|
|
20
|
-
* @returns Promise that resolves when all routes are registered
|
|
21
|
-
*
|
|
22
|
-
* @example
|
|
23
|
-
* ```typescript
|
|
24
|
-
* // Register session management routes
|
|
25
|
-
* await webSessionRoutes(app);
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export declare function webSessionRoutes(fastify: FastifyInstance): Promise<void>;
|
|
2
|
+
export declare function webSessionsRoutes(fastify: FastifyInstance): Promise<void>;
|
|
29
3
|
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../../../src/api/web/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../../../../src/api/web/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK1C,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,eAAe,iBAU/D"}
|