@mcp-ts/sdk 1.3.1 → 1.3.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/README.md +371 -290
- package/dist/adapters/agui-adapter.d.mts +3 -3
- package/dist/adapters/agui-adapter.d.ts +3 -3
- package/dist/adapters/agui-middleware.d.mts +3 -3
- package/dist/adapters/agui-middleware.d.ts +3 -3
- package/dist/adapters/ai-adapter.d.mts +3 -3
- package/dist/adapters/ai-adapter.d.ts +3 -3
- package/dist/adapters/langchain-adapter.d.mts +3 -3
- package/dist/adapters/langchain-adapter.d.ts +3 -3
- package/dist/adapters/mastra-adapter.d.mts +3 -3
- package/dist/adapters/mastra-adapter.d.ts +3 -3
- package/dist/client/index.d.mts +10 -66
- package/dist/client/index.d.ts +10 -66
- package/dist/client/index.js +91 -173
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +91 -173
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +15 -5
- package/dist/client/react.d.ts +15 -5
- package/dist/client/react.js +130 -182
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +130 -182
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +27 -7
- package/dist/client/vue.d.ts +27 -7
- package/dist/client/vue.js +131 -182
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +131 -182
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{events-BgeztGYZ.d.mts → events-CK3N--3g.d.mts} +2 -0
- package/dist/{events-BgeztGYZ.d.ts → events-CK3N--3g.d.ts} +2 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +224 -258
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +224 -258
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CxogNckF.d.mts → multi-session-client-DzjmT7FX.d.mts} +4 -10
- package/dist/{multi-session-client-cox_WXUj.d.ts → multi-session-client-FAFpUzZ4.d.ts} +4 -10
- package/dist/server/index.d.mts +18 -23
- package/dist/server/index.d.ts +18 -23
- package/dist/server/index.js +133 -85
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +133 -85
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +3 -3
- package/dist/shared/index.d.ts +3 -3
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{types-CLccx9wW.d.mts → types-CW6lghof.d.mts} +6 -0
- package/dist/{types-CLccx9wW.d.ts → types-CW6lghof.d.ts} +6 -0
- package/package.json +1 -1
- package/src/client/core/sse-client.ts +354 -493
- package/src/client/react/index.ts +16 -16
- package/src/client/react/use-mcp-apps.tsx +214 -214
- package/src/client/react/use-mcp.ts +84 -19
- package/src/client/vue/use-mcp.ts +119 -44
- package/src/server/handlers/nextjs-handler.ts +207 -217
- package/src/server/handlers/sse-handler.ts +14 -0
- package/src/server/mcp/oauth-client.ts +48 -46
- package/src/server/storage/types.ts +12 -5
- package/src/shared/events.ts +2 -0
- package/src/shared/types.ts +6 -0
package/dist/server/index.mjs
CHANGED
|
@@ -1002,18 +1002,15 @@ var MCPClient = class _MCPClient {
|
|
|
1002
1002
|
__publicField(this, "serverUrl");
|
|
1003
1003
|
__publicField(this, "callbackUrl");
|
|
1004
1004
|
__publicField(this, "onRedirect");
|
|
1005
|
-
__publicField(this, "tokens");
|
|
1006
|
-
__publicField(this, "tokenExpiresAt");
|
|
1007
|
-
__publicField(this, "clientInformation");
|
|
1008
1005
|
__publicField(this, "clientId");
|
|
1009
1006
|
__publicField(this, "clientSecret");
|
|
1010
|
-
__publicField(this, "onSaveTokens");
|
|
1011
1007
|
__publicField(this, "headers");
|
|
1012
1008
|
/** OAuth Client Metadata */
|
|
1013
1009
|
__publicField(this, "clientName");
|
|
1014
1010
|
__publicField(this, "clientUri");
|
|
1015
1011
|
__publicField(this, "logoUri");
|
|
1016
1012
|
__publicField(this, "policyUri");
|
|
1013
|
+
__publicField(this, "createdAt");
|
|
1017
1014
|
/** Event emitters for connection lifecycle */
|
|
1018
1015
|
__publicField(this, "_onConnectionEvent", new Emitter());
|
|
1019
1016
|
__publicField(this, "onConnectionEvent", this._onConnectionEvent.event);
|
|
@@ -1028,12 +1025,8 @@ var MCPClient = class _MCPClient {
|
|
|
1028
1025
|
this.serverId = options.serverId;
|
|
1029
1026
|
this.sessionId = options.sessionId;
|
|
1030
1027
|
this.transportType = options.transportType;
|
|
1031
|
-
this.tokens = options.tokens;
|
|
1032
|
-
this.tokenExpiresAt = options.tokenExpiresAt;
|
|
1033
|
-
this.clientInformation = options.clientInformation;
|
|
1034
1028
|
this.clientId = options.clientId;
|
|
1035
1029
|
this.clientSecret = options.clientSecret;
|
|
1036
|
-
this.onSaveTokens = options.onSaveTokens;
|
|
1037
1030
|
this.headers = options.headers;
|
|
1038
1031
|
this.clientName = options.clientName;
|
|
1039
1032
|
this.clientUri = options.clientUri;
|
|
@@ -1053,6 +1046,8 @@ var MCPClient = class _MCPClient {
|
|
|
1053
1046
|
sessionId: this.sessionId,
|
|
1054
1047
|
serverId: this.serverId,
|
|
1055
1048
|
serverName: this.serverName || this.serverId,
|
|
1049
|
+
serverUrl: this.serverUrl || "",
|
|
1050
|
+
createdAt: this.createdAt,
|
|
1056
1051
|
state: newState,
|
|
1057
1052
|
previousState,
|
|
1058
1053
|
timestamp: Date.now()
|
|
@@ -1173,6 +1168,7 @@ var MCPClient = class _MCPClient {
|
|
|
1173
1168
|
this.serverName = this.serverName || sessionData.serverName;
|
|
1174
1169
|
this.serverId = this.serverId || sessionData.serverId || "unknown";
|
|
1175
1170
|
this.headers = this.headers || sessionData.headers;
|
|
1171
|
+
this.createdAt = sessionData.createdAt;
|
|
1176
1172
|
}
|
|
1177
1173
|
if (!this.serverUrl || !this.callbackUrl || !this.serverId) {
|
|
1178
1174
|
throw new Error("Missing required connection metadata");
|
|
@@ -1226,6 +1222,7 @@ var MCPClient = class _MCPClient {
|
|
|
1226
1222
|
}
|
|
1227
1223
|
const existingSession = await storage.getSession(this.identity, this.sessionId);
|
|
1228
1224
|
if (!existingSession && this.serverId && this.serverUrl && this.callbackUrl) {
|
|
1225
|
+
this.createdAt = Date.now();
|
|
1229
1226
|
console.log(`[MCPClient] Creating initial session ${this.sessionId} for OAuth flow`);
|
|
1230
1227
|
await storage.createSession({
|
|
1231
1228
|
sessionId: this.sessionId,
|
|
@@ -1235,7 +1232,8 @@ var MCPClient = class _MCPClient {
|
|
|
1235
1232
|
serverUrl: this.serverUrl,
|
|
1236
1233
|
callbackUrl: this.callbackUrl,
|
|
1237
1234
|
transportType: this.transportType || "streamable_http",
|
|
1238
|
-
createdAt:
|
|
1235
|
+
createdAt: this.createdAt,
|
|
1236
|
+
active: false
|
|
1239
1237
|
}, Math.floor(STATE_EXPIRATION_MS / 1e3));
|
|
1240
1238
|
}
|
|
1241
1239
|
}
|
|
@@ -1243,9 +1241,10 @@ var MCPClient = class _MCPClient {
|
|
|
1243
1241
|
* Saves current session state to storage
|
|
1244
1242
|
* Creates new session if it doesn't exist, updates if it does
|
|
1245
1243
|
* @param ttl - Time-to-live in seconds (defaults to 12hr for connected sessions)
|
|
1244
|
+
* @param active - Session status marker used to avoid unnecessary TTL rewrites
|
|
1246
1245
|
* @private
|
|
1247
1246
|
*/
|
|
1248
|
-
async saveSession(ttl = SESSION_TTL_SECONDS) {
|
|
1247
|
+
async saveSession(ttl = SESSION_TTL_SECONDS, active = true) {
|
|
1249
1248
|
if (!this.sessionId || !this.serverId || !this.serverUrl || !this.callbackUrl) {
|
|
1250
1249
|
return;
|
|
1251
1250
|
}
|
|
@@ -1257,7 +1256,8 @@ var MCPClient = class _MCPClient {
|
|
|
1257
1256
|
serverUrl: this.serverUrl,
|
|
1258
1257
|
callbackUrl: this.callbackUrl,
|
|
1259
1258
|
transportType: this.transportType || "streamable_http",
|
|
1260
|
-
createdAt: Date.now()
|
|
1259
|
+
createdAt: this.createdAt || Date.now(),
|
|
1260
|
+
active
|
|
1261
1261
|
};
|
|
1262
1262
|
const existingSession = await storage.getSession(this.identity, this.sessionId);
|
|
1263
1263
|
if (existingSession) {
|
|
@@ -1331,15 +1331,17 @@ var MCPClient = class _MCPClient {
|
|
|
1331
1331
|
this.emitStateChange("CONNECTED");
|
|
1332
1332
|
this.emitProgress("Connected successfully");
|
|
1333
1333
|
const existingSession = await storage.getSession(this.identity, this.sessionId);
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1334
|
+
const needsTransportUpdate = !existingSession || existingSession.transportType !== this.transportType;
|
|
1335
|
+
const needsTtlPromotion = !existingSession || existingSession.active !== true;
|
|
1336
|
+
if (needsTransportUpdate || needsTtlPromotion) {
|
|
1337
|
+
console.log(`[MCPClient] Saving session ${this.sessionId} with 12hr TTL (connect success)`);
|
|
1338
|
+
await this.saveSession(SESSION_TTL_SECONDS, true);
|
|
1337
1339
|
}
|
|
1338
1340
|
} catch (error) {
|
|
1339
1341
|
if (error instanceof UnauthorizedError$1 || error instanceof Error && error.message.toLowerCase().includes("unauthorized")) {
|
|
1340
1342
|
this.emitStateChange("AUTHENTICATING");
|
|
1341
1343
|
console.log(`[MCPClient] Saving session ${this.sessionId} with 10min TTL (OAuth pending)`);
|
|
1342
|
-
await this.saveSession(Math.floor(STATE_EXPIRATION_MS / 1e3));
|
|
1344
|
+
await this.saveSession(Math.floor(STATE_EXPIRATION_MS / 1e3), false);
|
|
1343
1345
|
let authUrl = "";
|
|
1344
1346
|
if (this.oauthProvider) {
|
|
1345
1347
|
authUrl = this.oauthProvider.authUrl || "";
|
|
@@ -1417,7 +1419,7 @@ var MCPClient = class _MCPClient {
|
|
|
1417
1419
|
await this.client.connect(this.transport);
|
|
1418
1420
|
this.emitStateChange("CONNECTED");
|
|
1419
1421
|
console.log(`[MCPClient] Updating session ${this.sessionId} to 12hr TTL (OAuth complete)`);
|
|
1420
|
-
await this.saveSession(SESSION_TTL_SECONDS);
|
|
1422
|
+
await this.saveSession(SESSION_TTL_SECONDS, true);
|
|
1421
1423
|
return;
|
|
1422
1424
|
} catch (error) {
|
|
1423
1425
|
lastError = error;
|
|
@@ -2081,7 +2083,9 @@ var SSEConnectionManager = class {
|
|
|
2081
2083
|
serverId: s.serverId,
|
|
2082
2084
|
serverName: s.serverName,
|
|
2083
2085
|
serverUrl: s.serverUrl,
|
|
2084
|
-
transport: s.transportType
|
|
2086
|
+
transport: s.transportType,
|
|
2087
|
+
createdAt: s.createdAt,
|
|
2088
|
+
active: s.active !== false
|
|
2085
2089
|
}))
|
|
2086
2090
|
};
|
|
2087
2091
|
}
|
|
@@ -2096,6 +2100,13 @@ var SSEConnectionManager = class {
|
|
|
2096
2100
|
(s) => s.serverId === serverId || s.serverUrl === serverUrl
|
|
2097
2101
|
);
|
|
2098
2102
|
if (duplicate) {
|
|
2103
|
+
if (duplicate.active === false) {
|
|
2104
|
+
await this.restoreSession({ sessionId: duplicate.sessionId });
|
|
2105
|
+
return {
|
|
2106
|
+
sessionId: duplicate.sessionId,
|
|
2107
|
+
success: true
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2099
2110
|
throw new Error(`Connection already exists for server: ${duplicate.serverUrl || duplicate.serverId} (${duplicate.serverName})`);
|
|
2100
2111
|
}
|
|
2101
2112
|
const sessionId = await storage.generateSessionId();
|
|
@@ -2104,6 +2115,7 @@ var SSEConnectionManager = class {
|
|
|
2104
2115
|
sessionId,
|
|
2105
2116
|
serverId,
|
|
2106
2117
|
serverName,
|
|
2118
|
+
serverUrl,
|
|
2107
2119
|
state: "CONNECTING",
|
|
2108
2120
|
previousState: "DISCONNECTED",
|
|
2109
2121
|
timestamp: Date.now()
|
|
@@ -2236,6 +2248,7 @@ var SSEConnectionManager = class {
|
|
|
2236
2248
|
sessionId,
|
|
2237
2249
|
serverId: session.serverId ?? "unknown",
|
|
2238
2250
|
serverName: session.serverName ?? "Unknown",
|
|
2251
|
+
serverUrl: session.serverUrl,
|
|
2239
2252
|
state: "VALIDATING",
|
|
2240
2253
|
previousState: "DISCONNECTED",
|
|
2241
2254
|
timestamp: Date.now()
|
|
@@ -2287,6 +2300,7 @@ var SSEConnectionManager = class {
|
|
|
2287
2300
|
sessionId,
|
|
2288
2301
|
serverId: session.serverId ?? "unknown",
|
|
2289
2302
|
serverName: session.serverName ?? "Unknown",
|
|
2303
|
+
serverUrl: session.serverUrl,
|
|
2290
2304
|
state: "AUTHENTICATING",
|
|
2291
2305
|
previousState: "DISCONNECTED",
|
|
2292
2306
|
timestamp: Date.now()
|
|
@@ -2418,7 +2432,9 @@ function writeSSEEvent(res, event, data) {
|
|
|
2418
2432
|
}
|
|
2419
2433
|
|
|
2420
2434
|
// src/server/handlers/nextjs-handler.ts
|
|
2421
|
-
|
|
2435
|
+
function isRpcResponseEvent(event) {
|
|
2436
|
+
return "id" in event && ("result" in event || "error" in event);
|
|
2437
|
+
}
|
|
2422
2438
|
function createNextMcpHandler(options = {}) {
|
|
2423
2439
|
const {
|
|
2424
2440
|
getIdentity = (request) => new URL(request.url).searchParams.get("identity"),
|
|
@@ -2431,72 +2447,29 @@ function createNextMcpHandler(options = {}) {
|
|
|
2431
2447
|
clientDefaults,
|
|
2432
2448
|
getClientMetadata
|
|
2433
2449
|
} = options;
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
const stream = new TransformStream();
|
|
2445
|
-
const writer = stream.writable.getWriter();
|
|
2446
|
-
const encoder = new TextEncoder();
|
|
2447
|
-
const sendSSE = (event, data) => {
|
|
2448
|
-
const message = `event: ${event}
|
|
2449
|
-
data: ${JSON.stringify(data)}
|
|
2450
|
-
|
|
2451
|
-
`;
|
|
2452
|
-
writer.write(encoder.encode(message)).catch(() => {
|
|
2453
|
-
});
|
|
2454
|
-
};
|
|
2455
|
-
const previousManager = managers.get(identity);
|
|
2456
|
-
if (previousManager) {
|
|
2457
|
-
previousManager.dispose();
|
|
2458
|
-
}
|
|
2459
|
-
const resolvedClientMetadata = getClientMetadata ? await getClientMetadata(request) : clientDefaults;
|
|
2460
|
-
const manager = new SSEConnectionManager(
|
|
2450
|
+
const toManagerOptions = (identity, resolvedClientMetadata) => ({
|
|
2451
|
+
identity,
|
|
2452
|
+
heartbeatInterval,
|
|
2453
|
+
clientDefaults: resolvedClientMetadata
|
|
2454
|
+
});
|
|
2455
|
+
async function resolveClientMetadata(request) {
|
|
2456
|
+
return getClientMetadata ? await getClientMetadata(request) : clientDefaults;
|
|
2457
|
+
}
|
|
2458
|
+
async function GET() {
|
|
2459
|
+
return Response.json(
|
|
2461
2460
|
{
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
// Pass resolved metadata
|
|
2466
|
-
},
|
|
2467
|
-
(event) => {
|
|
2468
|
-
if ("id" in event) {
|
|
2469
|
-
sendSSE("rpc-response", event);
|
|
2470
|
-
} else if ("type" in event && "sessionId" in event) {
|
|
2471
|
-
sendSSE("connection", event);
|
|
2472
|
-
} else {
|
|
2473
|
-
sendSSE("observability", event);
|
|
2461
|
+
error: {
|
|
2462
|
+
code: "METHOD_NOT_ALLOWED",
|
|
2463
|
+
message: "Use POST /api/mcp. For streaming use Accept: text/event-stream."
|
|
2474
2464
|
}
|
|
2475
|
-
}
|
|
2465
|
+
},
|
|
2466
|
+
{ status: 405 }
|
|
2476
2467
|
);
|
|
2477
|
-
managers.set(identity, manager);
|
|
2478
|
-
sendSSE("connected", { timestamp: Date.now() });
|
|
2479
|
-
const abortController = new AbortController();
|
|
2480
|
-
request.signal?.addEventListener("abort", () => {
|
|
2481
|
-
manager.dispose();
|
|
2482
|
-
managers.delete(identity);
|
|
2483
|
-
writer.close().catch(() => {
|
|
2484
|
-
});
|
|
2485
|
-
abortController.abort();
|
|
2486
|
-
});
|
|
2487
|
-
return new Response(stream.readable, {
|
|
2488
|
-
status: 200,
|
|
2489
|
-
headers: {
|
|
2490
|
-
"Content-Type": "text/event-stream",
|
|
2491
|
-
"Cache-Control": "no-cache, no-transform",
|
|
2492
|
-
"Connection": "keep-alive",
|
|
2493
|
-
"X-Accel-Buffering": "no"
|
|
2494
|
-
}
|
|
2495
|
-
});
|
|
2496
2468
|
}
|
|
2497
2469
|
async function POST(request) {
|
|
2498
2470
|
const identity = getIdentity(request);
|
|
2499
2471
|
const authToken = getAuthToken(request);
|
|
2472
|
+
const acceptsEventStream = (request.headers.get("accept") || "").toLowerCase().includes("text/event-stream");
|
|
2500
2473
|
if (!identity) {
|
|
2501
2474
|
return Response.json({ error: { code: "MISSING_IDENTITY", message: "Missing identity" } }, { status: 400 });
|
|
2502
2475
|
}
|
|
@@ -2504,28 +2477,103 @@ data: ${JSON.stringify(data)}
|
|
|
2504
2477
|
if (!isAuthorized) {
|
|
2505
2478
|
return Response.json({ error: { code: "UNAUTHORIZED", message: "Unauthorized" } }, { status: 401 });
|
|
2506
2479
|
}
|
|
2480
|
+
let rawBody = "";
|
|
2507
2481
|
try {
|
|
2508
|
-
|
|
2509
|
-
const
|
|
2510
|
-
if (!
|
|
2482
|
+
rawBody = await request.text();
|
|
2483
|
+
const body = rawBody ? JSON.parse(rawBody) : null;
|
|
2484
|
+
if (!body || typeof body !== "object") {
|
|
2511
2485
|
return Response.json(
|
|
2512
2486
|
{
|
|
2513
2487
|
error: {
|
|
2514
|
-
code: "
|
|
2515
|
-
message: "
|
|
2488
|
+
code: "INVALID_REQUEST",
|
|
2489
|
+
message: "Invalid JSON-RPC request body"
|
|
2516
2490
|
}
|
|
2517
2491
|
},
|
|
2518
2492
|
{ status: 400 }
|
|
2519
2493
|
);
|
|
2520
2494
|
}
|
|
2521
|
-
const
|
|
2522
|
-
|
|
2495
|
+
const resolvedClientMetadata = await resolveClientMetadata(request);
|
|
2496
|
+
if (!acceptsEventStream) {
|
|
2497
|
+
const manager2 = new SSEConnectionManager(
|
|
2498
|
+
toManagerOptions(identity, resolvedClientMetadata),
|
|
2499
|
+
() => {
|
|
2500
|
+
}
|
|
2501
|
+
);
|
|
2502
|
+
try {
|
|
2503
|
+
const response = await manager2.handleRequest(body);
|
|
2504
|
+
return Response.json(response);
|
|
2505
|
+
} finally {
|
|
2506
|
+
manager2.dispose();
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
const stream = new TransformStream();
|
|
2510
|
+
const writer = stream.writable.getWriter();
|
|
2511
|
+
const encoder = new TextEncoder();
|
|
2512
|
+
let streamWritable = true;
|
|
2513
|
+
const sendSSE = (event, data) => {
|
|
2514
|
+
if (!streamWritable) return;
|
|
2515
|
+
const message = `event: ${event}
|
|
2516
|
+
data: ${JSON.stringify(data)}
|
|
2517
|
+
|
|
2518
|
+
`;
|
|
2519
|
+
writer.write(encoder.encode(message)).catch(() => {
|
|
2520
|
+
streamWritable = false;
|
|
2521
|
+
});
|
|
2522
|
+
};
|
|
2523
|
+
const manager = new SSEConnectionManager(
|
|
2524
|
+
toManagerOptions(identity, resolvedClientMetadata),
|
|
2525
|
+
(event) => {
|
|
2526
|
+
if (isRpcResponseEvent(event)) {
|
|
2527
|
+
sendSSE("rpc-response", event);
|
|
2528
|
+
} else if ("type" in event && "sessionId" in event) {
|
|
2529
|
+
sendSSE("connection", event);
|
|
2530
|
+
} else {
|
|
2531
|
+
sendSSE("observability", event);
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
);
|
|
2535
|
+
sendSSE("connected", { timestamp: Date.now() });
|
|
2536
|
+
void (async () => {
|
|
2537
|
+
try {
|
|
2538
|
+
await manager.handleRequest(body);
|
|
2539
|
+
} catch (error) {
|
|
2540
|
+
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
2541
|
+
sendSSE("rpc-response", {
|
|
2542
|
+
id: body.id || "unknown",
|
|
2543
|
+
error: {
|
|
2544
|
+
code: "EXECUTION_ERROR",
|
|
2545
|
+
message: err.message
|
|
2546
|
+
}
|
|
2547
|
+
});
|
|
2548
|
+
} finally {
|
|
2549
|
+
streamWritable = false;
|
|
2550
|
+
manager.dispose();
|
|
2551
|
+
writer.close().catch(() => {
|
|
2552
|
+
});
|
|
2553
|
+
}
|
|
2554
|
+
})();
|
|
2555
|
+
return new Response(stream.readable, {
|
|
2556
|
+
status: 200,
|
|
2557
|
+
headers: {
|
|
2558
|
+
"Content-Type": "text/event-stream",
|
|
2559
|
+
"Cache-Control": "no-cache, no-transform",
|
|
2560
|
+
"Connection": "keep-alive",
|
|
2561
|
+
"X-Accel-Buffering": "no"
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2523
2564
|
} catch (error) {
|
|
2565
|
+
const err = error instanceof Error ? error : new Error("Unknown error");
|
|
2566
|
+
console.error("[MCP Next Handler] Failed to handle RPC", {
|
|
2567
|
+
identity,
|
|
2568
|
+
message: err.message,
|
|
2569
|
+
stack: err.stack,
|
|
2570
|
+
rawBody: rawBody.slice(0, 500)
|
|
2571
|
+
});
|
|
2524
2572
|
return Response.json(
|
|
2525
2573
|
{
|
|
2526
2574
|
error: {
|
|
2527
2575
|
code: "EXECUTION_ERROR",
|
|
2528
|
-
message:
|
|
2576
|
+
message: err.message
|
|
2529
2577
|
}
|
|
2530
2578
|
},
|
|
2531
2579
|
{ status: 500 }
|