@mcp-ts/sdk 2.3.4 → 2.4.1

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 (89) hide show
  1. package/README.md +161 -39
  2. package/dist/adapters/agui-adapter.d.mts +4 -4
  3. package/dist/adapters/agui-adapter.d.ts +4 -4
  4. package/dist/adapters/agui-middleware.d.mts +4 -4
  5. package/dist/adapters/agui-middleware.d.ts +4 -4
  6. package/dist/adapters/ai-adapter.d.mts +4 -4
  7. package/dist/adapters/ai-adapter.d.ts +4 -4
  8. package/dist/adapters/langchain-adapter.d.mts +4 -4
  9. package/dist/adapters/langchain-adapter.d.ts +4 -4
  10. package/dist/adapters/mastra-adapter.d.mts +2 -2
  11. package/dist/adapters/mastra-adapter.d.ts +2 -2
  12. package/dist/client/index.d.mts +3 -3
  13. package/dist/client/index.d.ts +3 -3
  14. package/dist/client/index.js +2 -2
  15. package/dist/client/index.js.map +1 -1
  16. package/dist/client/index.mjs +2 -2
  17. package/dist/client/index.mjs.map +1 -1
  18. package/dist/client/react.d.mts +11 -10
  19. package/dist/client/react.d.ts +11 -10
  20. package/dist/client/react.js +66 -26
  21. package/dist/client/react.js.map +1 -1
  22. package/dist/client/react.mjs +67 -27
  23. package/dist/client/react.mjs.map +1 -1
  24. package/dist/client/vue.d.mts +8 -7
  25. package/dist/client/vue.d.ts +8 -7
  26. package/dist/client/vue.js +27 -17
  27. package/dist/client/vue.js.map +1 -1
  28. package/dist/client/vue.mjs +27 -17
  29. package/dist/client/vue.mjs.map +1 -1
  30. package/dist/{events-CK3N--3g.d.mts → events-C4m7tK1U.d.mts} +0 -1
  31. package/dist/{events-CK3N--3g.d.ts → events-C4m7tK1U.d.ts} +0 -1
  32. package/dist/{index-CmjMd2ac.d.ts → index-Ch7ouNSa.d.ts} +3 -3
  33. package/dist/{index-Cfjsme-a.d.mts → index-L5XoXgsb.d.mts} +3 -3
  34. package/dist/index.d.mts +6 -6
  35. package/dist/index.d.ts +6 -6
  36. package/dist/index.js +799 -326
  37. package/dist/index.js.map +1 -1
  38. package/dist/index.mjs +793 -324
  39. package/dist/index.mjs.map +1 -1
  40. package/dist/{multi-session-client-C_kPHpD5.d.ts → multi-session-client-Bwm-efqg.d.ts} +43 -38
  41. package/dist/{multi-session-client-C7hGqzgM.d.mts → multi-session-client-k-9RvWvi.d.mts} +43 -38
  42. package/dist/server/index.d.mts +48 -20
  43. package/dist/server/index.d.ts +48 -20
  44. package/dist/server/index.js +791 -320
  45. package/dist/server/index.js.map +1 -1
  46. package/dist/server/index.mjs +787 -319
  47. package/dist/server/index.mjs.map +1 -1
  48. package/dist/shared/index.d.mts +10 -9
  49. package/dist/shared/index.d.ts +10 -9
  50. package/dist/shared/index.js +7 -5
  51. package/dist/shared/index.js.map +1 -1
  52. package/dist/shared/index.mjs +5 -4
  53. package/dist/shared/index.mjs.map +1 -1
  54. package/dist/{tool-router-BMzhoNYt.d.ts → tool-router-CZMrOG8J.d.ts} +1 -1
  55. package/dist/{tool-router-BhHsvBfP.d.mts → tool-router-CuApsDiV.d.mts} +1 -1
  56. package/dist/{types-CxFaaZrM.d.mts → types-DCk_IF4L.d.mts} +5 -3
  57. package/dist/{types-CxFaaZrM.d.ts → types-DCk_IF4L.d.ts} +5 -3
  58. package/migrations/neon/20260513010000_install_mcp_sessions.sql +40 -3
  59. package/migrations/neon/20260513020000_add_session_cleanup_cron.sql +4 -4
  60. package/migrations/supabase/20260330195700_install_mcp_sessions.sql +67 -3
  61. package/migrations/supabase/20260421010000_add_session_cleanup_cron.sql +6 -6
  62. package/migrations/v2.3.4/neon/20260513010000_install_mcp_sessions.sql +69 -0
  63. package/migrations/v2.3.4/neon/20260513020000_add_session_cleanup_cron.sql +35 -0
  64. package/migrations/v2.3.4/supabase/20260330195700_install_mcp_sessions.sql +82 -0
  65. package/migrations/v2.3.4/supabase/20260421010000_add_session_cleanup_cron.sql +32 -0
  66. package/package.json +13 -3
  67. package/src/client/core/sse-client.ts +2 -2
  68. package/src/client/react/index.ts +1 -1
  69. package/src/client/react/oauth-popup.tsx +34 -13
  70. package/src/client/react/use-mcp.ts +19 -45
  71. package/src/client/utils/session-state.ts +43 -0
  72. package/src/client/vue/use-mcp.ts +18 -47
  73. package/src/server/handlers/sse-handler.ts +16 -9
  74. package/src/server/mcp/multi-session-client.ts +48 -11
  75. package/src/server/mcp/oauth-client.ts +133 -111
  76. package/src/server/mcp/storage-oauth-provider.ts +79 -50
  77. package/src/server/storage/file-backend.ts +74 -18
  78. package/src/server/storage/index.ts +2 -4
  79. package/src/server/storage/memory-backend.ts +49 -13
  80. package/src/server/storage/neon-backend.ts +201 -68
  81. package/src/server/storage/redis-backend.ts +81 -23
  82. package/src/server/storage/session-lifecycle.ts +78 -0
  83. package/src/server/storage/sqlite-backend.ts +89 -15
  84. package/src/server/storage/supabase-backend.ts +188 -63
  85. package/src/server/storage/types.ts +49 -16
  86. package/src/shared/constants.ts +5 -6
  87. package/src/shared/events.ts +0 -1
  88. package/src/shared/types.ts +5 -3
  89. package/src/shared/utils.ts +26 -0
