@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.mjs CHANGED
@@ -113,13 +113,9 @@ var init_redis = __esm({
113
113
  }
114
114
  });
115
115
  var OAUTH_STATE_SEPARATOR = ".";
116
- var firstChar = customAlphabet(
117
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
118
- 1
119
- );
120
- var rest = customAlphabet(
121
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
122
- 11
116
+ var serverIdAlphabet = customAlphabet(
117
+ "abcdefghijklmnopqrstuvwxyz0123456789",
118
+ 12
123
119
  );
124
120
  function sanitizeServerLabel(name) {
125
121
  let sanitized = name.replace(/[^a-zA-Z0-9-_]/g, "_").replace(/_{2,}/g, "_").toLowerCase();
@@ -129,7 +125,10 @@ function sanitizeServerLabel(name) {
129
125
  return sanitized;
130
126
  }
131
127
  function generateSessionId() {
132
- return firstChar() + rest();
128
+ return "sess_" + nanoid(21);
129
+ }
130
+ function generateServerId() {
131
+ return serverIdAlphabet();
133
132
  }
134
133
  function formatOAuthState(nonce, sessionId) {
135
134
  return `${nonce}${OAUTH_STATE_SEPARATOR}${sessionId}`;
@@ -2151,7 +2150,7 @@ var MCPClient = class {
2151
2150
  * @param options - Client configuration options
2152
2151
  */
2153
2152
  constructor(options) {
2154
- __publicField(this, "client", null);
2153
+ __publicField(this, "client");
2155
2154
  __publicField(this, "oauthProvider", null);
2156
2155
  __publicField(this, "transport", null);
2157
2156
  __publicField(this, "userId");
@@ -2192,6 +2191,21 @@ var MCPClient = class {
2192
2191
  this.clientUri = options.clientUri;
2193
2192
  this.logoUri = options.logoUri;
2194
2193
  this.policyUri = options.policyUri;
2194
+ this.client = new Client(
2195
+ {
2196
+ name: MCP_CLIENT_NAME,
2197
+ version: MCP_CLIENT_VERSION
2198
+ },
2199
+ {
2200
+ capabilities: {
2201
+ extensions: {
2202
+ "io.modelcontextprotocol/ui": {
2203
+ mimeTypes: ["text/html+mcp"]
2204
+ }
2205
+ }
2206
+ }
2207
+ }
2208
+ );
2195
2209
  }
2196
2210
  /**
2197
2211
  * Emit a connection state change event
@@ -2317,13 +2331,12 @@ var MCPClient = class {
2317
2331
  }
2318
2332
  }
2319
2333
  /**
2320
- * Initializes client components (client, transport, OAuth provider)
2321
- * Loads missing configuration from Redis session store if needed
2322
- * This method is idempotent and safe to call multiple times
2334
+ * Ensures session metadata and OAuth provider are loaded.
2335
+ * Does NOT create the SDK Client callers that need one create it themselves.
2323
2336
  * @private
2324
2337
  */
2325
- async initialize() {
2326
- if (this.client && this.oauthProvider) {
2338
+ async ensureSession() {
2339
+ if (this.oauthProvider) {
2327
2340
  return;
2328
2341
  }
2329
2342
  this.emitStateChange("INITIALIZING");
@@ -2366,30 +2379,21 @@ var MCPClient = class {
2366
2379
  }
2367
2380
  });
2368
2381
  }
2369
- if (!this.client) {
2370
- this.client = new Client(
2371
- {
2372
- name: MCP_CLIENT_NAME,
2373
- version: MCP_CLIENT_VERSION
2374
- },
2375
- {
2376
- capabilities: {
2377
- extensions: {
2378
- "io.modelcontextprotocol/ui": {
2379
- mimeTypes: ["text/html+mcp"]
2380
- }
2381
- }
2382
- }
2383
- }
2384
- );
2385
- }
2386
2382
  if (existingSession === null) {
2387
2383
  existingSession = await sessions.get(this.userId, this.sessionId);
2388
2384
  }
2389
2385
  if (!existingSession && this.serverId && this.serverUrl && this.callbackUrl) {
2390
2386
  this.createdAt = Date.now();
2391
2387
  const updatedAt = this.createdAt;
2392
- console.log(`[MCPClient] Creating pending session ${this.sessionId} for connection setup`);
2388
+ this._onObservabilityEvent.fire({
2389
+ type: "mcp:client:session_created",
2390
+ level: "info",
2391
+ message: `Creating pending session ${this.sessionId} for connection setup`,
2392
+ sessionId: this.sessionId,
2393
+ serverId: this.serverId,
2394
+ timestamp: Date.now(),
2395
+ id: nanoid()
2396
+ });
2393
2397
  await sessions.create({
2394
2398
  sessionId: this.sessionId,
2395
2399
  userId: this.userId,
@@ -2499,17 +2503,16 @@ var MCPClient = class {
2499
2503
  * @throws {Error} When connection fails for other reasons
2500
2504
  */
2501
2505
  async connect() {
2502
- if (this.client?.transport) {
2506
+ if (this.client.transport) {
2503
2507
  this.transport = null;
2504
2508
  try {
2505
2509
  await this.client.close();
2506
2510
  } catch {
2507
2511
  }
2508
- this.client = null;
2509
2512
  }
2510
- await this.initialize();
2511
- if (!this.client || !this.oauthProvider) {
2512
- const error = "Client or OAuth provider not initialized";
2513
+ await this.ensureSession();
2514
+ if (!this.oauthProvider) {
2515
+ const error = "OAuth provider not initialized";
2513
2516
  this.emitError(error, "connection");
2514
2517
  this.emitStateChange("FAILED");
2515
2518
  throw new Error(error);
@@ -2520,7 +2523,15 @@ var MCPClient = class {
2520
2523
  this.transportType = transportType;
2521
2524
  this.emitStateChange("CONNECTED");
2522
2525
  this.emitProgress("Connected successfully");
2523
- console.log(`[MCPClient] Saving active session ${this.sessionId} (connect success)`);
2526
+ this._onObservabilityEvent.fire({
2527
+ type: "mcp:client:session_saved",
2528
+ level: "info",
2529
+ message: `Saving active session ${this.sessionId} (connect success)`,
2530
+ sessionId: this.sessionId,
2531
+ serverId: this.serverId,
2532
+ timestamp: Date.now(),
2533
+ id: nanoid()
2534
+ });
2524
2535
  await this.saveSession("active");
2525
2536
  } catch (error) {
2526
2537
  if (error instanceof UnauthorizedError$1 || error instanceof Error && error.message.toLowerCase().includes("unauthorized")) {
@@ -2537,7 +2548,15 @@ var MCPClient = class {
2537
2548
  throw new Error(message);
2538
2549
  }
2539
2550
  this.emitStateChange("AUTHENTICATING");
2540
- console.log(`[MCPClient] Saving pending OAuth session ${this.sessionId}`);
2551
+ this._onObservabilityEvent.fire({
2552
+ type: "mcp:client:session_saved",
2553
+ level: "info",
2554
+ message: `Saving pending OAuth session ${this.sessionId}`,
2555
+ sessionId: this.sessionId,
2556
+ serverId: this.serverId,
2557
+ timestamp: Date.now(),
2558
+ id: nanoid()
2559
+ });
2541
2560
  await this.saveSession("pending");
2542
2561
  if (this.serverId) {
2543
2562
  this._onConnectionEvent.fire({
@@ -2576,7 +2595,7 @@ var MCPClient = class {
2576
2595
  async finishAuth(authCode, state) {
2577
2596
  this.emitStateChange("AUTHENTICATING");
2578
2597
  this.emitProgress("Exchanging authorization code for tokens...");
2579
- await this.initialize();
2598
+ await this.ensureSession();
2580
2599
  if (!this.oauthProvider) {
2581
2600
  const error = "OAuth provider not initialized";
2582
2601
  this.emitError(error, "auth");
@@ -2612,27 +2631,25 @@ var MCPClient = class {
2612
2631
  this.emitStateChange("AUTHENTICATED");
2613
2632
  authenticatedStateEmitted = true;
2614
2633
  }
2615
- this.emitProgress("Creating authenticated client...");
2616
- this.client = new Client(
2617
- {
2618
- name: MCP_CLIENT_NAME,
2619
- version: MCP_CLIENT_VERSION
2620
- },
2621
- {
2622
- capabilities: {
2623
- extensions: {
2624
- "io.modelcontextprotocol/ui": {
2625
- mimeTypes: ["text/html+mcp"]
2626
- }
2627
- }
2628
- }
2629
- }
2630
- );
2631
2634
  this.emitStateChange("CONNECTING");
2635
+ if (this.client.transport) {
2636
+ try {
2637
+ await this.client.close();
2638
+ } catch {
2639
+ }
2640
+ }
2632
2641
  await this.client.connect(this.transport);
2633
2642
  this.transportType = currentType;
2634
2643
  this.emitStateChange("CONNECTED");
2635
- console.log(`[MCPClient] Saving active session ${this.sessionId} (OAuth complete)`);
2644
+ this._onObservabilityEvent.fire({
2645
+ type: "mcp:client:session_saved",
2646
+ level: "info",
2647
+ message: `Saving active session ${this.sessionId} (OAuth complete)`,
2648
+ sessionId: this.sessionId,
2649
+ serverId: this.serverId,
2650
+ timestamp: Date.now(),
2651
+ id: nanoid()
2652
+ });
2636
2653
  await this.saveSession("active");
2637
2654
  return;
2638
2655
  } catch (error) {
@@ -2673,9 +2690,6 @@ var MCPClient = class {
2673
2690
  * @throws {Error} When client is not connected
2674
2691
  */
2675
2692
  async listTools() {
2676
- if (!this.client) {
2677
- throw new Error("Not connected to server");
2678
- }
2679
2693
  this.emitStateChange("DISCOVERING");
2680
2694
  try {
2681
2695
  const request = {
@@ -2713,9 +2727,6 @@ var MCPClient = class {
2713
2727
  * @throws {Error} When client is not connected
2714
2728
  */
2715
2729
  async callTool(toolName, toolArgs) {
2716
- if (!this.client) {
2717
- throw new Error("Not connected to server");
2718
- }
2719
2730
  const request = {
2720
2731
  method: "tools/call",
2721
2732
  params: {
@@ -2769,9 +2780,6 @@ var MCPClient = class {
2769
2780
  * @throws {Error} When client is not connected
2770
2781
  */
2771
2782
  async listPrompts() {
2772
- if (!this.client) {
2773
- throw new Error("Not connected to server");
2774
- }
2775
2783
  this.emitStateChange("DISCOVERING");
2776
2784
  try {
2777
2785
  const request = {
@@ -2799,9 +2807,6 @@ var MCPClient = class {
2799
2807
  * @throws {Error} When client is not connected
2800
2808
  */
2801
2809
  async getPrompt(name, args) {
2802
- if (!this.client) {
2803
- throw new Error("Not connected to server");
2804
- }
2805
2810
  const request = {
2806
2811
  method: "prompts/get",
2807
2812
  params: {
@@ -2819,9 +2824,6 @@ var MCPClient = class {
2819
2824
  * @throws {Error} When client is not connected
2820
2825
  */
2821
2826
  async listResources() {
2822
- if (!this.client) {
2823
- throw new Error("Not connected to server");
2824
- }
2825
2827
  this.emitStateChange("DISCOVERING");
2826
2828
  try {
2827
2829
  const request = {
@@ -2848,9 +2850,6 @@ var MCPClient = class {
2848
2850
  * @throws {Error} When client is not connected
2849
2851
  */
2850
2852
  async readResource(uri) {
2851
- if (!this.client) {
2852
- throw new Error("Not connected to server");
2853
- }
2854
2853
  const request = {
2855
2854
  method: "resources/read",
2856
2855
  params: {
@@ -2876,13 +2875,12 @@ var MCPClient = class {
2876
2875
  return await fn();
2877
2876
  } catch (error) {
2878
2877
  if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
2879
- if (this.client) {
2878
+ if (this.client.transport) {
2880
2879
  try {
2881
2880
  await this.client.close();
2882
2881
  } catch {
2883
2882
  }
2884
2883
  this.transport = null;
2885
- this.client = null;
2886
2884
  }
2887
2885
  await this.reconnect();
2888
2886
  return await fn();
@@ -2895,26 +2893,9 @@ var MCPClient = class {
2895
2893
  * @throws {Error} When OAuth provider is not initialized
2896
2894
  */
2897
2895
  async reconnect() {
2898
- await this.initialize();
2899
- if (!this.oauthProvider) {
2900
- throw new Error("OAuth provider not initialized");
2901
- }
2902
- if (this.client) {
2903
- try {
2904
- await this.client.close();
2905
- } catch {
2906
- }
2907
- }
2908
- this.client = new Client(
2909
- {
2910
- name: MCP_CLIENT_NAME,
2911
- version: MCP_CLIENT_VERSION
2912
- },
2913
- { capabilities: {} }
2914
- );
2915
- const tt = this.transportType || "streamable-http";
2916
- this.transport = this.getTransport(tt);
2917
- await this.client.connect(this.transport);
2896
+ await this.ensureSession();
2897
+ if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
2898
+ await this.connect();
2918
2899
  }
2919
2900
  /**
2920
2901
  * Completely removes the session from Redis including all OAuth data
@@ -2922,9 +2903,18 @@ var MCPClient = class {
2922
2903
  */
2923
2904
  async clearSession() {
2924
2905
  try {
2925
- await this.initialize();
2906
+ await this.ensureSession();
2926
2907
  } catch (error) {
2927
- console.warn("[MCPClient] Initialization failed during clearSession:", error);
2908
+ this._onObservabilityEvent.fire({
2909
+ type: "mcp:client:error",
2910
+ level: "warn",
2911
+ message: "Initialization failed during clearSession",
2912
+ sessionId: this.sessionId,
2913
+ serverId: this.serverId,
2914
+ payload: { error: String(error) },
2915
+ timestamp: Date.now(),
2916
+ id: nanoid()
2917
+ });
2928
2918
  }
2929
2919
  if (this.oauthProvider) {
2930
2920
  await this.oauthProvider.invalidateCredentials("all");
@@ -2937,7 +2927,7 @@ var MCPClient = class {
2937
2927
  * @returns True if connected, false otherwise
2938
2928
  */
2939
2929
  isConnected() {
2940
- return this.client !== null;
2930
+ return this.client.transport !== void 0;
2941
2931
  }
2942
2932
  /**
2943
2933
  * Disconnects from the MCP server and cleans up resources.
@@ -2955,10 +2945,12 @@ var MCPClient = class {
2955
2945
  } catch {
2956
2946
  }
2957
2947
  }
2958
- if (this.client) {
2959
- this.client.close();
2948
+ if (this.client.transport) {
2949
+ try {
2950
+ await this.client.close();
2951
+ } catch {
2952
+ }
2960
2953
  }
2961
- this.client = null;
2962
2954
  this.oauthProvider = null;
2963
2955
  this.transport = null;
2964
2956
  if (this.serverId) {
@@ -3399,7 +3391,7 @@ var SSEConnectionManager = class {
3399
3391
  async connect(params) {
3400
3392
  const { serverName, serverUrl, callbackUrl, transportType } = params;
3401
3393
  const headers = normalizeHeaders(params.headers);
3402
- const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await sessions.generateSessionId();
3394
+ const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : generateServerId();
3403
3395
  const existingSessions = await sessions.list(this.userId);
3404
3396
  const duplicate = existingSessions.find(
3405
3397
  (s) => s.serverId === serverId || s.serverUrl === serverUrl