mcp-use 1.34.7 → 1.34.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/{chunk-6ERGZHCN.js → chunk-4KPCPZWE.js} +1 -1
- package/dist/{chunk-XRLI6ZYX.js → chunk-5ZFGXHAU.js} +1 -1
- package/dist/{chunk-PJARRPKP.js → chunk-ENBB6Z2J.js} +5 -5
- package/dist/{chunk-YGL37XKG.js → chunk-FXO3CJ7N.js} +2 -2
- package/dist/{chunk-XILMNNJF.js → chunk-HIRI2UY6.js} +7 -7
- package/dist/{chunk-LOSPF4H5.js → chunk-I3P2KX5U.js} +1 -1
- package/dist/{chunk-SGT4D4LO.js → chunk-MG47YFCC.js} +1 -1
- package/dist/{chunk-QEYINRZL.js → chunk-NCK7SUJD.js} +4 -4
- package/dist/{chunk-RRCHCSPQ.js → chunk-RDJKEIOW.js} +2 -2
- package/dist/{chunk-E7PWRUQZ.js → chunk-SZYMINCU.js} +1 -1
- package/dist/{chunk-ESSZPKPU.js → chunk-TYVQPHZW.js} +1 -1
- package/dist/{client-Y2ZVEDQC.js → client-YE5FSLWK.js} +4 -4
- package/dist/index.cjs +1 -1
- package/dist/index.js +33 -33
- package/dist/src/agents/index.cjs +1 -1
- package/dist/src/agents/index.js +6 -6
- package/dist/src/browser-agent.cjs +1 -1
- package/dist/src/browser-agent.js +2 -2
- package/dist/src/browser.cjs +1 -1
- package/dist/src/browser.js +4 -4
- package/dist/src/client.cjs +1 -1
- package/dist/src/client.js +6 -6
- package/dist/src/react/index.cjs +1 -1
- package/dist/src/react/index.js +4 -4
- package/dist/src/server/connect-adapter.d.ts.map +1 -1
- package/dist/src/server/endpoints/mount-mcp.d.ts.map +1 -1
- package/dist/src/server/index.cjs +431 -240
- package/dist/src/server/index.js +438 -247
- package/dist/src/server/logging.d.ts +2 -1
- package/dist/src/server/logging.d.ts.map +1 -1
- package/dist/src/server/sessions/streams/redis.d.ts +18 -0
- package/dist/src/server/sessions/streams/redis.d.ts.map +1 -1
- package/dist/src/version.d.ts +1 -1
- package/dist/{stdio-BJKCQSAY.js → stdio-5L34RAVM.js} +4 -4
- package/dist/{stdio-3JX4DSGH.js → stdio-RCVXPUI4.js} +2 -2
- package/dist/{tool-execution-helpers-YOE4JC6H.js → tool-execution-helpers-IJTPZL55.js} +3 -3
- package/package.json +3 -3
package/dist/src/server/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
findSessionContext,
|
|
18
18
|
isValidLogLevel,
|
|
19
19
|
supportsApps
|
|
20
|
-
} from "../../chunk-
|
|
20
|
+
} from "../../chunk-SZYMINCU.js";
|
|
21
21
|
import {
|
|
22
22
|
getRequestContext,
|
|
23
23
|
hasRequestContext,
|
|
@@ -59,7 +59,8 @@ import {
|
|
|
59
59
|
Telemetry,
|
|
60
60
|
VERSION,
|
|
61
61
|
getPackageVersion
|
|
62
|
-
} from "../../chunk-
|
|
62
|
+
} from "../../chunk-NCK7SUJD.js";
|
|
63
|
+
import "../../chunk-BXZHMYMM.js";
|
|
63
64
|
import {
|
|
64
65
|
fsHelpers,
|
|
65
66
|
generateUUID,
|
|
@@ -69,7 +70,6 @@ import {
|
|
|
69
70
|
pathHelpers
|
|
70
71
|
} from "../../chunk-MTHLLDCX.js";
|
|
71
72
|
import "../../chunk-QWQYAQCK.js";
|
|
72
|
-
import "../../chunk-BXZHMYMM.js";
|
|
73
73
|
import {
|
|
74
74
|
__name
|
|
75
75
|
} from "../../chunk-3GQAWCBQ.js";
|
|
@@ -942,27 +942,19 @@ function isExpressMiddleware(middleware) {
|
|
|
942
942
|
}
|
|
943
943
|
const paramCount = middleware.length;
|
|
944
944
|
const fnString = middleware.toString();
|
|
945
|
-
const
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
/\bres\.statusCode\s*=/,
|
|
951
|
-
/\bres\.writeHead\s*\(/
|
|
945
|
+
const expressResponsePatterns = [
|
|
946
|
+
/(?<![\w$.])res\.(send|json|status|end|redirect|render|sendFile|download)\b/,
|
|
947
|
+
/(?<![\w$.])res\.set\s*\(/,
|
|
948
|
+
/(?<![\w$.])res\.statusCode\s*=/,
|
|
949
|
+
/(?<![\w$.])res\.writeHead\s*\(/
|
|
952
950
|
];
|
|
953
|
-
const
|
|
951
|
+
const hasExpressResponsePattern = expressResponsePatterns.some(
|
|
954
952
|
(pattern) => pattern.test(fnString)
|
|
955
953
|
);
|
|
956
954
|
if (paramCount === 3 || paramCount === 4) {
|
|
957
|
-
if (hasExpressPattern) {
|
|
958
|
-
return true;
|
|
959
|
-
}
|
|
960
955
|
return true;
|
|
961
956
|
}
|
|
962
957
|
if (paramCount === 2) {
|
|
963
|
-
if (hasExpressPattern) {
|
|
964
|
-
return true;
|
|
965
|
-
}
|
|
966
958
|
const honoPatterns = [
|
|
967
959
|
/\bc\.(req|res|json|text|html|status|header)\b/,
|
|
968
960
|
/\bc\.get\s*\(/,
|
|
@@ -975,7 +967,7 @@ function isExpressMiddleware(middleware) {
|
|
|
975
967
|
if (hasHonoPattern) {
|
|
976
968
|
return false;
|
|
977
969
|
}
|
|
978
|
-
return
|
|
970
|
+
return hasExpressResponsePattern;
|
|
979
971
|
}
|
|
980
972
|
return false;
|
|
981
973
|
}
|
|
@@ -1020,31 +1012,51 @@ async function adaptConnectMiddleware(connectMiddleware, middlewarePath) {
|
|
|
1020
1012
|
...request.body && { body: request.body }
|
|
1021
1013
|
});
|
|
1022
1014
|
const mockResponse = createResponse();
|
|
1023
|
-
|
|
1024
|
-
|
|
1015
|
+
const res = await new Promise((resolve, reject) => {
|
|
1016
|
+
let responseSettled = false;
|
|
1017
|
+
const resolveResponse = /* @__PURE__ */ __name((response) => {
|
|
1018
|
+
if (responseSettled) return;
|
|
1019
|
+
responseSettled = true;
|
|
1020
|
+
resolve(response);
|
|
1021
|
+
}, "resolveResponse");
|
|
1022
|
+
const rejectResponse = /* @__PURE__ */ __name((error2) => {
|
|
1023
|
+
if (responseSettled) return;
|
|
1024
|
+
responseSettled = true;
|
|
1025
|
+
reject(error2);
|
|
1026
|
+
}, "rejectResponse");
|
|
1025
1027
|
const originalEnd = mockResponse.end.bind(mockResponse);
|
|
1026
1028
|
mockResponse.end = (...args) => {
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1029
|
+
try {
|
|
1030
|
+
const result = originalEnd(...args);
|
|
1031
|
+
if (!responseSettled && mockResponse.writableEnded) {
|
|
1032
|
+
const statusCode = mockResponse.statusCode;
|
|
1033
|
+
const noBodyStatuses = [204, 304];
|
|
1034
|
+
const responseBody = noBodyStatuses.includes(statusCode) ? null : mockResponse._getData() || mockResponse._getBuffer() || null;
|
|
1035
|
+
const connectResponse = new Response(responseBody, {
|
|
1036
|
+
status: statusCode,
|
|
1037
|
+
statusText: mockResponse.statusMessage,
|
|
1038
|
+
headers: mockResponse.getHeaders()
|
|
1039
|
+
});
|
|
1040
|
+
resolveResponse(connectResponse);
|
|
1041
|
+
}
|
|
1042
|
+
return result;
|
|
1043
|
+
} catch (error2) {
|
|
1044
|
+
rejectResponse(error2);
|
|
1045
|
+
return mockResponse;
|
|
1039
1046
|
}
|
|
1040
|
-
return result;
|
|
1041
1047
|
};
|
|
1042
|
-
|
|
1043
|
-
if (
|
|
1044
|
-
|
|
1048
|
+
const connectNext = /* @__PURE__ */ __name((error2) => {
|
|
1049
|
+
if (responseSettled) return;
|
|
1050
|
+
if (error2) {
|
|
1051
|
+
rejectResponse(error2);
|
|
1052
|
+
return;
|
|
1053
|
+
}
|
|
1054
|
+
if (mockResponse.writableEnded) return;
|
|
1055
|
+
try {
|
|
1045
1056
|
const statusCode = mockResponse.statusCode;
|
|
1046
1057
|
const noBodyStatuses = [204, 304];
|
|
1047
|
-
const
|
|
1058
|
+
const buffer = mockResponse._getBuffer();
|
|
1059
|
+
const responseBody = noBodyStatuses.includes(statusCode) ? null : mockResponse._getData() || (buffer.length > 0 ? buffer : null);
|
|
1048
1060
|
const preparedHeaders = c.newResponse(null, 204, {}).headers;
|
|
1049
1061
|
for (const key of [...preparedHeaders.keys()]) {
|
|
1050
1062
|
if (preparedHeaders.has(key)) {
|
|
@@ -1065,14 +1077,23 @@ async function adaptConnectMiddleware(connectMiddleware, middlewarePath) {
|
|
|
1065
1077
|
}
|
|
1066
1078
|
c.status(statusCode);
|
|
1067
1079
|
if (noBodyStatuses.includes(statusCode)) {
|
|
1068
|
-
|
|
1080
|
+
resolveResponse(c.newResponse(null, statusCode));
|
|
1069
1081
|
} else if (responseBody) {
|
|
1070
|
-
|
|
1082
|
+
resolveResponse(c.body(responseBody));
|
|
1071
1083
|
} else {
|
|
1072
|
-
|
|
1084
|
+
resolveResponse(void 0);
|
|
1073
1085
|
}
|
|
1086
|
+
} catch (error3) {
|
|
1087
|
+
rejectResponse(error3);
|
|
1074
1088
|
}
|
|
1075
|
-
});
|
|
1089
|
+
}, "connectNext");
|
|
1090
|
+
try {
|
|
1091
|
+
Promise.resolve(
|
|
1092
|
+
connectMiddleware(mockRequest, mockResponse, connectNext)
|
|
1093
|
+
).catch(rejectResponse);
|
|
1094
|
+
} catch (error2) {
|
|
1095
|
+
rejectResponse(error2);
|
|
1096
|
+
}
|
|
1076
1097
|
});
|
|
1077
1098
|
if (res) {
|
|
1078
1099
|
c.res = res;
|
|
@@ -3332,7 +3353,7 @@ function registerPrompt(promptDefinition, callback) {
|
|
|
3332
3353
|
}
|
|
3333
3354
|
const wrappedCallback = /* @__PURE__ */ __name(async (params, extra) => {
|
|
3334
3355
|
const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await import("../../context-storage-KMOAHEL7.js");
|
|
3335
|
-
const { findSessionContext: findSessionContext2, createClientCapabilityChecker } = await import("../../tool-execution-helpers-
|
|
3356
|
+
const { findSessionContext: findSessionContext2, createClientCapabilityChecker } = await import("../../tool-execution-helpers-IJTPZL55.js");
|
|
3336
3357
|
const initialRequestContext = getRequestContext2();
|
|
3337
3358
|
const sessions = this.sessions || /* @__PURE__ */ new Map();
|
|
3338
3359
|
const { requestContext, session } = findSessionContext2(
|
|
@@ -3537,7 +3558,7 @@ function registerResource(resourceDefinition, callback) {
|
|
|
3537
3558
|
const explicitMimeType = resourceDefinition.mimeType;
|
|
3538
3559
|
const wrappedCallback = /* @__PURE__ */ __name(async () => {
|
|
3539
3560
|
const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await import("../../context-storage-KMOAHEL7.js");
|
|
3540
|
-
const { findSessionContext: findSessionContext2, createClientCapabilityChecker } = await import("../../tool-execution-helpers-
|
|
3561
|
+
const { findSessionContext: findSessionContext2, createClientCapabilityChecker } = await import("../../tool-execution-helpers-IJTPZL55.js");
|
|
3541
3562
|
const initialRequestContext = getRequestContext2();
|
|
3542
3563
|
const sessions = this.sessions || /* @__PURE__ */ new Map();
|
|
3543
3564
|
const { requestContext, session } = findSessionContext2(
|
|
@@ -3625,7 +3646,7 @@ function registerResourceTemplate(resourceTemplateDefinition, callback) {
|
|
|
3625
3646
|
async (uri) => {
|
|
3626
3647
|
const params = this.parseTemplateUri(uriTemplate, uri.toString());
|
|
3627
3648
|
const { getRequestContext: getRequestContext2, runWithContext: runWithContext2 } = await import("../../context-storage-KMOAHEL7.js");
|
|
3628
|
-
const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-
|
|
3649
|
+
const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-IJTPZL55.js");
|
|
3629
3650
|
const initialRequestContext = getRequestContext2();
|
|
3630
3651
|
const sessions = this.sessions || /* @__PURE__ */ new Map();
|
|
3631
3652
|
const { requestContext } = findSessionContext2(
|
|
@@ -5099,11 +5120,17 @@ var RedisStreamManager = class {
|
|
|
5099
5120
|
* Key: sessionId, Value: controller
|
|
5100
5121
|
*/
|
|
5101
5122
|
localControllers = /* @__PURE__ */ new Map();
|
|
5123
|
+
streamGenerations = /* @__PURE__ */ new Map();
|
|
5102
5124
|
/**
|
|
5103
5125
|
* Map of heartbeat intervals for keeping sessions alive
|
|
5104
5126
|
* Key: sessionId, Value: interval timer
|
|
5105
5127
|
*/
|
|
5106
5128
|
heartbeats = /* @__PURE__ */ new Map();
|
|
5129
|
+
// Track attempted subscriptions separately from controllers: a disconnected
|
|
5130
|
+
// controller or a rejected subscribe() must not lose its cleanup ownership.
|
|
5131
|
+
sessionSubscriptions = /* @__PURE__ */ new Map();
|
|
5132
|
+
sessionOperations = /* @__PURE__ */ new Map();
|
|
5133
|
+
closing = false;
|
|
5107
5134
|
/**
|
|
5108
5135
|
* Unique identifier for this server instance, used for request/response routing.
|
|
5109
5136
|
*/
|
|
@@ -5116,6 +5143,7 @@ var RedisStreamManager = class {
|
|
|
5116
5143
|
* Whether the server-level response channel subscription is active.
|
|
5117
5144
|
*/
|
|
5118
5145
|
serverChannelSubscribed = false;
|
|
5146
|
+
serverChannelSubscription;
|
|
5119
5147
|
constructor(config) {
|
|
5120
5148
|
this.pubSubClient = config.pubSubClient;
|
|
5121
5149
|
this.client = config.client;
|
|
@@ -5140,90 +5168,265 @@ var RedisStreamManager = class {
|
|
|
5140
5168
|
getActiveSessionsKey() {
|
|
5141
5169
|
return `${this.prefix}active`;
|
|
5142
5170
|
}
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5171
|
+
withSessionOperation(sessionId, operation) {
|
|
5172
|
+
const previous = this.sessionOperations.get(sessionId) ?? Promise.resolve();
|
|
5173
|
+
const result = previous.then(operation);
|
|
5174
|
+
const settled = result.then(
|
|
5175
|
+
() => {
|
|
5176
|
+
},
|
|
5177
|
+
() => {
|
|
5178
|
+
}
|
|
5179
|
+
);
|
|
5180
|
+
this.sessionOperations.set(sessionId, settled);
|
|
5181
|
+
void settled.then(() => {
|
|
5182
|
+
if (this.sessionOperations.get(sessionId) === settled) {
|
|
5183
|
+
this.sessionOperations.delete(sessionId);
|
|
5184
|
+
}
|
|
5185
|
+
});
|
|
5186
|
+
return result;
|
|
5187
|
+
}
|
|
5188
|
+
clearLocalStream(sessionId) {
|
|
5189
|
+
const heartbeat = this.heartbeats.get(sessionId);
|
|
5190
|
+
if (heartbeat) clearInterval(heartbeat);
|
|
5191
|
+
this.heartbeats.delete(sessionId);
|
|
5192
|
+
const controller = this.localControllers.get(sessionId);
|
|
5193
|
+
this.localControllers.delete(sessionId);
|
|
5194
|
+
this.streamGenerations.delete(sessionId);
|
|
5195
|
+
this.closeController(controller);
|
|
5196
|
+
}
|
|
5197
|
+
closeController(controller) {
|
|
5148
5198
|
try {
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
|
|
5152
|
-
|
|
5153
|
-
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5199
|
+
controller?.close();
|
|
5200
|
+
} catch {
|
|
5201
|
+
}
|
|
5202
|
+
}
|
|
5203
|
+
async unsubscribeSession(sessionId) {
|
|
5204
|
+
const channels = this.sessionSubscriptions.get(sessionId);
|
|
5205
|
+
if (!channels?.size) return;
|
|
5206
|
+
if (!this.pubSubClient.unsubscribe) {
|
|
5207
|
+
throw new Error(
|
|
5208
|
+
"[RedisStreamManager] Redis client does not support unsubscribe method"
|
|
5209
|
+
);
|
|
5210
|
+
}
|
|
5211
|
+
const results = await Promise.allSettled(
|
|
5212
|
+
Array.from(channels, async (channel) => {
|
|
5213
|
+
await this.pubSubClient.unsubscribe(channel);
|
|
5214
|
+
channels.delete(channel);
|
|
5215
|
+
})
|
|
5216
|
+
);
|
|
5217
|
+
if (!channels.size) this.sessionSubscriptions.delete(sessionId);
|
|
5218
|
+
this.throwCleanupError(results);
|
|
5219
|
+
}
|
|
5220
|
+
throwCleanupError(results) {
|
|
5221
|
+
const failed = results.find((result) => result.status === "rejected");
|
|
5222
|
+
if (failed?.status === "rejected") throw failed.reason;
|
|
5223
|
+
}
|
|
5224
|
+
async markAvailable(sessionId) {
|
|
5225
|
+
const key = this.getAvailableKey(sessionId);
|
|
5226
|
+
const ttl = this.heartbeatInterval * 2;
|
|
5227
|
+
if (this.client.setEx) {
|
|
5228
|
+
await this.client.setEx(key, ttl, "active");
|
|
5229
|
+
} else if (this.client.setex) {
|
|
5230
|
+
await this.client.setex(key, ttl, "active");
|
|
5231
|
+
} else {
|
|
5232
|
+
await this.client.set(key, "active", { EX: ttl });
|
|
5233
|
+
if (this.client.expire) await this.client.expire(key, ttl);
|
|
5234
|
+
}
|
|
5235
|
+
if (this.client.sAdd) {
|
|
5236
|
+
await this.client.sAdd(this.getActiveSessionsKey(), sessionId);
|
|
5237
|
+
await this.client.expire?.(this.getActiveSessionsKey(), ttl);
|
|
5238
|
+
}
|
|
5239
|
+
}
|
|
5240
|
+
async removeAvailability(sessionId) {
|
|
5241
|
+
const results = await Promise.allSettled([
|
|
5242
|
+
Promise.resolve().then(
|
|
5243
|
+
() => this.client.del(this.getAvailableKey(sessionId))
|
|
5244
|
+
),
|
|
5245
|
+
Promise.resolve().then(
|
|
5246
|
+
() => this.client.sRem?.(this.getActiveSessionsKey(), sessionId)
|
|
5247
|
+
)
|
|
5248
|
+
]);
|
|
5249
|
+
this.throwCleanupError(results);
|
|
5250
|
+
}
|
|
5251
|
+
async removeStream(sessionId, notifyOtherServers, cleanupAvailability = true) {
|
|
5252
|
+
this.clearLocalStream(sessionId);
|
|
5253
|
+
const results = await Promise.allSettled([
|
|
5254
|
+
this.unsubscribeSession(sessionId),
|
|
5255
|
+
cleanupAvailability ? this.removeAvailability(sessionId) : Promise.resolve()
|
|
5256
|
+
]);
|
|
5257
|
+
if (notifyOtherServers) {
|
|
5258
|
+
results.push(
|
|
5259
|
+
...await Promise.allSettled([
|
|
5260
|
+
Promise.resolve().then(() => {
|
|
5261
|
+
if (!this.client.publish) {
|
|
5262
|
+
throw new Error(
|
|
5263
|
+
"[RedisStreamManager] Redis client does not support publish method"
|
|
5264
|
+
);
|
|
5265
|
+
}
|
|
5266
|
+
return this.client.publish(
|
|
5267
|
+
`delete:${this.getChannel(sessionId)}`,
|
|
5268
|
+
""
|
|
5269
|
+
);
|
|
5270
|
+
})
|
|
5271
|
+
])
|
|
5272
|
+
);
|
|
5273
|
+
}
|
|
5274
|
+
this.throwCleanupError(results);
|
|
5275
|
+
}
|
|
5276
|
+
// These factories have no enclosing controller or handler argument. Redis
|
|
5277
|
+
// may retain their callbacks after a failed unsubscribe, so the callbacks
|
|
5278
|
+
// must resolve controllers/handlers through the manager rather than capture
|
|
5279
|
+
// a registration operation's context.
|
|
5280
|
+
createMessageCallback(sessionId, generation) {
|
|
5281
|
+
return (message) => {
|
|
5282
|
+
if (this.streamGenerations.get(sessionId) !== generation) return;
|
|
5283
|
+
const controller = this.localControllers.get(sessionId);
|
|
5284
|
+
if (!controller) return;
|
|
5285
|
+
try {
|
|
5286
|
+
controller.enqueue(this.textEncoder.encode(message));
|
|
5287
|
+
} catch {
|
|
5288
|
+
this.clearLocalStream(sessionId);
|
|
5289
|
+
this.cleanupDisconnectedStream(sessionId);
|
|
5162
5290
|
}
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5291
|
+
};
|
|
5292
|
+
}
|
|
5293
|
+
cleanupDisconnectedStream(sessionId) {
|
|
5294
|
+
void this.withSessionOperation(sessionId, async () => {
|
|
5295
|
+
if (!this.localControllers.has(sessionId)) {
|
|
5296
|
+
await this.unsubscribeSession(sessionId);
|
|
5168
5297
|
}
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
5298
|
+
}).catch((error2) => {
|
|
5299
|
+
console.warn(
|
|
5300
|
+
`[RedisStreamManager] Failed to unsubscribe disconnected stream ${sessionId}:`,
|
|
5301
|
+
error2
|
|
5302
|
+
);
|
|
5303
|
+
});
|
|
5304
|
+
}
|
|
5305
|
+
createDeleteCallback(sessionId, generation) {
|
|
5306
|
+
return () => {
|
|
5307
|
+
if (this.streamGenerations.get(sessionId) !== generation) return;
|
|
5308
|
+
void this.withSessionOperation(
|
|
5309
|
+
sessionId,
|
|
5310
|
+
() => this.removeStream(sessionId, false)
|
|
5311
|
+
).catch((error2) => {
|
|
5312
|
+
console.warn(
|
|
5313
|
+
`[RedisStreamManager] Failed to clean up deleted stream ${sessionId}:`,
|
|
5314
|
+
error2
|
|
5315
|
+
);
|
|
5316
|
+
});
|
|
5317
|
+
};
|
|
5318
|
+
}
|
|
5319
|
+
startHeartbeat(sessionId) {
|
|
5320
|
+
const availableKey = this.getAvailableKey(sessionId);
|
|
5321
|
+
const activeSessionsKey = this.getActiveSessionsKey();
|
|
5322
|
+
const heartbeat = setInterval(async () => {
|
|
5323
|
+
try {
|
|
5172
5324
|
if (this.client.expire) {
|
|
5325
|
+
await this.client.expire(availableKey, this.heartbeatInterval * 2);
|
|
5173
5326
|
await this.client.expire(
|
|
5174
5327
|
activeSessionsKey,
|
|
5175
5328
|
this.heartbeatInterval * 2
|
|
5176
5329
|
);
|
|
5177
5330
|
}
|
|
5331
|
+
} catch (error2) {
|
|
5332
|
+
console.warn(
|
|
5333
|
+
`[RedisStreamManager] Heartbeat failed for session ${sessionId}:`,
|
|
5334
|
+
error2
|
|
5335
|
+
);
|
|
5178
5336
|
}
|
|
5179
|
-
|
|
5180
|
-
|
|
5181
|
-
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5186
|
-
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
|
|
5190
|
-
|
|
5191
|
-
|
|
5192
|
-
|
|
5337
|
+
}, this.heartbeatInterval * 1e3);
|
|
5338
|
+
this.heartbeats.set(sessionId, heartbeat);
|
|
5339
|
+
}
|
|
5340
|
+
createForwardedResponseCallback() {
|
|
5341
|
+
return (raw) => {
|
|
5342
|
+
try {
|
|
5343
|
+
const { response, sessionId } = JSON.parse(raw);
|
|
5344
|
+
this.forwardedResponseHandler?.(response, sessionId);
|
|
5345
|
+
} catch (error2) {
|
|
5346
|
+
console.warn(
|
|
5347
|
+
`[RedisStreamManager] Failed to parse forwarded response:`,
|
|
5348
|
+
error2
|
|
5349
|
+
);
|
|
5350
|
+
}
|
|
5351
|
+
};
|
|
5352
|
+
}
|
|
5353
|
+
/**
|
|
5354
|
+
* Register an active SSE stream and subscribe to Redis channel.
|
|
5355
|
+
* Idempotent: if the session already has a subscription, it is cleaned up first.
|
|
5356
|
+
*/
|
|
5357
|
+
async create(sessionId, controller) {
|
|
5358
|
+
return this.withSessionOperation(sessionId, async () => {
|
|
5359
|
+
if (this.closing) {
|
|
5360
|
+
this.closeController(controller);
|
|
5361
|
+
throw new Error("[RedisStreamManager] Stream manager is closed");
|
|
5362
|
+
}
|
|
5363
|
+
if (this.localControllers.get(sessionId) === controller) return;
|
|
5364
|
+
this.clearLocalStream(sessionId);
|
|
5365
|
+
let controllerRegistered = false;
|
|
5366
|
+
try {
|
|
5367
|
+
await this.unsubscribeSession(sessionId);
|
|
5368
|
+
if (this.closing) {
|
|
5369
|
+
throw new Error("[RedisStreamManager] Stream manager is closed");
|
|
5370
|
+
}
|
|
5371
|
+
this.localControllers.set(sessionId, controller);
|
|
5372
|
+
controllerRegistered = true;
|
|
5373
|
+
const generation = Symbol(sessionId);
|
|
5374
|
+
this.streamGenerations.set(sessionId, generation);
|
|
5375
|
+
if (!this.pubSubClient.subscribe) {
|
|
5376
|
+
throw new Error(
|
|
5377
|
+
"[RedisStreamManager] Redis client does not support subscribe method"
|
|
5193
5378
|
);
|
|
5194
5379
|
}
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
|
|
5380
|
+
const channels = /* @__PURE__ */ new Set();
|
|
5381
|
+
this.sessionSubscriptions.set(sessionId, channels);
|
|
5382
|
+
const channel = this.getChannel(sessionId);
|
|
5383
|
+
channels.add(channel);
|
|
5384
|
+
await this.pubSubClient.subscribe(
|
|
5385
|
+
channel,
|
|
5386
|
+
this.createMessageCallback(sessionId, generation)
|
|
5201
5387
|
);
|
|
5202
|
-
|
|
5203
|
-
|
|
5204
|
-
|
|
5205
|
-
|
|
5206
|
-
|
|
5207
|
-
|
|
5208
|
-
|
|
5209
|
-
|
|
5388
|
+
const deleteChannel = `delete:${channel}`;
|
|
5389
|
+
channels.add(deleteChannel);
|
|
5390
|
+
await this.pubSubClient.subscribe(
|
|
5391
|
+
deleteChannel,
|
|
5392
|
+
this.createDeleteCallback(sessionId, generation)
|
|
5393
|
+
);
|
|
5394
|
+
if (this.closing || this.streamGenerations.get(sessionId) !== generation) {
|
|
5395
|
+
throw new Error(
|
|
5396
|
+
"[RedisStreamManager] Stream closed during registration"
|
|
5397
|
+
);
|
|
5398
|
+
}
|
|
5399
|
+
await this.markAvailable(sessionId);
|
|
5400
|
+
if (this.closing || this.streamGenerations.get(sessionId) !== generation) {
|
|
5401
|
+
throw new Error(
|
|
5402
|
+
"[RedisStreamManager] Stream closed during registration"
|
|
5403
|
+
);
|
|
5404
|
+
}
|
|
5405
|
+
this.startHeartbeat(sessionId);
|
|
5406
|
+
console.log(
|
|
5407
|
+
`[RedisStreamManager] Created stream for session ${sessionId}`
|
|
5408
|
+
);
|
|
5409
|
+
} catch (error2) {
|
|
5410
|
+
this.clearLocalStream(sessionId);
|
|
5411
|
+
if (!controllerRegistered) this.closeController(controller);
|
|
5412
|
+
const cleanups = await Promise.allSettled([
|
|
5413
|
+
this.unsubscribeSession(sessionId)
|
|
5414
|
+
]);
|
|
5415
|
+
for (const cleanup of cleanups) {
|
|
5416
|
+
if (cleanup.status === "rejected") {
|
|
5417
|
+
console.warn(
|
|
5418
|
+
`[RedisStreamManager] Failed to roll back stream ${sessionId}:`,
|
|
5419
|
+
cleanup.reason
|
|
5420
|
+
);
|
|
5210
5421
|
}
|
|
5211
5422
|
}
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
|
|
5218
|
-
|
|
5219
|
-
);
|
|
5220
|
-
} catch (error2) {
|
|
5221
|
-
console.error(
|
|
5222
|
-
`[RedisStreamManager] Error creating stream for ${sessionId}:`,
|
|
5223
|
-
error2
|
|
5224
|
-
);
|
|
5225
|
-
throw error2;
|
|
5226
|
-
}
|
|
5423
|
+
console.error(
|
|
5424
|
+
`[RedisStreamManager] Error creating stream for ${sessionId}:`,
|
|
5425
|
+
error2
|
|
5426
|
+
);
|
|
5427
|
+
throw error2;
|
|
5428
|
+
}
|
|
5429
|
+
});
|
|
5227
5430
|
}
|
|
5228
5431
|
/**
|
|
5229
5432
|
* Send data to sessions via Redis Pub/Sub
|
|
@@ -5241,6 +5444,22 @@ var RedisStreamManager = class {
|
|
|
5241
5444
|
if (this.client.sMembers) {
|
|
5242
5445
|
const sessionIds2 = await this.client.sMembers(activeSessionsKey);
|
|
5243
5446
|
for (const sessionId of sessionIds2) {
|
|
5447
|
+
const availableKey = this.getAvailableKey(sessionId);
|
|
5448
|
+
if (await this.client.exists(availableKey) !== 1) {
|
|
5449
|
+
await this.client.sRem?.(activeSessionsKey, sessionId);
|
|
5450
|
+
let available;
|
|
5451
|
+
try {
|
|
5452
|
+
available = await this.client.exists(availableKey);
|
|
5453
|
+
} catch (error2) {
|
|
5454
|
+
try {
|
|
5455
|
+
await this.client.sAdd?.(activeSessionsKey, sessionId);
|
|
5456
|
+
} catch {
|
|
5457
|
+
}
|
|
5458
|
+
throw error2;
|
|
5459
|
+
}
|
|
5460
|
+
if (available !== 1) continue;
|
|
5461
|
+
await this.client.sAdd?.(activeSessionsKey, sessionId);
|
|
5462
|
+
}
|
|
5244
5463
|
const channel = this.getChannel(sessionId);
|
|
5245
5464
|
if (!this.client.publish) {
|
|
5246
5465
|
throw new Error(
|
|
@@ -5283,53 +5502,20 @@ var RedisStreamManager = class {
|
|
|
5283
5502
|
* Remove an active SSE stream
|
|
5284
5503
|
*/
|
|
5285
5504
|
async delete(sessionId) {
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
}
|
|
5292
|
-
const channel = this.getChannel(sessionId);
|
|
5293
|
-
const deleteChannel = `delete:${channel}`;
|
|
5294
|
-
if (!this.pubSubClient.unsubscribe) {
|
|
5295
|
-
throw new Error(
|
|
5296
|
-
"[RedisStreamManager] Redis client does not support unsubscribe method"
|
|
5505
|
+
return this.withSessionOperation(sessionId, async () => {
|
|
5506
|
+
try {
|
|
5507
|
+
await this.removeStream(sessionId, true);
|
|
5508
|
+
console.log(
|
|
5509
|
+
`[RedisStreamManager] Deleted stream for session ${sessionId}`
|
|
5297
5510
|
);
|
|
5298
|
-
}
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5302
|
-
throw new Error(
|
|
5303
|
-
"[RedisStreamManager] Redis client does not support publish method"
|
|
5511
|
+
} catch (error2) {
|
|
5512
|
+
console.error(
|
|
5513
|
+
`[RedisStreamManager] Error deleting stream for ${sessionId}:`,
|
|
5514
|
+
error2
|
|
5304
5515
|
);
|
|
5516
|
+
throw error2;
|
|
5305
5517
|
}
|
|
5306
|
-
|
|
5307
|
-
await this.client.del(this.getAvailableKey(sessionId));
|
|
5308
|
-
const activeSessionsKey = this.getActiveSessionsKey();
|
|
5309
|
-
if (this.client.sRem) {
|
|
5310
|
-
await this.client.sRem(activeSessionsKey, sessionId);
|
|
5311
|
-
}
|
|
5312
|
-
const controller = this.localControllers.get(sessionId);
|
|
5313
|
-
if (controller) {
|
|
5314
|
-
try {
|
|
5315
|
-
controller.close();
|
|
5316
|
-
} catch (error2) {
|
|
5317
|
-
console.debug(
|
|
5318
|
-
`[RedisStreamManager] Controller already closed for ${sessionId}`
|
|
5319
|
-
);
|
|
5320
|
-
}
|
|
5321
|
-
this.localControllers.delete(sessionId);
|
|
5322
|
-
}
|
|
5323
|
-
console.log(
|
|
5324
|
-
`[RedisStreamManager] Deleted stream for session ${sessionId}`
|
|
5325
|
-
);
|
|
5326
|
-
} catch (error2) {
|
|
5327
|
-
console.error(
|
|
5328
|
-
`[RedisStreamManager] Error deleting stream for ${sessionId}:`,
|
|
5329
|
-
error2
|
|
5330
|
-
);
|
|
5331
|
-
throw error2;
|
|
5332
|
-
}
|
|
5518
|
+
});
|
|
5333
5519
|
}
|
|
5334
5520
|
/**
|
|
5335
5521
|
* Check if a session has an active stream (on ANY server)
|
|
@@ -5351,31 +5537,42 @@ var RedisStreamManager = class {
|
|
|
5351
5537
|
* Close all connections and cleanup
|
|
5352
5538
|
*/
|
|
5353
5539
|
async close() {
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
this.heartbeats.
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5362
|
-
|
|
5363
|
-
|
|
5364
|
-
|
|
5365
|
-
|
|
5366
|
-
|
|
5367
|
-
|
|
5368
|
-
|
|
5369
|
-
|
|
5370
|
-
|
|
5540
|
+
this.closing = true;
|
|
5541
|
+
this.forwardedResponseHandler = void 0;
|
|
5542
|
+
const sessionIds = /* @__PURE__ */ new Set([
|
|
5543
|
+
...this.localControllers.keys(),
|
|
5544
|
+
...this.heartbeats.keys(),
|
|
5545
|
+
...this.sessionSubscriptions.keys(),
|
|
5546
|
+
...this.sessionOperations.keys()
|
|
5547
|
+
]);
|
|
5548
|
+
for (const sessionId of sessionIds) this.clearLocalStream(sessionId);
|
|
5549
|
+
const results = await Promise.allSettled([
|
|
5550
|
+
...Array.from(
|
|
5551
|
+
sessionIds,
|
|
5552
|
+
(sessionId) => this.withSessionOperation(
|
|
5553
|
+
sessionId,
|
|
5554
|
+
() => (
|
|
5555
|
+
// Shared availability expires after shutdown; deleting it here
|
|
5556
|
+
// could invalidate another manager serving the same session.
|
|
5557
|
+
this.removeStream(sessionId, false, false)
|
|
5558
|
+
)
|
|
5559
|
+
)
|
|
5560
|
+
),
|
|
5561
|
+
Promise.resolve().then(async () => {
|
|
5562
|
+
await this.serverChannelSubscription;
|
|
5563
|
+
if (this.serverChannelSubscribed) {
|
|
5564
|
+
if (!this.pubSubClient.unsubscribe) {
|
|
5565
|
+
throw new Error(
|
|
5566
|
+
"[RedisStreamManager] Redis client does not support unsubscribe method"
|
|
5567
|
+
);
|
|
5568
|
+
}
|
|
5569
|
+
await this.pubSubClient.unsubscribe(this.getServerChannel());
|
|
5570
|
+
this.serverChannelSubscribed = false;
|
|
5371
5571
|
}
|
|
5372
|
-
}
|
|
5373
|
-
|
|
5374
|
-
|
|
5375
|
-
|
|
5376
|
-
console.error(`[RedisStreamManager] Error during close:`, error2);
|
|
5377
|
-
throw error2;
|
|
5378
|
-
}
|
|
5572
|
+
})
|
|
5573
|
+
]);
|
|
5574
|
+
this.throwCleanupError(results);
|
|
5575
|
+
console.log(`[RedisStreamManager] Closed all streams`);
|
|
5379
5576
|
}
|
|
5380
5577
|
/**
|
|
5381
5578
|
* Get count of active local streams on this server instance
|
|
@@ -5440,9 +5637,9 @@ var RedisStreamManager = class {
|
|
|
5440
5637
|
* Subscribes to this server's dedicated Pub/Sub channel.
|
|
5441
5638
|
*/
|
|
5442
5639
|
onForwardedResponse(handler) {
|
|
5640
|
+
if (this.closing) return;
|
|
5443
5641
|
this.forwardedResponseHandler = handler;
|
|
5444
5642
|
if (this.serverChannelSubscribed) return;
|
|
5445
|
-
this.serverChannelSubscribed = true;
|
|
5446
5643
|
const serverChannel = this.getServerChannel();
|
|
5447
5644
|
if (!this.pubSubClient.subscribe) {
|
|
5448
5645
|
console.warn(
|
|
@@ -5450,17 +5647,21 @@ var RedisStreamManager = class {
|
|
|
5450
5647
|
);
|
|
5451
5648
|
return;
|
|
5452
5649
|
}
|
|
5453
|
-
this.
|
|
5650
|
+
this.serverChannelSubscribed = true;
|
|
5651
|
+
this.serverChannelSubscription = Promise.resolve().then(
|
|
5652
|
+
() => this.pubSubClient.subscribe(
|
|
5653
|
+
serverChannel,
|
|
5654
|
+
this.createForwardedResponseCallback()
|
|
5655
|
+
)
|
|
5656
|
+
).then(() => {
|
|
5657
|
+
}).catch(async (error2) => {
|
|
5454
5658
|
try {
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
error2
|
|
5461
|
-
);
|
|
5659
|
+
if (this.pubSubClient.unsubscribe) {
|
|
5660
|
+
await this.pubSubClient.unsubscribe(serverChannel);
|
|
5661
|
+
this.serverChannelSubscribed = false;
|
|
5662
|
+
}
|
|
5663
|
+
} catch {
|
|
5462
5664
|
}
|
|
5463
|
-
}).catch((error2) => {
|
|
5464
5665
|
console.error(
|
|
5465
5666
|
`[RedisStreamManager] Failed to subscribe to server channel:`,
|
|
5466
5667
|
error2
|
|
@@ -5528,37 +5729,21 @@ async function extractResponseError(res) {
|
|
|
5528
5729
|
return null;
|
|
5529
5730
|
}
|
|
5530
5731
|
if (!text2) return null;
|
|
5531
|
-
|
|
5532
|
-
|
|
5533
|
-
|
|
5534
|
-
|
|
5535
|
-
|
|
5536
|
-
try {
|
|
5537
|
-
payloads.push(JSON.parse(raw));
|
|
5538
|
-
} catch {
|
|
5539
|
-
}
|
|
5540
|
-
}, "tryParse");
|
|
5541
|
-
if (isSse) {
|
|
5542
|
-
for (const line of text2.split(/\r?\n/)) {
|
|
5543
|
-
if (line.startsWith("data:")) {
|
|
5544
|
-
const data = line.slice(5).trim();
|
|
5545
|
-
if (data) tryParse(data);
|
|
5546
|
-
}
|
|
5547
|
-
}
|
|
5548
|
-
} else {
|
|
5549
|
-
tryParse(text2);
|
|
5732
|
+
let payload;
|
|
5733
|
+
try {
|
|
5734
|
+
payload = JSON.parse(text2);
|
|
5735
|
+
} catch {
|
|
5736
|
+
return null;
|
|
5550
5737
|
}
|
|
5551
|
-
for (const
|
|
5552
|
-
|
|
5553
|
-
|
|
5554
|
-
|
|
5555
|
-
|
|
5556
|
-
|
|
5557
|
-
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
return textBlock ? String(textBlock.text) : "tool error";
|
|
5561
|
-
}
|
|
5738
|
+
for (const msg of Array.isArray(payload) ? payload : [payload]) {
|
|
5739
|
+
if (!msg || typeof msg !== "object") continue;
|
|
5740
|
+
const m = msg;
|
|
5741
|
+
if (typeof m.error?.message === "string") return m.error.message;
|
|
5742
|
+
if (m.result?.isError === true) {
|
|
5743
|
+
const textBlock = Array.isArray(m.result.content) ? m.result.content.find(
|
|
5744
|
+
(b) => b?.type === "text" && typeof b.text === "string"
|
|
5745
|
+
) : null;
|
|
5746
|
+
return textBlock ? String(textBlock.text) : "tool error";
|
|
5562
5747
|
}
|
|
5563
5748
|
}
|
|
5564
5749
|
return null;
|
|
@@ -5602,6 +5787,7 @@ async function requestLogger(c, next) {
|
|
|
5602
5787
|
await next();
|
|
5603
5788
|
const durationMs = Date.now() - startedAt;
|
|
5604
5789
|
const statusCode = c.res.status;
|
|
5790
|
+
const isStreaming = c.res.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase() === "text/event-stream";
|
|
5605
5791
|
const incomingSid = c.req.header("mcp-session-id");
|
|
5606
5792
|
const responseSid = c.res.headers.get("mcp-session-id");
|
|
5607
5793
|
const mcpMethod = requestBody?.method;
|
|
@@ -5640,7 +5826,7 @@ async function requestLogger(c, next) {
|
|
|
5640
5826
|
parts.push(chalk2.gray(`\u2192 session=${shortSessionId(responseSid)}`));
|
|
5641
5827
|
}
|
|
5642
5828
|
let outcomePart;
|
|
5643
|
-
const errMsg = await extractResponseError(c.res);
|
|
5829
|
+
const errMsg = isStreaming ? null : await extractResponseError(c.res);
|
|
5644
5830
|
if (errMsg) {
|
|
5645
5831
|
outcomePart = chalk2.red(`ERROR ${errMsg}`);
|
|
5646
5832
|
} else if (mcpMethod) {
|
|
@@ -5676,7 +5862,9 @@ async function requestLogger(c, next) {
|
|
|
5676
5862
|
console.log(formatForLogging(responseHeaders));
|
|
5677
5863
|
}
|
|
5678
5864
|
try {
|
|
5679
|
-
if (
|
|
5865
|
+
if (isStreaming) {
|
|
5866
|
+
console.log(chalk2.yellow("Response Body:") + " (streaming; skipped)");
|
|
5867
|
+
} else if (c.res.body !== null && c.res.body !== void 0) {
|
|
5680
5868
|
try {
|
|
5681
5869
|
const clonedResponse = c.res.clone();
|
|
5682
5870
|
const responseBody = await clonedResponse.text().catch(() => null);
|
|
@@ -5789,6 +5977,29 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
5789
5977
|
}));
|
|
5790
5978
|
const streamManager = config.streamManager ?? new InMemoryStreamManager();
|
|
5791
5979
|
const transports = /* @__PURE__ */ new Map();
|
|
5980
|
+
const cleanupClosedSession = /* @__PURE__ */ __name(async (sid) => {
|
|
5981
|
+
if (getDebugLevel() !== "info") {
|
|
5982
|
+
console.log(`[MCP] Session closed: ${sid}`);
|
|
5983
|
+
}
|
|
5984
|
+
transports.delete(sid);
|
|
5985
|
+
sessions.delete(sid);
|
|
5986
|
+
const cleanups = await Promise.allSettled([
|
|
5987
|
+
Promise.resolve().then(
|
|
5988
|
+
() => mcpServerInstance.cleanupSessionSubscriptions?.(sid)
|
|
5989
|
+
),
|
|
5990
|
+
Promise.resolve().then(() => mcpServerInstance.cleanupSessionRefs?.(sid)),
|
|
5991
|
+
Promise.resolve().then(() => streamManager.delete(sid)),
|
|
5992
|
+
Promise.resolve().then(() => sessionStore.delete(sid))
|
|
5993
|
+
]);
|
|
5994
|
+
for (const cleanup of cleanups) {
|
|
5995
|
+
if (cleanup.status === "rejected") {
|
|
5996
|
+
console.warn(
|
|
5997
|
+
`[MCP] Error cleaning up closed session ${sid}:`,
|
|
5998
|
+
cleanup.reason
|
|
5999
|
+
);
|
|
6000
|
+
}
|
|
6001
|
+
}
|
|
6002
|
+
}, "cleanupClosedSession");
|
|
5792
6003
|
if (streamManager.onForwardedResponse) {
|
|
5793
6004
|
streamManager.onForwardedResponse((message, sid) => {
|
|
5794
6005
|
const transport = transports.get(sid);
|
|
@@ -5933,17 +6144,7 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
5933
6144
|
console.log(`[MCP] Session re-initialized: ${sid}`);
|
|
5934
6145
|
}
|
|
5935
6146
|
}, "onsessioninitialized"),
|
|
5936
|
-
onsessionclosed:
|
|
5937
|
-
if (getDebugLevel() !== "info") {
|
|
5938
|
-
console.log(`[MCP] Session closed: ${sid}`);
|
|
5939
|
-
}
|
|
5940
|
-
transports.delete(sid);
|
|
5941
|
-
await streamManager.delete(sid);
|
|
5942
|
-
await sessionStore.delete(sid);
|
|
5943
|
-
sessions.delete(sid);
|
|
5944
|
-
mcpServerInstance.cleanupSessionSubscriptions?.(sid);
|
|
5945
|
-
mcpServerInstance.cleanupSessionRefs?.(sid);
|
|
5946
|
-
}, "onsessionclosed")
|
|
6147
|
+
onsessionclosed: cleanupClosedSession
|
|
5947
6148
|
});
|
|
5948
6149
|
wrapTransportForStreamManager(transport, sessionId, streamManager);
|
|
5949
6150
|
await server.connect(transport);
|
|
@@ -6069,17 +6270,7 @@ async function mountMcp(app, mcpServerInstance, sessions, config, isProductionMo
|
|
|
6069
6270
|
);
|
|
6070
6271
|
};
|
|
6071
6272
|
}, "onsessioninitialized"),
|
|
6072
|
-
onsessionclosed:
|
|
6073
|
-
if (getDebugLevel() !== "info") {
|
|
6074
|
-
console.log(`[MCP] Session closed: ${sid}`);
|
|
6075
|
-
}
|
|
6076
|
-
transports.delete(sid);
|
|
6077
|
-
await streamManager.delete(sid);
|
|
6078
|
-
await sessionStore.delete(sid);
|
|
6079
|
-
sessions.delete(sid);
|
|
6080
|
-
mcpServerInstance.cleanupSessionSubscriptions?.(sid);
|
|
6081
|
-
mcpServerInstance.cleanupSessionRefs?.(sid);
|
|
6082
|
-
}, "onsessionclosed")
|
|
6273
|
+
onsessionclosed: cleanupClosedSession
|
|
6083
6274
|
});
|
|
6084
6275
|
allocatedTransport = transport;
|
|
6085
6276
|
wrapTransportForStreamManager(transport, newSessionId, streamManager);
|
|
@@ -7021,7 +7212,7 @@ var MCPServerClass = class _MCPServerClass {
|
|
|
7021
7212
|
onSampling: /* @__PURE__ */ __name(async (params) => {
|
|
7022
7213
|
try {
|
|
7023
7214
|
const { getRequestContext: getRequestContext2 } = await import("../../context-storage-KMOAHEL7.js");
|
|
7024
|
-
const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-
|
|
7215
|
+
const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-IJTPZL55.js");
|
|
7025
7216
|
const ctx = getRequestContext2();
|
|
7026
7217
|
if (!ctx) throw new Error("No request context");
|
|
7027
7218
|
const { session } = findSessionContext2(
|
|
@@ -7049,7 +7240,7 @@ var MCPServerClass = class _MCPServerClass {
|
|
|
7049
7240
|
onElicitation: /* @__PURE__ */ __name(async (params) => {
|
|
7050
7241
|
try {
|
|
7051
7242
|
const { getRequestContext: getRequestContext2 } = await import("../../context-storage-KMOAHEL7.js");
|
|
7052
|
-
const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-
|
|
7243
|
+
const { findSessionContext: findSessionContext2 } = await import("../../tool-execution-helpers-IJTPZL55.js");
|
|
7053
7244
|
const ctx = getRequestContext2();
|
|
7054
7245
|
if (!ctx) throw new Error("No request context");
|
|
7055
7246
|
const { session } = findSessionContext2(
|