@mcp-ts/sdk 2.4.3 → 2.4.5

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 (56) hide show
  1. package/dist/adapters/agui-adapter.d.mts +3 -3
  2. package/dist/adapters/agui-adapter.d.ts +3 -3
  3. package/dist/adapters/agui-middleware.d.mts +3 -3
  4. package/dist/adapters/agui-middleware.d.ts +3 -3
  5. package/dist/adapters/ai-adapter.d.mts +3 -3
  6. package/dist/adapters/ai-adapter.d.ts +3 -3
  7. package/dist/adapters/langchain-adapter.d.mts +3 -3
  8. package/dist/adapters/langchain-adapter.d.ts +3 -3
  9. package/dist/adapters/mastra-adapter.d.mts +2 -2
  10. package/dist/adapters/mastra-adapter.d.ts +2 -2
  11. package/dist/client/index.d.mts +2 -2
  12. package/dist/client/index.d.ts +2 -2
  13. package/dist/client/react.d.mts +4 -5
  14. package/dist/client/react.d.ts +4 -5
  15. package/dist/client/react.js +2 -6
  16. package/dist/client/react.js.map +1 -1
  17. package/dist/client/react.mjs +2 -6
  18. package/dist/client/react.mjs.map +1 -1
  19. package/dist/client/vue.d.mts +4 -5
  20. package/dist/client/vue.d.ts +4 -5
  21. package/dist/client/vue.js.map +1 -1
  22. package/dist/client/vue.mjs.map +1 -1
  23. package/dist/{index-B8kJSrBJ.d.ts → index-CZk2gu2E.d.ts} +1 -1
  24. package/dist/{index-DiJsm_lK.d.mts → index-CkM3p0eE.d.mts} +1 -1
  25. package/dist/index.d.mts +4 -4
  26. package/dist/index.d.ts +4 -4
  27. package/dist/index.js +96 -104
  28. package/dist/index.js.map +1 -1
  29. package/dist/index.mjs +96 -104
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{multi-session-client-DOBvtaQV.d.ts → multi-session-client-ChQrBZhF.d.mts} +4 -5
  32. package/dist/{multi-session-client-B6hsYO8V.d.mts → multi-session-client-QOOPdEVp.d.ts} +4 -5
  33. package/dist/server/index.d.mts +4 -4
  34. package/dist/server/index.d.ts +4 -4
  35. package/dist/server/index.js +96 -104
  36. package/dist/server/index.js.map +1 -1
  37. package/dist/server/index.mjs +96 -104
  38. package/dist/server/index.mjs.map +1 -1
  39. package/dist/shared/index.d.mts +4 -4
  40. package/dist/shared/index.d.ts +4 -4
  41. package/dist/shared/index.js +2 -6
  42. package/dist/shared/index.js.map +1 -1
  43. package/dist/shared/index.mjs +2 -6
  44. package/dist/shared/index.mjs.map +1 -1
  45. package/dist/{tool-router-CbG4Tum6.d.mts → tool-router-CGs3IDOJ.d.mts} +1 -1
  46. package/dist/{tool-router-ChIhPwgP.d.ts → tool-router-DQ-HrD7W.d.ts} +1 -1
  47. package/dist/{types-CjczQwNX.d.mts → types-Bf-7GOLW.d.mts} +0 -2
  48. package/dist/{types-CjczQwNX.d.ts → types-Bf-7GOLW.d.ts} +0 -2
  49. package/package.json +1 -1
  50. package/src/client/react/use-mcp.ts +0 -1
  51. package/src/client/vue/use-mcp.ts +0 -1
  52. package/src/server/handlers/sse-handler.ts +2 -2
  53. package/src/server/mcp/oauth-client.ts +94 -121
  54. package/src/server/storage/index.ts +1 -1
  55. package/src/shared/events.ts +0 -2
  56. package/src/shared/utils.ts +16 -14
@@ -112,13 +112,9 @@ var init_redis = __esm({
112
112
  }
113
113
  });