@@ -1,4 +1,4 @@
1
- import { b as Event, M as McpConnectionEvent, d as McpObservabilityEvent, c as McpConnectionState } from './events-CK3N--3g.js';
1
+ import { b as Event, M as McpConnectionEvent, d as McpObservabilityEvent, c as McpConnectionState } from './events-C4m7tK1U.js';
2
2
  import { ListToolsResult, CallToolResult, ListPromptsResult, GetPromptResult, ListResourcesResult, ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
3
3
  import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
4
4
  import { OAuthClientMetadata, OAuthClientInformationMixed, OAuthClientInformationFull, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
@@ -18,8 +18,6 @@ interface AgentsOAuthProvider extends OAuthClientProvider {
18
18
  }>;
19
19
  consumeState(state: string): Promise<void>;
20
20
  deleteCodeVerifier(): Promise<void>;
21
- isTokenExpired(): boolean;
22
- setTokenExpiresAt(expiresAt: number): void;
23
21
  }
24
22
  interface StorageOAuthClientProviderOptions {
25
23
  userId: string;
@@ -51,7 +49,6 @@ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
51
49
  private _authUrl;
52
50
  private _clientId;
53
51
  private onRedirectCallback?;
54
- private tokenExpiresAt?;
55
52
  /**
56
53
  * Creates a new session-backed OAuth provider
57
54
  * @param options - Provider configuration
@@ -61,17 +58,17 @@ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
61
58
  get clientId(): string | undefined;
62
59
  set clientId(clientId_: string | undefined);
63
60
  /**
64
- * Loads OAuth data from the session store
61
+ * Loads OAuth credentials from the session store
65
62
  * @private
66
63
  */
67
- private getSessionData;
64
+ private getCredentials;
68
65
  /**
69
- * Saves OAuth data to the session store
70
- * @param data - Partial OAuth data to save
66
+ * Saves OAuth credentials to the session store
67
+ * @param data - Partial OAuth credentials to save
71
68
  * @private
72
69
  * @throws Error if session doesn't exist (session must be created by controller layer)
73
70
  */
74
- private saveSessionData;
71
+ private patchCredentials;
75
72
  /**
76
73
  * Retrieves stored OAuth client information
77
74
  */
@@ -86,20 +83,18 @@ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
86
83
  saveTokens(tokens: OAuthTokens): Promise<void>;
87
84
  get authUrl(): string | undefined;
88
85
  state(): Promise<string>;
89
- checkState(_state: string): Promise<{
86
+ checkState(state: string): Promise<{
90
87
  valid: boolean;
91
88
  serverId?: string;
92
89
  error?: string;
93
90
  }>;
94
- consumeState(_state: string): Promise<void>;
91
+ consumeState(state: string): Promise<void>;
95
92
  redirectToAuthorization(authUrl: URL): Promise<void>;
96
93
  invalidateCredentials(scope: "all" | "client" | "tokens" | "verifier"): Promise<void>;
97
94
  saveCodeVerifier(verifier: string): Promise<void>;
98
95
  codeVerifier(): Promise<string>;
99
96
  deleteCodeVerifier(): Promise<void>;
100
97
  tokens(): Promise<OAuthTokens | undefined>;
101
- isTokenExpired(): boolean;
102
- setTokenExpiresAt(expiresAt: number): void;
103
98
  }
104
99
 
105
100
  /**
@@ -198,11 +193,15 @@ declare class MCPClient {
198
193
  /**
199
194
  * Saves current session state to the session store
200
195
  * Creates new session if it doesn't exist, updates if it does
201
- * @param ttl - Time-to-live in seconds (defaults to 12hr for connected sessions)
202
- * @param active - Session status marker used to avoid unnecessary TTL rewrites
196
+ * @param status - Session lifecycle status used by storage cleanup
203
197
  * @private
204
198
  */
205
199
  private saveSession;
200
+ /**
201
+ * Removes transient setup/auth sessions without masking the original error.
202
+ * @private
203
+ */
204
+ private deleteTransientSession;
206
205
  /**
207
206
  * Try to connect using available transports
208
207
  * @returns The corrected transport type object if successful
@@ -223,7 +222,7 @@ declare class MCPClient {
223
222
  * Saves active session to Redis after successful authentication
224
223
  * @param authCode - Authorization code received from OAuth callback
225
224
  */
226
- finishAuth(authCode: string): Promise<void>;
225
+ finishAuth(authCode: string, state?: string): Promise<void>;
227
226
  /**
228
227
  * Lists all available tools from the connected MCP server
229
228
  * @returns List of tools with their schemas and descriptions
@@ -283,10 +282,15 @@ declare class MCPClient {
283
282
  */
284
283
  isConnected(): boolean;
285
284
  /**
286
- * Disconnects from the MCP server and cleans up resources
287
- * Does not remove session from Redis - use clearSession() for that
285
+ * Disconnects from the MCP server and cleans up resources.
286
+ * Does not remove session from Redis use clearSession() for that.
287
+ *
288
+ * For Streamable HTTP sessions, sends an HTTP DELETE to the MCP endpoint
289
+ * before closing, as recommended by the MCP Streamable HTTP spec
290
+ * (section "Session Management", rule 5). This is best-effort — errors
291
+ * (e.g. server already restarted, 404/405 responses) are silently ignored.
288
292
  */
289
- disconnect(reason?: string): void;
293
+ disconnect(): Promise<void>;
290
294
  /**
291
295
  * Dispose of all event emitters
292
296
  * Call this when the client is no longer needed
@@ -322,19 +326,6 @@ declare class MCPClient {
322
326
  * @returns Session ID
323
327
  */
324
328
  getSessionId(): string;
325
- /**
326
- * Gets MCP server configuration for all active user sessions
327
- * Loads sessions from storage and returns server connection metadata.
328
- * OAuth refresh is handled by SDK transports through their authProvider.
329
- * @deprecated This returns legacy connection metadata only and does not
330
- * include OAuth tokens or generated Authorization headers. Prefer
331
- * MultiSessionClient or explicit MCPClient instances so SDK transports can
332
- * own OAuth refresh and reauthorization.
333
- * @param userId - User ID to fetch sessions for
334
- * @returns Object keyed by sanitized server labels containing transport and url.
335
- * @static
336
- */
337
- static getMcpServerConfig(userId: string): Promise<Record<string, any>>;
338
329
  }
339
330
 
340
331
  /**
@@ -384,12 +375,8 @@ declare class MultiSessionClient {
384
375
  *
385
376
  * A session is considered connectable when:
386
377
  * - It has a `serverId`, `serverUrl`, and `callbackUrl` (i.e. it was fully initialized)
387
- * - Its `active` flag is not explicitly `false` sessions with `active: false` are
388
- * either mid-OAuth flow, auth-pending, or previously failed. We skip those here
378
+ * - Its status is `active`. Pending sessions are skipped here
389
379
  * and let the OAuth flow complete separately before we try to reconnect them.
390
- *
391
- * Note: Sessions where `active` is `undefined` (legacy records) are included
392
- * for backwards compatibility.
393
380
  */
394
381
  private getActiveSessions;
395
382
  /**
@@ -405,6 +392,9 @@ declare class MultiSessionClient {
405
392
  * Connects a single session, with built-in deduplication to prevent race conditions.
406
393
  *
407
394
  * - If a client for this session already exists and is connected, returns immediately.
395
+ * - If the existing client entry is no longer connected (e.g. it was explicitly
396
+ * disconnected), it is evicted so that `establishConnectionWithRetries` creates a
397
+ * fresh transport — preventing "Client already connected" errors from the SDK.
408
398
  * - If a connection attempt for this session is already in-flight (e.g. from a
409
399
  * concurrent call), it joins the existing promise instead of starting a new one.
410
400
  * This is the key concurrency lock — the `connectionPromises` map acts as a
@@ -436,6 +426,17 @@ declare class MultiSessionClient {
436
426
  * re-fetching and re-connecting on every request.
437
427
  */
438
428
  connect(): Promise<void>;
429
+ /**
430
+ * Drops all cached `MCPClient` instances and reconnects fresh from storage.
431
+ *
432
+ * Call this when downstream MCP servers have expired their transport sessions
433
+ * (e.g. after a remote server restart) and subsequent tool calls return
434
+ * "Session not found. Reconnect without session header." errors.
435
+ *
436
+ * OAuth tokens are preserved in the storage backend — no re-authentication
437
+ * is required. Only the in-memory transport sessions are cleared.
438
+ */
439
+ reconnect(): Promise<void>;
439
440
  /**
440
441
  * Returns all currently connected `MCPClient` instances.
441
442
  *
@@ -446,10 +447,14 @@ declare class MultiSessionClient {
446
447
  /**
447
448
  * Gracefully disconnects all active MCP clients and clears the internal client list.
448
449
  *
450
+ * For Streamable HTTP sessions, each client sends an HTTP DELETE to its MCP
451
+ * endpoint per the spec before closing locally. All disconnects run in
452
+ * parallel so shutdown is not serialised across many sessions.
453
+ *
449
454
  * Call this during server shutdown or when a user logs out to free up
450
455
  * underlying transport resources (SSE streams, HTTP connections, etc.).
451
456
  */
452
- disconnect(): void;
457
+ disconnect(): Promise<void>;
453
458
  }
