@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
package/dist/index.js CHANGED
@@ -163,13 +163,9 @@ init_cjs_shims();
163
163
  // src/shared/utils.ts
164
164
  init_cjs_shims();
165
165
  var OAUTH_STATE_SEPARATOR = ".";
166
- var firstChar = nanoid.customAlphabet(
167
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
168
- 1
169
- );
170
- var rest = nanoid.customAlphabet(
171
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
172
- 11
166
+ var serverIdAlphabet = nanoid.customAlphabet(
167
+ "abcdefghijklmnopqrstuvwxyz0123456789",
168
+ 12
173
169
  );
174
170
  function sanitizeServerLabel(name) {
175
171
  let sanitized = name.replace(/[^a-zA-Z0-9-_]/g, "_").replace(/_{2,}/g, "_").toLowerCase();
@@ -179,7 +175,10 @@ function sanitizeServerLabel(name) {
179
175
  return sanitized;
180
176
  }
181
177
  function generateSessionId() {
182
- return firstChar() + rest();
178
+ return "sess_" + nanoid.nanoid(21);
179
+ }
180
+ function generateServerId() {
181
+ return serverIdAlphabet();
183
182
  }
184
183
  function formatOAuthState(nonce, sessionId) {
185
184
  return `${nonce}${OAUTH_STATE_SEPARATOR}${sessionId}`;
@@ -2224,7 +2223,7 @@ var MCPClient = class {
2224
2223
  * @param options - Client configuration options
2225
2224
  */
2226
2225
  constructor(options) {
2227
- __publicField(this, "client", null);
2226
+ __publicField(this, "client");
2228
2227
  __publicField(this, "oauthProvider", null);
2229
2228
  __publicField(this, "transport", null);
2230
2229
  __publicField(this, "userId");
@@ -2265,6 +2264,21 @@ var MCPClient = class {
2265
2264
  this.clientUri = options.clientUri;
2266
2265
  this.logoUri = options.logoUri;
2267
2266
  this.policyUri = options.policyUri;
2267
+ this.client = new index_js.Client(
2268
+ {
2269
+ name: MCP_CLIENT_NAME,
2270
+ version: MCP_CLIENT_VERSION
2271
+ },
2272
+ {
2273
+ capabilities: {
2274
+ extensions: {
2275
+ "io.modelcontextprotocol/ui": {
2276
+ mimeTypes: ["text/html+mcp"]
2277
+ }
2278
+ }
2279
+ }
2280
+ }
2281
+ );
2268
2282
  }
2269
2283
  /**
2270
2284
  * Emit a connection state change event
@@ -2390,13 +2404,12 @@ var MCPClient = class {
2390
2404
  }
2391
2405
  }
2392
2406
  /**
2393
- * Initializes client components (client, transport, OAuth provider)
2394
- * Loads missing configuration from Redis session store if needed
2395
- * This method is idempotent and safe to call multiple times
2407
+ * Ensures session metadata and OAuth provider are loaded.
2408
+ * Does NOT create the SDK Client callers that need one create it themselves.
2396
2409
  * @private
2397
2410
  */
2398
- async initialize() {
2399
- if (this.client && this.oauthProvider) {
2411
+ async ensureSession() {
2412
+ if (this.oauthProvider) {
2400
2413
  return;
2401
2414
  }
2402
2415
  this.emitStateChange("INITIALIZING");
@@ -2439,30 +2452,21 @@ var MCPClient = class {
2439
2452
  }
2440
2453
  });
2441
2454
  }
2442
- if (!this.client) {
2443
- this.client = new index_js.Client(
2444
- {
2445
- name: MCP_CLIENT_NAME,
2446
- version: MCP_CLIENT_VERSION
2447
- },
2448
- {
2449
- capabilities: {
2450
- extensions: {
2451
- "io.modelcontextprotocol/ui": {
2452
- mimeTypes: ["text/html+mcp"]
2453
- }
2454
- }
2455
- }
2456
- }
2457
- );
2458
- }
2459
2455
  if (existingSession === null) {
2460
2456
  existingSession = await sessions.get(this.userId, this.sessionId);
2461
2457
  }
2462
2458
  if (!existingSession && this.serverId && this.serverUrl && this.callbackUrl) {
2463
2459
  this.createdAt = Date.now();
2464
2460
  const updatedAt = this.createdAt;
2465
- console.log(`[MCPClient] Creating pending session ${this.sessionId} for connection setup`);
2461
+ this._onObservabilityEvent.fire({
2462
+ type: "mcp:client:session_created",
2463
+ level: "info",
2464
+ message: `Creating pending session ${this.sessionId} for connection setup`,
2465
+ sessionId: this.sessionId,
2466
+ serverId: this.serverId,
2467
+ timestamp: Date.now(),
2468
+ id: nanoid.nanoid()
2469
+ });
2466
2470
  await sessions.create({
2467
2471
  sessionId: this.sessionId,
2468
2472
  userId: this.userId,
@@ -2572,17 +2576,16 @@ var MCPClient = class {
2572
2576
  * @throws {Error} When connection fails for other reasons
2573
2577
  */
2574
2578
  async connect() {
2575
- if (this.client?.transport) {
2579
+ if (this.client.transport) {
2576
2580
  this.transport = null;
2577
2581
  try {
2578
2582
  await this.client.close();
2579
2583
  } catch {
2580
2584
  }
2581
- this.client = null;
2582
2585
  }
2583
- await this.initialize();
2584
- if (!this.client || !this.oauthProvider) {
2585
- const error = "Client or OAuth provider not initialized";
2586
+ await this.ensureSession();
2587
+ if (!this.oauthProvider) {
2588
+ const error = "OAuth provider not initialized";
2586
2589
  this.emitError(error, "connection");
2587
2590
  this.emitStateChange("FAILED");
2588
2591
  throw new Error(error);
@@ -2593,7 +2596,15 @@ var MCPClient = class {
2593
2596
  this.transportType = transportType;
2594
2597
  this.emitStateChange("CONNECTED");
2595
2598
  this.emitProgress("Connected successfully");
2596
- console.log(`[MCPClient] Saving active session ${this.sessionId} (connect success)`);
2599
+ this._onObservabilityEvent.fire({
2600
+ type: "mcp:client:session_saved",
2601
+ level: "info",
2602
+ message: `Saving active session ${this.sessionId} (connect success)`,
2603
+ sessionId: this.sessionId,
2604
+ serverId: this.serverId,
2605
+ timestamp: Date.now(),
2606
+ id: nanoid.nanoid()
2607
+ });
2597
2608
  await this.saveSession("active");
2598
2609
  } catch (error) {
2599
2610
  if (error instanceof auth_js.UnauthorizedError || error instanceof Error && error.message.toLowerCase().includes("unauthorized")) {
@@ -2610,7 +2621,15 @@ var MCPClient = class {
2610
2621
  throw new Error(message);
2611
2622
  }
2612
2623
  this.emitStateChange("AUTHENTICATING");
2613
- console.log(`[MCPClient] Saving pending OAuth session ${this.sessionId}`);
2624
+ this._onObservabilityEvent.fire({
2625
+ type: "mcp:client:session_saved",
2626
+ level: "info",
2627
+ message: `Saving pending OAuth session ${this.sessionId}`,
2628
+ sessionId: this.sessionId,
2629
+ serverId: this.serverId,
2630
+ timestamp: Date.now(),
2631
+ id: nanoid.nanoid()
2632
+ });
2614
2633
  await this.saveSession("pending");
2615
2634
  if (this.serverId) {
2616
2635
  this._onConnectionEvent.fire({
@@ -2649,7 +2668,7 @@ var MCPClient = class {
2649
2668
  async finishAuth(authCode, state) {
2650
2669
  this.emitStateChange("AUTHENTICATING");
2651
2670
  this.emitProgress("Exchanging authorization code for tokens...");
2652
- await this.initialize();
2671
+ await this.ensureSession();
2653
2672
  if (!this.oauthProvider) {
2654
2673
  const error = "OAuth provider not initialized";
2655
2674
  this.emitError(error, "auth");
@@ -2685,27 +2704,25 @@ var MCPClient = class {
2685
2704
  this.emitStateChange("AUTHENTICATED");
2686
2705
  authenticatedStateEmitted = true;
2687
2706
  }
2688
- this.emitProgress("Creating authenticated client...");
2689
- this.client = new index_js.Client(
2690
- {
2691
- name: MCP_CLIENT_NAME,
2692
- version: MCP_CLIENT_VERSION
2693
- },
2694
- {
2695
- capabilities: {
2696
- extensions: {
2697
- "io.modelcontextprotocol/ui": {
2698
- mimeTypes: ["text/html+mcp"]
2699
- }
2700
- }
2701
- }
2702
- }
2703
- );
2704
2707
  this.emitStateChange("CONNECTING");
2708
+ if (this.client.transport) {
2709
+ try {
2710
+ await this.client.close();
2711
+ } catch {
2712
+ }
2713
+ }
2705
2714
  await this.client.connect(this.transport);
2706
2715
  this.transportType = currentType;
2707
2716
  this.emitStateChange("CONNECTED");
2708
- console.log(`[MCPClient] Saving active session ${this.sessionId} (OAuth complete)`);
2717
+ this._onObservabilityEvent.fire({
2718
+ type: "mcp:client:session_saved",
2719
+ level: "info",
2720
+ message: `Saving active session ${this.sessionId} (OAuth complete)`,
2721
+ sessionId: this.sessionId,
2722
+ serverId: this.serverId,
2723
+ timestamp: Date.now(),
2724
+ id: nanoid.nanoid()
2725
+ });
2709
2726
  await this.saveSession("active");
2710
2727
  return;
2711
2728
  } catch (error) {
@@ -2746,9 +2763,6 @@ var MCPClient = class {
2746
2763
  * @throws {Error} When client is not connected
2747
2764
  */
2748
2765
  async listTools() {
2749
- if (!this.client) {
2750
- throw new Error("Not connected to server");
2751
- }
2752
2766
  this.emitStateChange("DISCOVERING");
2753
2767
  try {
2754
2768
  const request = {
@@ -2786,9 +2800,6 @@ var MCPClient = class {
2786
2800
  * @throws {Error} When client is not connected
2787
2801
  */
2788
2802
  async callTool(toolName, toolArgs) {
2789
- if (!this.client) {
2790
- throw new Error("Not connected to server");
2791
- }
2792
2803
  const request = {
2793
2804
  method: "tools/call",
2794
2805
  params: {
@@ -2842,9 +2853,6 @@ var MCPClient = class {
2842
2853
  * @throws {Error} When client is not connected
2843
2854
  */
2844
2855
  async listPrompts() {
2845
- if (!this.client) {
2846
- throw new Error("Not connected to server");
2847
- }
2848
2856
  this.emitStateChange("DISCOVERING");
2849
2857
  try {
2850
2858
  const request = {
@@ -2872,9 +2880,6 @@ var MCPClient = class {
2872
2880
  * @throws {Error} When client is not connected
2873
2881
  */
2874
2882
  async getPrompt(name, args) {
2875
- if (!this.client) {
2876
- throw new Error("Not connected to server");
2877
- }
2878
2883
  const request = {
2879
2884
  method: "prompts/get",
2880
2885
  params: {
@@ -2892,9 +2897,6 @@ var MCPClient = class {
2892
2897
  * @throws {Error} When client is not connected
2893
2898
  */
2894
2899
  async listResources() {
2895
- if (!this.client) {
2896
- throw new Error("Not connected to server");
2897
- }
2898
2900
  this.emitStateChange("DISCOVERING");
2899
2901
  try {
2900
2902
  const request = {
@@ -2921,9 +2923,6 @@ var MCPClient = class {
2921
2923
  * @throws {Error} When client is not connected
2922
2924
  */
2923
2925
  async readResource(uri) {
2924
- if (!this.client) {
2925
- throw new Error("Not connected to server");
2926
- }
2927
2926
  const request = {
2928
2927
  method: "resources/read",
2929
2928
  params: {
@@ -2949,13 +2948,12 @@ var MCPClient = class {
2949
2948
  return await fn();
2950
2949
  } catch (error) {
2951
2950
  if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
2952
- if (this.client) {
2951
+ if (this.client.transport) {
2953
2952
  try {
2954
2953
  await this.client.close();
2955
2954
  } catch {
2956
2955
  }
2957
2956
  this.transport = null;
2958
- this.client = null;
2959
2957
  }
2960
2958
  await this.reconnect();
2961
2959
  return await fn();
@@ -2968,26 +2966,9 @@ var MCPClient = class {
2968
2966
  * @throws {Error} When OAuth provider is not initialized
2969
2967
  */
2970
2968
  async reconnect() {
2971
- await this.initialize();
2972
- if (!this.oauthProvider) {
2973
- throw new Error("OAuth provider not initialized");
2974
- }
2975
- if (this.client) {
2976
- try {
2977
- await this.client.close();
2978
- } catch {
2979
- }
2980
- }
2981
- this.client = new index_js.Client(
2982
- {
2983
- name: MCP_CLIENT_NAME,
2984
- version: MCP_CLIENT_VERSION
2985
- },
2986
- { capabilities: {} }
2987
- );
2988
- const tt = this.transportType || "streamable-http";
2989
- this.transport = this.getTransport(tt);
2990
- await this.client.connect(this.transport);
2969
+ await this.ensureSession();
2970
+ if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
2971
+ await this.connect();
2991
2972
  }
2992
2973
  /**
2993
2974
  * Completely removes the session from Redis including all OAuth data
@@ -2995,9 +2976,18 @@ var MCPClient = class {
2995
2976
  */
2996
2977
  async clearSession() {
2997
2978
  try {
2998
- await this.initialize();
2979
+ await this.ensureSession();
2999
2980
  } catch (error) {
3000
- console.warn("[MCPClient] Initialization failed during clearSession:", error);
2981
+ this._onObservabilityEvent.fire({
2982
+ type: "mcp:client:error",
2983
+ level: "warn",
2984
+ message: "Initialization failed during clearSession",
2985
+ sessionId: this.sessionId,
2986
+ serverId: this.serverId,
2987
+ payload: { error: String(error) },
2988
+ timestamp: Date.now(),
2989
+ id: nanoid.nanoid()
2990
+ });
3001
2991
  }
3002
2992
  if (this.oauthProvider) {
3003
2993
  await this.oauthProvider.invalidateCredentials("all");
@@ -3010,7 +3000,7 @@ var MCPClient = class {
3010
3000
  * @returns True if connected, false otherwise
3011
3001
  */
3012
3002
  isConnected() {
3013
- return this.client !== null;
3003
+ return this.client.transport !== void 0;
3014
3004
  }
3015
3005
  /**
3016
3006
  * Disconnects from the MCP server and cleans up resources.
@@ -3028,10 +3018,12 @@ var MCPClient = class {
3028
3018
  } catch {
3029
3019
  }
3030
3020
  }
3031
- if (this.client) {
3032
- this.client.close();
3021
+ if (this.client.transport) {
3022
+ try {
3023
+ await this.client.close();
3024
+ } catch {
3025
+ }
3033
3026
  }
3034
- this.client = null;
3035
3027
  this.oauthProvider = null;
3036
3028
  this.transport = null;
3037
3029
  if (this.serverId) {
@@ -3477,7 +3469,7 @@ var SSEConnectionManager = class {
3477
3469
  async connect(params) {
3478
3470
  const { serverName, serverUrl, callbackUrl, transportType } = params;
3479
3471
  const headers = normalizeHeaders(params.headers);
3480
- const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await sessions.generateSessionId();
3472
+ const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : generateServerId();
3481
3473
  const existingSessions = await sessions.list(this.userId);
3482
3474
  const duplicate = existingSessions.find(
3483
3475
  (s) => s.serverId === serverId || s.serverUrl === serverUrl