114
114
  var OAUTH_STATE_SEPARATOR = ".";
115
- var firstChar = customAlphabet(
116
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
117
- 1
118
- );
119
- var rest = customAlphabet(
120
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
121
- 11
115
+ var serverIdAlphabet = customAlphabet(
116
+ "abcdefghijklmnopqrstuvwxyz0123456789",
117
+ 12
122
118
  );
123
119
  function sanitizeServerLabel(name) {
124
120
  let sanitized = name.replace(/[^a-zA-Z0-9-_]/g, "_").replace(/_{2,}/g, "_").toLowerCase();
@@ -128,7 +124,10 @@ function sanitizeServerLabel(name) {
128
124
  return sanitized;
129
125
  }
130
126
  function generateSessionId() {
131
- return firstChar() + rest();
127
+ return "sess_" + nanoid(21);
128
+ }
129
+ function generateServerId() {
130
+ return serverIdAlphabet();
132
131
  }
133
132
  function formatOAuthState(nonce, sessionId) {
134
133
  return `${nonce}${OAUTH_STATE_SEPARATOR}${sessionId}`;
@@ -2079,7 +2078,7 @@ var MCPClient = class {
2079
2078
  * @param options - Client configuration options
2080
2079
  */
2081
2080
  constructor(options) {
2082
- __publicField(this, "client", null);
2081
+ __publicField(this, "client");
2083
2082
  __publicField(this, "oauthProvider", null);
2084
2083
  __publicField(this, "transport", null);
2085
2084
  __publicField(this, "userId");
@@ -2120,6 +2119,21 @@ var MCPClient = class {
2120
2119
  this.clientUri = options.clientUri;
2121
2120
  this.logoUri = options.logoUri;
2122
2121
  this.policyUri = options.policyUri;
2122
+ this.client = new Client(
2123
+ {
2124
+ name: MCP_CLIENT_NAME,
2125
+ version: MCP_CLIENT_VERSION
2126
+ },
2127
+ {
2128
+ capabilities: {
2129
+ extensions: {
2130
+ "io.modelcontextprotocol/ui": {
2131
+ mimeTypes: ["text/html+mcp"]
2132
+ }
2133
+ }
2134
+ }
2135
+ }
2136
+ );
2123
2137
  }
2124
2138
  /**
2125
2139
  * Emit a connection state change event
@@ -2245,13 +2259,12 @@ var MCPClient = class {
2245
2259
  }
2246
2260
  }
2247
2261
  /**
2248
- * Initializes client components (client, transport, OAuth provider)
2249
- * Loads missing configuration from Redis session store if needed
2250
- * This method is idempotent and safe to call multiple times
2262
+ * Ensures session metadata and OAuth provider are loaded.
2263
+ * Does NOT create the SDK Client callers that need one create it themselves.
2251
2264
  * @private
2252
2265
  */
2253
- async initialize() {
2254
- if (this.client && this.oauthProvider) {
2266
+ async ensureSession() {
2267
+ if (this.oauthProvider) {
2255
2268
  return;
2256
2269
  }
2257
2270
  this.emitStateChange("INITIALIZING");
@@ -2294,30 +2307,21 @@ var MCPClient = class {
2294
2307
  }
2295
2308
  });
2296
2309
  }
2297
- if (!this.client) {
2298
- this.client = new Client(
2299
- {
2300
- name: MCP_CLIENT_NAME,
2301
- version: MCP_CLIENT_VERSION
2302
- },
2303
- {
2304
- capabilities: {
2305
- extensions: {
2306
- "io.modelcontextprotocol/ui": {
2307
- mimeTypes: ["text/html+mcp"]
2308
- }
2309
- }
2310
- }
2311
- }
2312
- );
2313
- }
2314
2310
  if (existingSession === null) {
2315
2311
  existingSession = await sessions.get(this.userId, this.sessionId);
2316
2312
  }
2317
2313
  if (!existingSession && this.serverId && this.serverUrl && this.callbackUrl) {
2318
2314
  this.createdAt = Date.now();
2319
2315
  const updatedAt = this.createdAt;
2320
- console.log(`[MCPClient] Creating pending session ${this.sessionId} for connection setup`);
2316
+ this._onObservabilityEvent.fire({
2317
+ type: "mcp:client:session_created",
2318
+ level: "info",
2319
+ message: `Creating pending session ${this.sessionId} for connection setup`,
2320
+ sessionId: this.sessionId,
2321
+ serverId: this.serverId,
2322
+ timestamp: Date.now(),
2323
+ id: nanoid()
2324
+ });
2321
2325
  await sessions.create({
2322
2326
  sessionId: this.sessionId,
2323
2327
  userId: this.userId,
@@ -2427,17 +2431,16 @@ var MCPClient = class {
2427
2431
  * @throws {Error} When connection fails for other reasons
2428
2432
  */
2429
2433
  async connect() {
2430
- if (this.client?.transport) {
2434
+ if (this.client.transport) {
2431
2435
  this.transport = null;
2432
2436
  try {
2433
2437
  await this.client.close();
2434
2438
  } catch {
2435
2439
  }
2436
- this.client = null;
2437
2440
  }
2438
- await this.initialize();
2439
- if (!this.client || !this.oauthProvider) {
2440
- const error = "Client or OAuth provider not initialized";
2441
+ await this.ensureSession();
2442
+ if (!this.oauthProvider) {
2443
+ const error = "OAuth provider not initialized";
2441
2444
  this.emitError(error, "connection");
2442
2445
  this.emitStateChange("FAILED");
2443
2446
  throw new Error(error);
@@ -2448,7 +2451,15 @@ var MCPClient = class {
2448
2451
  this.transportType = transportType;
2449
2452
  this.emitStateChange("CONNECTED");
2450
2453
  this.emitProgress("Connected successfully");
2451
- console.log(`[MCPClient] Saving active session ${this.sessionId} (connect success)`);
2454
+ this._onObservabilityEvent.fire({
2455
+ type: "mcp:client:session_saved",
2456
+ level: "info",
2457
+ message: `Saving active session ${this.sessionId} (connect success)`,
2458
+ sessionId: this.sessionId,
2459
+ serverId: this.serverId,
2460
+ timestamp: Date.now(),
2461
+ id: nanoid()
2462
+ });
2452
2463
  await this.saveSession("active");
2453
2464
  } catch (error) {
2454
2465
  if (error instanceof UnauthorizedError$1 || error instanceof Error && error.message.toLowerCase().includes("unauthorized")) {
@@ -2465,7 +2476,15 @@ var MCPClient = class {
2465
2476
  throw new Error(message);
2466
2477
  }
2467
2478
  this.emitStateChange("AUTHENTICATING");
2468
- console.log(`[MCPClient] Saving pending OAuth session ${this.sessionId}`);
2479
+ this._onObservabilityEvent.fire({
2480
+ type: "mcp:client:session_saved",
2481
+ level: "info",
2482
+ message: `Saving pending OAuth session ${this.sessionId}`,
2483
+ sessionId: this.sessionId,
2484
+ serverId: this.serverId,
2485
+ timestamp: Date.now(),
2486
+ id: nanoid()
2487
+ });
2469
2488
  await this.saveSession("pending");
2470
2489
  if (this.serverId) {
2471
2490
  this._onConnectionEvent.fire({
@@ -2504,7 +2523,7 @@ var MCPClient = class {
2504
2523
  async finishAuth(authCode, state) {
2505
2524
  this.emitStateChange("AUTHENTICATING");
2506
2525
  this.emitProgress("Exchanging authorization code for tokens...");
2507
- await this.initialize();
2526
+ await this.ensureSession();
2508
2527
  if (!this.oauthProvider) {
2509
2528
  const error = "OAuth provider not initialized";
2510
2529
  this.emitError(error, "auth");
@@ -2540,27 +2559,25 @@ var MCPClient = class {
2540
2559
  this.emitStateChange("AUTHENTICATED");
2541
2560
  authenticatedStateEmitted = true;
2542
2561
  }
2543
- this.emitProgress("Creating authenticated client...");
2544
- this.client = new Client(
2545
- {
2546
- name: MCP_CLIENT_NAME,
2547
- version: MCP_CLIENT_VERSION
2548
- },
2549
- {
2550
- capabilities: {
2551
- extensions: {
2552
- "io.modelcontextprotocol/ui": {
2553
- mimeTypes: ["text/html+mcp"]
2554
- }
2555
- }
2556
- }
2557
- }
2558
- );
2559
2562
  this.emitStateChange("CONNECTING");
2563
+ if (this.client.transport) {
2564
+ try {
2565
+ await this.client.close();
2566
+ } catch {
2567
+ }
2568
+ }
2560
2569
  await this.client.connect(this.transport);
2561
2570
  this.transportType = currentType;
2562
2571
  this.emitStateChange("CONNECTED");
2563
- console.log(`[MCPClient] Saving active session ${this.sessionId} (OAuth complete)`);
2572
+ this._onObservabilityEvent.fire({
2573
+ type: "mcp:client:session_saved",
2574
+ level: "info",
2575
+ message: `Saving active session ${this.sessionId} (OAuth complete)`,
2576
+ sessionId: this.sessionId,
2577
+ serverId: this.serverId,
2578
+ timestamp: Date.now(),
2579
+ id: nanoid()
2580
+ });
2564
2581
  await this.saveSession("active");
2565
2582
  return;
2566
2583
  } catch (error) {
@@ -2601,9 +2618,6 @@ var MCPClient = class {
2601
2618
  * @throws {Error} When client is not connected
2602
2619
  */
2603
2620
  async listTools() {
2604
- if (!this.client) {
2605
- throw new Error("Not connected to server");
2606
- }
2607
2621
  this.emitStateChange("DISCOVERING");
2608
2622
  try {
2609
2623
  const request = {
@@ -2641,9 +2655,6 @@ var MCPClient = class {
2641
2655
  * @throws {Error} When client is not connected
2642
2656
  */
2643
2657
  async callTool(toolName, toolArgs) {
2644
- if (!this.client) {
2645
- throw new Error("Not connected to server");
2646
- }
2647
2658
  const request = {
2648
2659
  method: "tools/call",
2649
2660
  params: {
@@ -2697,9 +2708,6 @@ var MCPClient = class {
2697
2708
  * @throws {Error} When client is not connected
2698
2709
  */
2699
2710
  async listPrompts() {
2700
- if (!this.client) {
2701
- throw new Error("Not connected to server");
2702
- }
2703
2711
  this.emitStateChange("DISCOVERING");
2704
2712
  try {
2705
2713
  const request = {
@@ -2727,9 +2735,6 @@ var MCPClient = class {
2727
2735
  * @throws {Error} When client is not connected
2728
2736
  */
2729
2737
  async getPrompt(name, args) {
2730
- if (!this.client) {
2731
- throw new Error("Not connected to server");
2732
- }
2733
2738
  const request = {
2734
2739
  method: "prompts/get",
2735
2740
  params: {
@@ -2747,9 +2752,6 @@ var MCPClient = class {
2747
2752
  * @throws {Error} When client is not connected
2748
2753
  */
2749
2754
  async listResources() {
2750
- if (!this.client) {
2751
- throw new Error("Not connected to server");
2752
- }
2753
2755
  this.emitStateChange("DISCOVERING");
2754
2756
  try {
2755
2757
  const request = {
@@ -2776,9 +2778,6 @@ var MCPClient = class {
2776
2778
  * @throws {Error} When client is not connected
2777
2779
  */
2778
2780
  async readResource(uri) {
2779
- if (!this.client) {
2780
- throw new Error("Not connected to server");
2781
- }
2782
2781
  const request = {
2783
2782
  method: "resources/read",
2784
2783
  params: {
@@ -2804,13 +2803,12 @@ var MCPClient = class {
2804
2803
  return await fn();
2805
2804
  } catch (error) {
2806
2805
  if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
2807
- if (this.client) {
2806
+ if (this.client.transport) {
2808
2807
  try {
2809
2808
  await this.client.close();
2810
2809
  } catch {
2811
2810
  }
2812
2811
  this.transport = null;
2813
- this.client = null;
2814
2812
  }
2815
2813
  await this.reconnect();
2816
2814
  return await fn();
@@ -2823,26 +2821,9 @@ var MCPClient = class {
2823
2821
  * @throws {Error} When OAuth provider is not initialized
2824
2822
  */
2825
2823
  async reconnect() {
2826
- await this.initialize();
2827
- if (!this.oauthProvider) {
2828
- throw new Error("OAuth provider not initialized");
2829
- }
2830
- if (this.client) {
2831
- try {
2832
- await this.client.close();
2833
- } catch {
2834
- }
2835
- }
2836
- this.client = new Client(
2837
- {
2838
- name: MCP_CLIENT_NAME,
2839
- version: MCP_CLIENT_VERSION
2840
- },
2841
- { capabilities: {} }
2842
- );
2843
- const tt = this.transportType || "streamable-http";
2844
- this.transport = this.getTransport(tt);
2845
- await this.client.connect(this.transport);
2824
+ await this.ensureSession();
2825
+ if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
2826
+ await this.connect();
2846
2827
  }
2847
2828
  /**
2848
2829
  * Completely removes the session from Redis including all OAuth data
@@ -2850,9 +2831,18 @@ var MCPClient = class {
2850
2831
  */
2851
2832
  async clearSession() {
2852
2833
  try {
2853
- await this.initialize();
2834
+ await this.ensureSession();
2854
2835
  } catch (error) {
2855
- console.warn("[MCPClient] Initialization failed during clearSession:", error);
2836
+ this._onObservabilityEvent.fire({
2837
+ type: "mcp:client:error",
2838
+ level: "warn",
2839
+ message: "Initialization failed during clearSession",
2840
+ sessionId: this.sessionId,
2841
+ serverId: this.serverId,
2842
+ payload: { error: String(error) },
2843
+ timestamp: Date.now(),
2844
+ id: nanoid()
2845
+ });
2856
2846
  }
2857
2847
  if (this.oauthProvider) {
2858
2848
  await this.oauthProvider.invalidateCredentials("all");
@@ -2865,7 +2855,7 @@ var MCPClient = class {
2865
2855
  * @returns True if connected, false otherwise
2866
2856
  */
2867
2857
  isConnected() {
2868
- return this.client !== null;
2858
+ return this.client.transport !== void 0;
2869
2859
  }
2870
2860
  /**
2871
2861
  * Disconnects from the MCP server and cleans up resources.
@@ -2883,10 +2873,12 @@ var MCPClient = class {
2883
2873
  } catch {
2884
2874
  }
2885
2875
  }
2886
- if (this.client) {
2887
- this.client.close();
2876
+ if (this.client.transport) {
2877
+ try {
2878
+ await this.client.close();
2879
+ } catch {
2880
+ }
2888
2881
  }
2889
- this.client = null;
2890
2882
  this.oauthProvider = null;
2891
2883
  this.transport = null;
2892
2884
  if (this.serverId) {
@@ -3327,7 +3319,7 @@ var SSEConnectionManager = class {
3327
3319
  async connect(params) {
3328
3320
  const { serverName, serverUrl, callbackUrl, transportType } = params;
3329
3321
  const headers = normalizeHeaders(params.headers);
3330
- const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await sessions.generateSessionId();
3322
+ const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : generateServerId();
3331
3323
  const existingSessions = await sessions.list(this.userId);
3332
3324
  const duplicate = existingSessions.find(
3333
3325
  (s) => s.serverId === serverId || s.serverUrl === serverUrl