454
459
 
455
460
  export { MCPClient as M, StorageOAuthClientProvider as S, MultiSessionClient as a };
@@ -1,4 +1,4 @@
1
- import { b as Event, M as McpConnectionEvent, d as McpObservabilityEvent, c as McpConnectionState } from './events-CK3N--3g.mjs';
1
+ import { b as Event, M as McpConnectionEvent, d as McpObservabilityEvent, c as McpConnectionState } from './events-C4m7tK1U.mjs';
2
2
  import { ListToolsResult, CallToolResult, ListPromptsResult, GetPromptResult, ListResourcesResult, ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
3
3
  import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
4
4
  import { OAuthClientMetadata, OAuthClientInformationMixed, OAuthClientInformationFull, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
@@ -18,8 +18,6 @@ interface AgentsOAuthProvider extends OAuthClientProvider {
18
18
  }>;
19
19
  consumeState(state: string): Promise<void>;
20
20
  deleteCodeVerifier(): Promise<void>;
21
- isTokenExpired(): boolean;
22
- setTokenExpiresAt(expiresAt: number): void;
23
21
  }
24
22
  interface StorageOAuthClientProviderOptions {
25
23
  userId: string;
@@ -51,7 +49,6 @@ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
51
49
  private _authUrl;
52
50
  private _clientId;
53
51
  private onRedirectCallback?;
54
- private tokenExpiresAt?;
55
52
  /**
56
53
  * Creates a new session-backed OAuth provider
57
54
  * @param options - Provider configuration
@@ -61,17 +58,17 @@ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
61
58
  get clientId(): string | undefined;
62
59
  set clientId(clientId_: string | undefined);
63
60
  /**
64
- * Loads OAuth data from the session store
61
+ * Loads OAuth credentials from the session store
65
62
  * @private
66
63
  */
67
- private getSessionData;
64
+ private getCredentials;
68
65
  /**
69
- * Saves OAuth data to the session store
70
- * @param data - Partial OAuth data to save
66
+ * Saves OAuth credentials to the session store
67
+ * @param data - Partial OAuth credentials to save
71
68
  * @private
72
69
  * @throws Error if session doesn't exist (session must be created by controller layer)
73
70
  */
74
- private saveSessionData;
71
+ private patchCredentials;
75
72
  /**
76
73
  * Retrieves stored OAuth client information
77
74
  */
@@ -86,20 +83,18 @@ declare class StorageOAuthClientProvider implements AgentsOAuthProvider {
86
83
  saveTokens(tokens: OAuthTokens): Promise<void>;
87
84
  get authUrl(): string | undefined;
88
85
  state(): Promise<string>;
89
- checkState(_state: string): Promise<{
86
+ checkState(state: string): Promise<{
90
87
  valid: boolean;
91
88
  serverId?: string;
92
89
  error?: string;
93
90
  }>;
94
- consumeState(_state: string): Promise<void>;
91
+ consumeState(state: string): Promise<void>;
95
92
  redirectToAuthorization(authUrl: URL): Promise<void>;
96
93
  invalidateCredentials(scope: "all" | "client" | "tokens" | "verifier"): Promise<void>;
97
94
  saveCodeVerifier(verifier: string): Promise<void>;
98
95
  codeVerifier(): Promise<string>;
99
96
  deleteCodeVerifier(): Promise<void>;
100
97
  tokens(): Promise<OAuthTokens | undefined>;
101
- isTokenExpired(): boolean;
102
- setTokenExpiresAt(expiresAt: number): void;
103
98
  }
104
99
 
105
100
  /**
@@ -198,11 +193,15 @@ declare class MCPClient {
198
193
  /**
199
194
  * Saves current session state to the session store
200
195
  * Creates new session if it doesn't exist, updates if it does
201
- * @param ttl - Time-to-live in seconds (defaults to 12hr for connected sessions)
202
- * @param active - Session status marker used to avoid unnecessary TTL rewrites
196
+ * @param status - Session lifecycle status used by storage cleanup
203
197
  * @private
204
198
  */
205
199
  private saveSession;
200
+ /**
201
+ * Removes transient setup/auth sessions without masking the original error.
202
+ * @private
203
+ */
204
+ private deleteTransientSession;
206
205
  /**
207
206
  * Try to connect using available transports
208
207
  * @returns The corrected transport type object if successful
@@ -223,7 +222,7 @@ declare class MCPClient {
223
222
  * Saves active session to Redis after successful authentication
224
223
  * @param authCode - Authorization code received from OAuth callback
225
224
  */
226
- finishAuth(authCode: string): Promise<void>;
225
+ finishAuth(authCode: string, state?: string): Promise<void>;
227
226
  /**
228
227
  * Lists all available tools from the connected MCP server
229
228
  * @returns List of tools with their schemas and descriptions
@@ -283,10 +282,15 @@ declare class MCPClient {
283
282
  */
284
283
  isConnected(): boolean;
285
284
  /**
286
- * Disconnects from the MCP server and cleans up resources
287
- * Does not remove session from Redis - use clearSession() for that
285
+ * Disconnects from the MCP server and cleans up resources.
286
+ * Does not remove session from Redis use clearSession() for that.
287
+ *
288
+ * For Streamable HTTP sessions, sends an HTTP DELETE to the MCP endpoint
289
+ * before closing, as recommended by the MCP Streamable HTTP spec
290
+ * (section "Session Management", rule 5). This is best-effort — errors
291
+ * (e.g. server already restarted, 404/405 responses) are silently ignored.
288
292
  */
289
- disconnect(reason?: string): void;
293
+ disconnect(): Promise<void>;
290
294
  /**
291
295
  * Dispose of all event emitters
292
296
  * Call this when the client is no longer needed
@@ -322,19 +326,6 @@ declare class MCPClient {
322
326
  * @returns Session ID
323
327
  */
324
328
  getSessionId(): string;
325
- /**
326
- * Gets MCP server configuration for all active user sessions
327
- * Loads sessions from storage and returns server connection metadata.
328
- * OAuth refresh is handled by SDK transports through their authProvider.
329
- * @deprecated This returns legacy connection metadata only and does not
330
- * include OAuth tokens or generated Authorization headers. Prefer
331
- * MultiSessionClient or explicit MCPClient instances so SDK transports can
332
- * own OAuth refresh and reauthorization.
333
- * @param userId - User ID to fetch sessions for
334
- * @returns Object keyed by sanitized server labels containing transport and url.
335
- * @static
336
- */
337
- static getMcpServerConfig(userId: string): Promise<Record<string, any>>;
338
329
  }
339
330
 
340
331
  /**
@@ -384,12 +375,8 @@ declare class MultiSessionClient {
384
375
  *
385
376
  * A session is considered connectable when:
386
377
  * - It has a `serverId`, `serverUrl`, and `callbackUrl` (i.e. it was fully initialized)
387
- * - Its `active` flag is not explicitly `false` sessions with `active: false` are
388
- * either mid-OAuth flow, auth-pending, or previously failed. We skip those here
378
+ * - Its status is `active`. Pending sessions are skipped here
389
379
  * and let the OAuth flow complete separately before we try to reconnect them.
390
- *
391
- * Note: Sessions where `active` is `undefined` (legacy records) are included
392
- * for backwards compatibility.
393
380
  */
394
381
  private getActiveSessions;
395
382
  /**
@@ -405,6 +392,9 @@ declare class MultiSessionClient {
405
392
  * Connects a single session, with built-in deduplication to prevent race conditions.
406
393
  *
407
394
  * - If a client for this session already exists and is connected, returns immediately.
395
+ * - If the existing client entry is no longer connected (e.g. it was explicitly
396
+ * disconnected), it is evicted so that `establishConnectionWithRetries` creates a
397
+ * fresh transport — preventing "Client already connected" errors from the SDK.
408
398
  * - If a connection attempt for this session is already in-flight (e.g. from a
409
399
  * concurrent call), it joins the existing promise instead of starting a new one.
410
400
  * This is the key concurrency lock — the `connectionPromises` map acts as a
@@ -436,6 +426,17 @@ declare class MultiSessionClient {
436
426
  * re-fetching and re-connecting on every request.
437
427
  */
438
428
  connect(): Promise<void>;
429
+ /**
430
+ * Drops all cached `MCPClient` instances and reconnects fresh from storage.
431
+ *
432
+ * Call this when downstream MCP servers have expired their transport sessions
433
+ * (e.g. after a remote server restart) and subsequent tool calls return
434
+ * "Session not found. Reconnect without session header." errors.
435
+ *
436
+ * OAuth tokens are preserved in the storage backend — no re-authentication
437
+ * is required. Only the in-memory transport sessions are cleared.
438
+ */
439
+ reconnect(): Promise<void>;
439
440
  /**
440
441
  * Returns all currently connected `MCPClient` instances.
441
442
  *
@@ -446,10 +447,14 @@ declare class MultiSessionClient {
446
447
  /**
447
448
  * Gracefully disconnects all active MCP clients and clears the internal client list.
448
449
  *
450
+ * For Streamable HTTP sessions, each client sends an HTTP DELETE to its MCP
451
+ * endpoint per the spec before closing locally. All disconnects run in
452
+ * parallel so shutdown is not serialised across many sessions.
453
+ *
449
454
  * Call this during server shutdown or when a user logs out to free up
450
455
  * underlying transport resources (SSE streams, HTTP connections, etc.).
451
456
  */
452
- disconnect(): void;
457
+ disconnect(): Promise<void>;
453
458
  }
454
459
 
455
460
  export { MCPClient as M, StorageOAuthClientProvider as S, MultiSessionClient as a };
@@ -1,14 +1,21 @@
1
- export { M as MCPClient, a as MultiSessionClient, S as StorageOAuthClientProvider } from '../multi-session-client-C7hGqzgM.mjs';
1
+ export { M as MCPClient, a as MultiSessionClient, S as StorageOAuthClientProvider } from '../multi-session-client-k-9RvWvi.mjs';
2
2
  export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.mjs';
3
3
  import { OAuthClientInformationMixed, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
4
4
  export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
5
- import { M as McpConnectionEvent, d as McpObservabilityEvent } from '../events-CK3N--3g.mjs';
6
- export { D as Disposable, E as Emitter, b as Event, c as McpConnectionState } from '../events-CK3N--3g.mjs';
7
- import { r as McpRpcResponse, q as McpRpcRequest } from '../types-CxFaaZrM.mjs';
8
- export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, n as ListToolsResponse, T as ToolClient, u as ToolClientProvider, v as ToolInfo } from '../types-CxFaaZrM.mjs';
5
+ import { M as McpConnectionEvent, d as McpObservabilityEvent } from '../events-C4m7tK1U.mjs';
6
+ export { D as Disposable, E as Emitter, b as Event, c as McpConnectionState } from '../events-C4m7tK1U.mjs';
7
+ import { r as McpRpcResponse, q as McpRpcRequest } from '../types-DCk_IF4L.mjs';
8
+ export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, n as ListToolsResponse, T as ToolClient, u as ToolClientProvider, v as ToolInfo } from '../types-DCk_IF4L.mjs';
9
9
  export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
