@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.
Files changed (63) hide show
  1. package/README.md +371 -290
  2. package/dist/adapters/agui-adapter.d.mts +3 -3
  3. package/dist/adapters/agui-adapter.d.ts +3 -3
  4. package/dist/adapters/agui-middleware.d.mts +3 -3
  5. package/dist/adapters/agui-middleware.d.ts +3 -3
  6. package/dist/adapters/ai-adapter.d.mts +3 -3
  7. package/dist/adapters/ai-adapter.d.ts +3 -3
  8. package/dist/adapters/langchain-adapter.d.mts +3 -3
  9. package/dist/adapters/langchain-adapter.d.ts +3 -3
  10. package/dist/adapters/mastra-adapter.d.mts +3 -3
  11. package/dist/adapters/mastra-adapter.d.ts +3 -3
  12. package/dist/client/index.d.mts +10 -66
  13. package/dist/client/index.d.ts +10 -66
  14. package/dist/client/index.js +91 -173
  15. package/dist/client/index.js.map +1 -1
  16. package/dist/client/index.mjs +91 -173
  17. package/dist/client/index.mjs.map +1 -1
  18. package/dist/client/react.d.mts +15 -5
  19. package/dist/client/react.d.ts +15 -5
  20. package/dist/client/react.js +130 -182
  21. package/dist/client/react.js.map +1 -1
  22. package/dist/client/react.mjs +130 -182
  23. package/dist/client/react.mjs.map +1 -1
  24. package/dist/client/vue.d.mts +27 -7
  25. package/dist/client/vue.d.ts +27 -7
  26. package/dist/client/vue.js +131 -182
  27. package/dist/client/vue.js.map +1 -1
  28. package/dist/client/vue.mjs +131 -182
  29. package/dist/client/vue.mjs.map +1 -1
  30. package/dist/{events-BgeztGYZ.d.mts → events-CK3N--3g.d.mts} +2 -0
  31. package/dist/{events-BgeztGYZ.d.ts → events-CK3N--3g.d.ts} +2 -0
  32. package/dist/index.d.mts +3 -3
  33. package/dist/index.d.ts +3 -3
  34. package/dist/index.js +224 -258
  35. package/dist/index.js.map +1 -1
  36. package/dist/index.mjs +224 -258
  37. package/dist/index.mjs.map +1 -1
  38. package/dist/{multi-session-client-CxogNckF.d.mts → multi-session-client-DzjmT7FX.d.mts} +4 -10
  39. package/dist/{multi-session-client-cox_WXUj.d.ts → multi-session-client-FAFpUzZ4.d.ts} +4 -10
  40. package/dist/server/index.d.mts +18 -23
  41. package/dist/server/index.d.ts +18 -23
  42. package/dist/server/index.js +133 -85
  43. package/dist/server/index.js.map +1 -1
  44. package/dist/server/index.mjs +133 -85
  45. package/dist/server/index.mjs.map +1 -1
  46. package/dist/shared/index.d.mts +3 -3
  47. package/dist/shared/index.d.ts +3 -3
  48. package/dist/shared/index.js.map +1 -1
  49. package/dist/shared/index.mjs.map +1 -1
  50. package/dist/{types-CLccx9wW.d.mts → types-CW6lghof.d.mts} +6 -0
  51. package/dist/{types-CLccx9wW.d.ts → types-CW6lghof.d.ts} +6 -0
  52. package/package.json +1 -1
  53. package/src/client/core/sse-client.ts +354 -493
  54. package/src/client/react/index.ts +16 -16
  55. package/src/client/react/use-mcp-apps.tsx +214 -214
  56. package/src/client/react/use-mcp.ts +84 -19
  57. package/src/client/vue/use-mcp.ts +119 -44
  58. package/src/server/handlers/nextjs-handler.ts +207 -217
  59. package/src/server/handlers/sse-handler.ts +14 -0
  60. package/src/server/mcp/oauth-client.ts +48 -46
  61. package/src/server/storage/types.ts +12 -5
  62. package/src/shared/events.ts +2 -0
  63. package/src/shared/types.ts +6 -0
@@ -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: Date.now()
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
- if (!existingSession || existingSession.transportType !== this.transportType) {
1335
- console.log(`[MCPClient] Saving session ${this.sessionId} (new or transport changed)`);
1336
- await this.saveSession(SESSION_TTL_SECONDS);
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
- var managers = /* @__PURE__ */ new Map();
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
- async function GET(request) {
2435
- const identity = getIdentity(request);
2436
- const authToken = getAuthToken(request);
2437
- if (!identity) {
2438
- return new Response("Missing identity", { status: 400 });
2439
- }
2440
- const isAuthorized = await authenticate(identity, authToken);
2441
- if (!isAuthorized) {
2442
- return new Response("Unauthorized", { status: 401 });
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
- identity,
2463
- heartbeatInterval,
2464
- clientDefaults: resolvedClientMetadata
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
- const body = await request.json();
2509
- const manager = managers.get(identity);
2510
- if (!manager) {
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: "NO_CONNECTION",
2515
- message: "No SSE connection found. Please establish SSE connection first."
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 response = await manager.handleRequest(body);
2522
- return Response.json(response);
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: error instanceof Error ? error.message : "Unknown error"
2576
+ message: err.message
2529
2577
  }
2530
2578
  },
2531
2579
  { status: 500 }