10
10
  import '@modelcontextprotocol/sdk/client/auth.js';
11
11
 
12
+ interface OAuthState {
13
+ nonce: string;
14
+ sessionId: string;
15
+ serverId: string;
16
+ createdAt: number;
17
+ }
18
+ type SessionStatus = 'pending' | 'active';
12
19
  interface Session {
13
20
  sessionId: string;
14
21
  serverId?: string;
@@ -17,19 +24,30 @@ interface Session {
17
24
  transportType: 'sse' | 'streamable-http';
18
25
  callbackUrl: string;
19
26
  createdAt: number;
27
+ updatedAt?: number;
28
+ /**
29
+ * Storage-owned expiration timestamp for pending/inactive sessions.
30
+ * Active sessions use updatedAt-based dormancy cleanup instead.
31
+ */
32
+ expiresAt?: number | null;
20
33
  userId: string;
21
34
  headers?: Record<string, string>;
35
+ authUrl?: string | null;
22
36
  /**
23
- * Session status marker used for TTL transitions:
24
- * - false: short-lived intermediate/error/auth-pending session state
25
- * (keep this value when connection/auth is incomplete or failed)
26
- * - true: active long-lived session state after successful connection/auth completion
37
+ * Session status marker used for lifecycle cleanup:
38
+ * - pending: short-lived intermediate/auth-pending session state
39
+ * - active: restorable session after successful connection/auth completion
27
40
  */
28
- active?: boolean;
29
- clientInformation?: OAuthClientInformationMixed;
30
- tokens?: OAuthTokens;
31
- codeVerifier?: string;
32
- clientId?: string;
41
+ status?: SessionStatus;
42
+ }
43
+ interface SessionCredentials {
44
+ sessionId: string;
45
+ userId: string;
46
+ clientInformation?: OAuthClientInformationMixed | null;
47
+ tokens?: OAuthTokens | null;
48
+ codeVerifier?: string | null;
49
+ clientId?: string | null;
50
+ oauthState?: OAuthState | null;
33
51
  }
34
52
  type SessionMutationType = 'create' | 'update' | 'delete';
35
53
  interface SessionMutationEvent {
@@ -39,7 +57,6 @@ interface SessionMutationEvent {
39
57
  timestamp: number;
40
58
  session?: Session;
41
59
  patch?: Partial<Session>;
42
- ttl?: number;
43
60
  }
44
61
  type SessionMutationListener = (event: SessionMutationEvent) => void | Promise<void>;
45
62
  /**
@@ -57,21 +74,32 @@ interface SessionStore {
57
74
  /**
58
75
  * Creates a new session. Throws if session already exists.
59
76
  * @param session - Session data to create
60
- * @param ttl - Optional TTL in seconds (defaults to backend's default)
61
77
  */
62
- create(session: Session, ttl?: number): Promise<void>;
78
+ create(session: Session): Promise<void>;
63
79
  /**
64
80
  * Updates an existing session with partial data. Throws if session does not exist.
65
81
  * @param userId - User identifier
66
82
  * @param sessionId - Session identifier
67
83
  * @param data - Partial session data to update
68
- * @param ttl - Optional TTL in seconds (defaults to backend's default)
69
84
  */
70
- update(userId: string, sessionId: string, data: Partial<Session>, ttl?: number): Promise<void>;
85
+ update(userId: string, sessionId: string, data: Partial<Session>): Promise<void>;
86
+ /**
87
+ * Patches runtime credentials for an existing session.
88
+ * These values are separated from connection metadata in durable SQL stores.
89
+ */
90
+ patchCredentials(userId: string, sessionId: string, data: Partial<SessionCredentials>): Promise<void>;
71
91
  /**
72
92
  * Retrieves a session
73
93
  */
74
94
  get(userId: string, sessionId: string): Promise<Session | null>;
95
+ /**
96
+ * Retrieves runtime credentials for a session.
97
+ */
98
+ getCredentials(userId: string, sessionId: string): Promise<SessionCredentials | null>;
99
+ /**
100
+ * Clears runtime credentials without removing connection metadata.
101
+ */
102
+ clearCredentials(userId: string, sessionId: string): Promise<void>;
75
103
  /**
76
104
  * Gets full session data for all sessions owned by a user
77
105
  */
@@ -221,7 +249,7 @@ declare class SSEConnectionManager {
221
249
  /**
222
250
  * Cleanup and close all connections
223
251
  */
224
- dispose(): void;
252
+ dispose(): Promise<void>;
225
253
  }
226
254
  /**
227
255
  * Create an SSE endpoint handler compatible with Node.js HTTP frameworks.
@@ -1,14 +1,21 @@
1
- export { M as MCPClient, a as MultiSessionClient, S as StorageOAuthClientProvider } from '../multi-session-client-C_kPHpD5.js';
1
+ export { M as MCPClient, a as MultiSessionClient, S as StorageOAuthClientProvider } from '../multi-session-client-Bwm-efqg.js';
2
2
  export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.js';
3
3
  import { OAuthClientInformationMixed, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
4
4
  export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
5
- import { M as McpConnectionEvent, d as McpObservabilityEvent } from '../events-CK3N--3g.js';
6
- export { D as Disposable, E as Emitter, b as Event, c as McpConnectionState } from '../events-CK3N--3g.js';
7
- import { r as McpRpcResponse, q as McpRpcRequest } from '../types-CxFaaZrM.js';
8
- export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, n as ListToolsResponse, T as ToolClient, u as ToolClientProvider, v as ToolInfo } from '../types-CxFaaZrM.js';
5
+ import { M as McpConnectionEvent, d as McpObservabilityEvent } from '../events-C4m7tK1U.js';
6
+ export { D as Disposable, E as Emitter, b as Event, c as McpConnectionState } from '../events-C4m7tK1U.js';
7
+ import { r as McpRpcResponse, q as McpRpcRequest } from '../types-DCk_IF4L.js';
8
+ export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, n as ListToolsResponse, T as ToolClient, u as ToolClientProvider, v as ToolInfo } from '../types-DCk_IF4L.js';
9
9
  export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
10
10
  import '@modelcontextprotocol/sdk/client/auth.js';
11
11
 
12
+ interface OAuthState {
13
+ nonce: string;
14
+ sessionId: string;
15
+ serverId: string;
16
+ createdAt: number;
17
+ }
18
+ type SessionStatus = 'pending' | 'active';
12
19
  interface Session {
13
20
  sessionId: string;
14
21
  serverId?: string;
@@ -17,19 +24,30 @@ interface Session {
17
24
  transportType: 'sse' | 'streamable-http';
18
25
  callbackUrl: string;
19
26
  createdAt: number;
27
+ updatedAt?: number;
28
+ /**
29
+ * Storage-owned expiration timestamp for pending/inactive sessions.
30
+ * Active sessions use updatedAt-based dormancy cleanup instead.
31
+ */
32
+ expiresAt?: number | null;
20
33
  userId: string;
21
34
  headers?: Record<string, string>;
35
+ authUrl?: string | null;
22
36
  /**
23
- * Session status marker used for TTL transitions:
24
- * - false: short-lived intermediate/error/auth-pending session state
25
- * (keep this value when connection/auth is incomplete or failed)
26
- * - true: active long-lived session state after successful connection/auth completion
37
+ * Session status marker used for lifecycle cleanup:
38
+ * - pending: short-lived intermediate/auth-pending session state
39
+ * - active: restorable session after successful connection/auth completion
27
40
  */
28
- active?: boolean;
29
- clientInformation?: OAuthClientInformationMixed;
30
- tokens?: OAuthTokens;
31
- codeVerifier?: string;
32
- clientId?: string;
41
+ status?: SessionStatus;
42
+ }
43
+ interface SessionCredentials {
44
+ sessionId: string;
45
+ userId: string;
46
+ clientInformation?: OAuthClientInformationMixed | null;
47
+ tokens?: OAuthTokens | null;
48
+ codeVerifier?: string | null;
49
+ clientId?: string | null;
50
+ oauthState?: OAuthState | null;
33
51
  }
34
52
  type SessionMutationType = 'create' | 'update' | 'delete';
35
53
  interface SessionMutationEvent {
@@ -39,7 +57,6 @@ interface SessionMutationEvent {
39
57
  timestamp: number;
40
58
  session?: Session;
41
59
  patch?: Partial<Session>;
42
- ttl?: number;
43
60
  }
44
61
  type SessionMutationListener = (event: SessionMutationEvent) => void | Promise<void>;
45
62
  /**
@@ -57,21 +74,32 @@ interface SessionStore {
57
74
  /**
58
75
  * Creates a new session. Throws if session already exists.
59
76
  * @param session - Session data to create
60
- * @param ttl - Optional TTL in seconds (defaults to backend's default)
61
77
  */
62
- create(session: Session, ttl?: number): Promise<void>;
78
+ create(session: Session): Promise<void>;
63
79
  /**
64
80
  * Updates an existing session with partial data. Throws if session does not exist.
65
81
  * @param userId - User identifier
66
82
  * @param sessionId - Session identifier
67
83
  * @param data - Partial session data to update
68
- * @param ttl - Optional TTL in seconds (defaults to backend's default)
69
84
  */
70
- update(userId: string, sessionId: string, data: Partial<Session>, ttl?: number): Promise<void>;
85
+ update(userId: string, sessionId: string, data: Partial<Session>): Promise<void>;
86
+ /**
87
+ * Patches runtime credentials for an existing session.
88
+ * These values are separated from connection metadata in durable SQL stores.
89
+ */
90
+ patchCredentials(userId: string, sessionId: string, data: Partial<SessionCredentials>): Promise<void>;
71
91
  /**
72
92
  * Retrieves a session
73
93
  */
74
94
  get(userId: string, sessionId: string): Promise<Session | null>;
95
+ /**
96
+ * Retrieves runtime credentials for a session.
97
+ */
98
+ getCredentials(userId: string, sessionId: string): Promise<SessionCredentials | null>;
99
+ /**
100
+ * Clears runtime credentials without removing connection metadata.
101
+ */
102
+ clearCredentials(userId: string, sessionId: string): Promise<void>;
75
103
  /**
76
104
  * Gets full session data for all sessions owned by a user
77
105
  */
@@ -221,7 +249,7 @@ declare class SSEConnectionManager {
221
249
  /**
222
250
  * Cleanup and close all connections
223
251
  */
224
- dispose(): void;
252
+ dispose(): Promise<void>;
225
253
  }
226
254
  /**
227
255
  * Create an SSE endpoint handler compatible with Node.js HTTP frameworks.