@mcp-ts/sdk 1.6.2 → 2.0.0

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 (113) hide show
  1. package/README.md +12 -6
  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-adapter.js +4 -5
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +4 -5
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +3 -3
  9. package/dist/adapters/agui-middleware.d.ts +3 -3
  10. package/dist/adapters/ai-adapter.d.mts +9 -3
  11. package/dist/adapters/ai-adapter.d.ts +9 -3
  12. package/dist/adapters/ai-adapter.js +20 -6
  13. package/dist/adapters/ai-adapter.js.map +1 -1
  14. package/dist/adapters/ai-adapter.mjs +20 -6
  15. package/dist/adapters/ai-adapter.mjs.map +1 -1
  16. package/dist/adapters/langchain-adapter.d.mts +3 -3
  17. package/dist/adapters/langchain-adapter.d.ts +3 -3
  18. package/dist/adapters/langchain-adapter.js +9 -6
  19. package/dist/adapters/langchain-adapter.js.map +1 -1
  20. package/dist/adapters/langchain-adapter.mjs +9 -6
  21. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  22. package/dist/adapters/mastra-adapter.d.mts +1 -1
  23. package/dist/adapters/mastra-adapter.d.ts +1 -1
  24. package/dist/adapters/mastra-adapter.js +5 -1
  25. package/dist/adapters/mastra-adapter.js.map +1 -1
  26. package/dist/adapters/mastra-adapter.mjs +5 -1
  27. package/dist/adapters/mastra-adapter.mjs.map +1 -1
  28. package/dist/bin/mcp-ts.js +7 -1
  29. package/dist/bin/mcp-ts.js.map +1 -1
  30. package/dist/bin/mcp-ts.mjs +7 -1
  31. package/dist/bin/mcp-ts.mjs.map +1 -1
  32. package/dist/client/index.d.mts +2 -2
  33. package/dist/client/index.d.ts +2 -2
  34. package/dist/client/index.js +9 -13
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/client/index.mjs +9 -13
  37. package/dist/client/index.mjs.map +1 -1
  38. package/dist/client/react.d.mts +7 -7
  39. package/dist/client/react.d.ts +7 -7
  40. package/dist/client/react.js +15 -19
  41. package/dist/client/react.js.map +1 -1
  42. package/dist/client/react.mjs +15 -19
  43. package/dist/client/react.mjs.map +1 -1
  44. package/dist/client/vue.d.mts +7 -7
  45. package/dist/client/vue.d.ts +7 -7
  46. package/dist/client/vue.js +14 -18
  47. package/dist/client/vue.js.map +1 -1
  48. package/dist/client/vue.mjs +14 -18
  49. package/dist/client/vue.mjs.map +1 -1
  50. package/dist/{index-DhA-OEAe.d.ts → index-C9gvpxy5.d.ts} +5 -5
  51. package/dist/{index-bFL4ZF2N.d.mts → index-eaH14_5u.d.mts} +5 -5
  52. package/dist/index.d.mts +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +616 -370
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.mjs +615 -370
  57. package/dist/index.mjs.map +1 -1
  58. package/dist/{multi-session-client-CHE8QpVE.d.ts → multi-session-client-BYtguGJm.d.ts} +22 -22
  59. package/dist/{multi-session-client-CQsRbxYI.d.mts → multi-session-client-DYNe6az3.d.mts} +22 -22
  60. package/dist/server/index.d.mts +31 -34
  61. package/dist/server/index.d.ts +31 -34
  62. package/dist/server/index.js +531 -256
  63. package/dist/server/index.js.map +1 -1
  64. package/dist/server/index.mjs +530 -256
  65. package/dist/server/index.mjs.map +1 -1
  66. package/dist/shared/index.d.mts +5 -5
  67. package/dist/shared/index.d.ts +5 -5
  68. package/dist/shared/index.js +76 -101
  69. package/dist/shared/index.js.map +1 -1
  70. package/dist/shared/index.mjs +76 -101
  71. package/dist/shared/index.mjs.map +1 -1
  72. package/dist/{tool-router-Dh2804tM.d.ts → tool-router-Ddtybmr0.d.ts} +71 -73
  73. package/dist/{tool-router-BVaV1udm.d.mts → tool-router-Dnd6IOKC.d.mts} +71 -73
  74. package/dist/{types-rIuN1CQi.d.mts → types-BCAG20P6.d.mts} +4 -4
  75. package/dist/{types-rIuN1CQi.d.ts → types-BCAG20P6.d.ts} +4 -4
  76. package/dist/{utils-0qmYrqoa.d.mts → utils-DELRKQPU.d.mts} +1 -1
  77. package/dist/{utils-0qmYrqoa.d.ts → utils-DELRKQPU.d.ts} +1 -1
  78. package/migrations/neon/20260513010000_install_mcp_sessions.sql +69 -0
  79. package/migrations/neon/20260513020000_add_session_cleanup_cron.sql +35 -0
  80. package/{supabase/migrations → migrations/supabase}/20260330195700_install_mcp_sessions.sql +7 -9
  81. package/package.json +14 -5
  82. package/src/adapters/ai-adapter.ts +30 -1
  83. package/src/adapters/langchain-adapter.ts +6 -2
  84. package/src/adapters/mastra-adapter.ts +6 -2
  85. package/src/bin/mcp-ts.ts +8 -1
  86. package/src/client/core/app-host.ts +1 -1
  87. package/src/client/core/sse-client.ts +12 -14
  88. package/src/client/core/types.ts +1 -1
  89. package/src/client/react/use-mcp-apps.tsx +1 -1
  90. package/src/client/react/use-mcp.ts +11 -11
  91. package/src/client/vue/use-mcp.ts +10 -10
  92. package/src/server/handlers/nextjs-handler.ts +18 -15
  93. package/src/server/handlers/sse-handler.ts +29 -29
  94. package/src/server/index.ts +1 -1
  95. package/src/server/mcp/multi-session-client.ts +17 -17
  96. package/src/server/mcp/oauth-client.ts +37 -37
  97. package/src/server/mcp/storage-oauth-provider.ts +17 -17
  98. package/src/server/storage/file-backend.ts +25 -25
  99. package/src/server/storage/index.ts +67 -10
  100. package/src/server/storage/memory-backend.ts +34 -34
  101. package/src/server/storage/neon-backend.ts +281 -0
  102. package/src/server/storage/redis-backend.ts +64 -64
  103. package/src/server/storage/sqlite-backend.ts +33 -33
  104. package/src/server/storage/supabase-backend.ts +23 -24
  105. package/src/server/storage/types.ts +18 -21
  106. package/src/shared/errors.ts +1 -1
  107. package/src/shared/index.ts +1 -2
  108. package/src/shared/meta-tools.ts +4 -6
  109. package/src/shared/schema-compressor.ts +2 -42
  110. package/src/shared/tool-index.ts +89 -84
  111. package/src/shared/tool-router.ts +0 -24
  112. package/src/shared/types.ts +4 -4
  113. /package/{supabase/migrations → migrations/supabase}/20260421010000_add_session_cleanup_cron.sql +0 -0
@@ -26,7 +26,7 @@ import type {
26
26
  SessionListResult,
27
27
  ConnectResult,
28
28
  DisconnectResult,
29
- RestoreSessionResult,
29
+ GetSessionResult,
30
30
  FinishAuthResult,
31
31
  ListToolsRpcResult,
32
32
  ListPromptsResult,
@@ -37,7 +37,7 @@ import { RpcErrorCodes } from '../../shared/errors.js';
37
37
  import { UnauthorizedError } from '../../shared/errors.js';
38
38
  import { isConnectionEvent, isRpcResponseEvent } from '../../shared/event-routing.js';
39
39
  import { MCPClient } from '../mcp/oauth-client.js';
40
- import { storage } from '../storage/index.js';
40
+ import { sessions } from '../storage/index.js';
41
41
 
42
42
  // ============================================
43
43
  // Types & Interfaces
@@ -52,10 +52,10 @@ export interface ClientMetadata {
52
52
 
53
53
  export interface SSEHandlerOptions {
54
54
  /** User/Client identifier */
55
- identity: string;
55
+ userId: string;
56
56
 
57
57
  /** Optional callback for authentication/authorization */
58
- onAuth?: (identity: string) => Promise<boolean>;
58
+ onAuth?: (userId: string) => Promise<boolean>;
59
59
 
60
60
  /** Heartbeat interval in milliseconds @default 30000 */
61
61
  heartbeatInterval?: number;
@@ -92,7 +92,7 @@ function normalizeHeaders(headers?: Record<string, string>): Record<string, stri
92
92
  * Each instance corresponds to one connected browser client.
93
93
  */
94
94
  export class SSEConnectionManager {
95
- private readonly identity: string;
95
+ private readonly userId: string;
96
96
  private readonly clients = new Map<string, MCPClient>();
97
97
  private heartbeatTimer?: NodeJS.Timeout;
98
98
  private isActive = true;
@@ -101,7 +101,7 @@ export class SSEConnectionManager {
101
101
  private readonly options: SSEHandlerOptions,
102
102
  private readonly sendEvent: (event: McpConnectionEvent | McpObservabilityEvent | McpRpcResponse) => void
103
103
  ) {
104
- this.identity = options.identity;
104
+ this.userId = options.userId;
105
105
  this.startHeartbeat();
106
106
  }
107
107
 
@@ -148,11 +148,11 @@ export class SSEConnectionManager {
148
148
  */
149
149
  async handleRequest(request: McpRpcRequest): Promise<McpRpcResponse> {
150
150
  try {
151
- let result: SessionListResult | ConnectResult | DisconnectResult | RestoreSessionResult | FinishAuthResult | ListToolsRpcResult | ListPromptsResult | ListResourcesResult | unknown;
151
+ let result: SessionListResult | ConnectResult | DisconnectResult | GetSessionResult | FinishAuthResult | ListToolsRpcResult | ListPromptsResult | ListResourcesResult | unknown;
152
152
 
153
153
  switch (request.method) {
154
- case 'getSessions':
155
- result = await this.getSessions();
154
+ case 'listSessions':
155
+ result = await this.listSessions();
156
156
  break;
157
157
 
158
158
  case 'connect':
@@ -171,8 +171,8 @@ export class SSEConnectionManager {
171
171
  result = await this.callTool(request.params as CallToolParams);
172
172
  break;
173
173
 
174
- case 'restoreSession':
175
- result = await this.restoreSession(request.params as SessionParams);
174
+ case 'getSession':
175
+ result = await this.getSession(request.params as SessionParams);
176
176
  break;
177
177
 
178
178
  case 'finishAuth':
@@ -225,13 +225,13 @@ export class SSEConnectionManager {
225
225
  }
226
226
 
227
227
  /**
228
- * Get all sessions for the current identity
228
+ * Get all sessions for the current userId
229
229
  */
230
- private async getSessions(): Promise<SessionListResult> {
231
- const sessions = await storage.getIdentitySessionsData(this.identity);
230
+ private async listSessions(): Promise<SessionListResult> {
231
+ const sessionList = await sessions.list(this.userId);
232
232
 
233
233
  return {
234
- sessions: sessions.map((s) => ({
234
+ sessions: sessionList.map((s) => ({
235
235
  sessionId: s.sessionId,
236
236
  serverId: s.serverId,
237
237
  serverName: s.serverName,
@@ -254,10 +254,10 @@ export class SSEConnectionManager {
254
254
  // Tool name format: tool_<serverId>_<toolName> - with 12 char serverId leaves 46 chars for tool name
255
255
  const serverId = params.serverId && params.serverId.length <= 12
256
256
  ? params.serverId
257
- : await storage.generateSessionId();
257
+ : await sessions.generateSessionId();
258
258
 
259
259
  // Check for existing connections
260
- const existingSessions = await storage.getIdentitySessionsData(this.identity);
260
+ const existingSessions = await sessions.list(this.userId);
261
261
  const duplicate = existingSessions.find(s =>
262
262
  s.serverId === serverId || s.serverUrl === serverUrl
263
263
  );
@@ -266,7 +266,7 @@ export class SSEConnectionManager {
266
266
  // If the existing session is still pending OAuth, treat connect as "resume auth"
267
267
  // instead of failing with duplicate connection error.
268
268
  if (duplicate.active === false) {
269
- await this.restoreSession({ sessionId: duplicate.sessionId });
269
+ await this.getSession({ sessionId: duplicate.sessionId });
270
270
  return {
271
271
  sessionId: duplicate.sessionId,
272
272
  success: true,
@@ -276,7 +276,7 @@ export class SSEConnectionManager {
276
276
  }
277
277
 
278
278
  // Generate session ID
279
- const sessionId = await storage.generateSessionId();
279
+ const sessionId = await sessions.generateSessionId();
280
280
 
281
281
  try {
282
282
  // Get resolved client metadata
@@ -284,7 +284,7 @@ export class SSEConnectionManager {
284
284
 
285
285
  // Create MCP client
286
286
  const client = new MCPClient({
287
- identity: this.identity,
287
+ userId: this.userId,
288
288
  sessionId,
289
289
  serverId,
290
290
  serverName,
@@ -360,7 +360,7 @@ export class SSEConnectionManager {
360
360
  } else {
361
361
  // Handle orphaned sessions (e.g., OAuth flow failed before client was stored)
362
362
  // Directly remove from storage since there's no active client
363
- await storage.removeSession(this.identity, sessionId);
363
+ await sessions.delete(this.userId, sessionId);
364
364
  }
365
365
 
366
366
  return { success: true };
@@ -375,13 +375,13 @@ export class SSEConnectionManager {
375
375
  return existing;
376
376
  }
377
377
 
378
- const session = await storage.getSession(this.identity, sessionId);
378
+ const session = await sessions.get(this.userId, sessionId);
379
379
  if (!session) {
380
380
  throw new Error('Session not found');
381
381
  }
382
382
 
383
383
  const client = new MCPClient({
384
- identity: this.identity,
384
+ userId: this.userId,
385
385
  sessionId,
386
386
  // These fields are optional in MCPClient, but when rehydrating a known
387
387
  // stored session on the server we pass them explicitly to preserve the
@@ -439,10 +439,10 @@ export class SSEConnectionManager {
439
439
  /**
440
440
  * Restore and validate an existing session
441
441
  */
442
- private async restoreSession(params: SessionParams): Promise<RestoreSessionResult> {
442
+ private async getSession(params: SessionParams): Promise<GetSessionResult> {
443
443
  const { sessionId } = params;
444
444
 
445
- const session = await storage.getSession(this.identity, sessionId);
445
+ const session = await sessions.get(this.userId, sessionId);
446
446
  if (!session) {
447
447
  throw new Error('Session not found');
448
448
  }
@@ -462,7 +462,7 @@ export class SSEConnectionManager {
462
462
  const clientMetadata = await this.getResolvedClientMetadata();
463
463
 
464
464
  const client = new MCPClient({
465
- identity: this.identity,
465
+ userId: this.userId,
466
466
  sessionId,
467
467
  // These fields are optional in MCPClient, but when rehydrating a known
468
468
  // stored session on the server we pass them explicitly to preserve the
@@ -506,14 +506,14 @@ export class SSEConnectionManager {
506
506
  private async finishAuth(params: FinishAuthParams): Promise<FinishAuthResult> {
507
507
  const { sessionId, code } = params;
508
508
 
509
- const session = await storage.getSession(this.identity, sessionId);
509
+ const session = await sessions.get(this.userId, sessionId);
510
510
  if (!session) {
511
511
  throw new Error('Session not found');
512
512
  }
513
513
 
514
514
  try {
515
515
  const client = new MCPClient({
516
- identity: this.identity,
516
+ userId: this.userId,
517
517
  sessionId,
518
518
  // These fields are optional in MCPClient, but when rehydrating a known
519
519
  // stored session on the server we pass them explicitly to preserve the
@@ -524,7 +524,7 @@ export class SSEConnectionManager {
524
524
  serverUrl: session.serverUrl,
525
525
  callbackUrl: session.callbackUrl,
526
526
  // NOTE: transportType is intentionally omitted here.
527
- // The session's stored transportType is a placeholder ('streamable_http')
527
+ // The session's stored transportType is a placeholder ('streamable-http')
528
528
  // set before transport negotiation. Omitting it lets MCPClient auto-negotiate
529
529
  // (try streamable_http → SSE fallback), which is critical for servers like
530
530
  // Neon that only support SSE transport.
@@ -6,7 +6,7 @@
6
6
  /** Core MCP client and session management */
7
7
  export { MCPClient } from './mcp/oauth-client.js';
8
8
  export { UnauthorizedError } from '../shared/errors.js';
9
- export { storage, type StorageBackend } from './storage/index.js';
9
+ export { sessions, type SessionStore } from './storage/index.js';
10
10
  export { StorageOAuthClientProvider } from './mcp/storage-oauth-provider.js';
11
11
  export { MultiSessionClient } from './mcp/multi-session-client.js';
12
12
 
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
3
  import { MCPClient } from './oauth-client.js';
4
- import { storage, type SessionData } from '../storage/index.js';
4
+ import { sessions, type Session } from '../storage/index.js';
5
5
 
6
6
  const DEFAULT_TIMEOUT_MS = 15000;
7
7
  const DEFAULT_MAX_RETRIES = 2;
@@ -9,7 +9,7 @@ const DEFAULT_RETRY_DELAY_MS = 1000;
9
9
  const CONNECTION_BATCH_SIZE = 5;
10
10
 
11
11
  /**
12
- * Manages multiple MCP connections for a single user identity.
12
+ * Manages multiple MCP connections for a single user.
13
13
  * Allows aggregating tools from all connected servers.
14
14
  */
15
15
  export interface MultiSessionOptions {
@@ -31,7 +31,7 @@ export interface MultiSessionOptions {
31
31
  }
32
32
 
33
33
  /**
34
- * Manages multiple MCP client connections for a single user identity.
34
+ * Manages multiple MCP client connections for a single user.
35
35
  *
36
36
  * On a traditional long-running server, you can cache this instance per user
37
37
  * so the connections stay alive between requests. On serverless, a new instance
@@ -40,18 +40,18 @@ export interface MultiSessionOptions {
40
40
  */
41
41
  export class MultiSessionClient {
42
42
  private clients: MCPClient[] = [];
43
- private identity: string;
43
+ private userId: string;
44
44
  private options: MultiSessionOptions;
45
45
 
46
46
  /**
47
- * Creates a new MultiSessionClient for the given user identity.
47
+ * Creates a new MultiSessionClient for the given user userId.
48
48
  *
49
- * @param identity - A unique string identifying the user (e.g. user ID or email).
49
+ * @param userId - A unique string identifying the user (e.g. user ID or email).
50
50
  * @param options - Optional tuning for connection timeout, retry count, and retry delay.
51
51
  * Falls back to sensible defaults if not provided.
52
52
  */
53
- constructor(identity: string, options: MultiSessionOptions = {}) {
54
- this.identity = identity;
53
+ constructor(userId: string, options: MultiSessionOptions = {}) {
54
+ this.userId = userId;
55
55
  this.options = {
56
56
  timeout: DEFAULT_TIMEOUT_MS,
57
57
  maxRetries: DEFAULT_MAX_RETRIES,
@@ -61,7 +61,7 @@ export class MultiSessionClient {
61
61
  }
62
62
 
63
63
  /**
64
- * Fetches all sessions for this identity from storage and returns only the
64
+ * Fetches all sessions for this userId from storage and returns only the
65
65
  * ones that are ready to connect.
66
66
  *
67
67
  * A session is considered connectable when:
@@ -73,9 +73,9 @@ export class MultiSessionClient {
73
73
  * Note: Sessions where `active` is `undefined` (legacy records) are included
74
74
  * for backwards compatibility.
75
75
  */
76
- private async getActiveSessions(): Promise<SessionData[]> {
77
- const sessions = await storage.getIdentitySessionsData(this.identity);
78
- const valid = sessions.filter(s =>
76
+ private async getActiveSessions(): Promise<Session[]> {
77
+ const sessionList = await sessions.list(this.userId);
78
+ const valid = sessionList.filter(s =>
79
79
  s.serverId &&
80
80
  s.serverUrl &&
81
81
  s.callbackUrl &&
@@ -91,7 +91,7 @@ export class MultiSessionClient {
91
91
  * has many active MCP sessions (e.g. 20+ servers). Within each batch, sessions
92
92
  * are connected concurrently using `Promise.all` for speed.
93
93
  */
94
- private async connectInBatches(sessions: SessionData[]): Promise<void> {
94
+ private async connectInBatches(sessions: Session[]): Promise<void> {
95
95
  for (let i = 0; i < sessions.length; i += CONNECTION_BATCH_SIZE) {
96
96
  const batch = sessions.slice(i, i + CONNECTION_BATCH_SIZE);
97
97
  await Promise.all(batch.map(session => this.connectSession(session)));
@@ -110,7 +110,7 @@ export class MultiSessionClient {
110
110
  * per-session mutex so we never spin up two physical connections for the same session.
111
111
  * - On completion (success or failure), the promise is cleaned up from the map.
112
112
  */
113
- private async connectSession(session: SessionData): Promise<void> {
113
+ private async connectSession(session: Session): Promise<void> {
114
114
  const existingClient = this.clients.find(c => c.getSessionId() === session.sessionId);
115
115
  if (existingClient?.isConnected()) {
116
116
  return;
@@ -146,7 +146,7 @@ export class MultiSessionClient {
146
146
  * If all attempts are exhausted, logs an error and returns silently (does not throw),
147
147
  * so a single bad server doesn't block the rest of the batch from connecting.
148
148
  */
149
- private async establishConnectionWithRetries(session: SessionData): Promise<void> {
149
+ private async establishConnectionWithRetries(session: Session): Promise<void> {
150
150
  const maxRetries = this.options.maxRetries ?? DEFAULT_MAX_RETRIES;
151
151
  const retryDelay = this.options.retryDelay ?? DEFAULT_RETRY_DELAY_MS;
152
152
  let lastError: unknown;
@@ -154,7 +154,7 @@ export class MultiSessionClient {
154
154
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
155
155
  try {
156
156
  const client = new MCPClient({
157
- identity: this.identity,
157
+ userId: this.userId,
158
158
  sessionId: session.sessionId,
159
159
  serverId: session.serverId,
160
160
  serverUrl: session.serverUrl,
@@ -192,7 +192,7 @@ export class MultiSessionClient {
192
192
  }
193
193
 
194
194
  /**
195
- * The main entry point. Fetches all active sessions for this identity from
195
+ * The main entry point. Fetches all active sessions for this userId from
196
196
  * storage and establishes connections to all of them in batches.
197
197
  *
198
198
  * Call this once after creating the client. On traditional servers, you can
@@ -33,7 +33,7 @@ import { StorageOAuthClientProvider, type AgentsOAuthProvider } from './storage-
33
33
  import { sanitizeServerLabel } from '../../shared/utils.js';
34
34
  import { Emitter, type McpConnectionEvent, type McpObservabilityEvent, type McpConnectionState } from '../../shared/events.js';
35
35
  import { UnauthorizedError } from '../../shared/errors.js';
36
- import { storage } from '../storage/index.js';
36
+ import { sessions } from '../storage/index.js';
37
37
  import {
38
38
  MCP_CLIENT_NAME,
39
39
  MCP_CLIENT_VERSION,
@@ -44,7 +44,7 @@ import {
44
44
  /**
45
45
  * Supported MCP transport types
46
46
  */
47
- export type TransportType = 'sse' | 'streamable_http';
47
+ export type TransportType = 'sse' | 'streamable-http';
48
48
 
49
49
  /**
50
50
  * Extended capabilities including MCP App support
@@ -65,7 +65,7 @@ export interface MCPOAuthClientOptions {
65
65
  serverName?: string;
66
66
  callbackUrl?: string;
67
67
  onRedirect?: (url: string) => void;
68
- identity: string;
68
+ userId: string;
69
69
  serverId?: string; /** Optional - loaded from session if not provided */
70
70
  sessionId: string; /** Required - primary key for session lookup */
71
71
  transportType?: TransportType;
@@ -88,7 +88,7 @@ export class MCPClient {
88
88
  private client: Client | null = null;
89
89
  public oauthProvider: AgentsOAuthProvider | null = null;
90
90
  private transport: StreamableHTTPClientTransport | SSEClientTransport | null = null;
91
- private identity: string;
91
+ private userId: string;
92
92
  private serverId?: string;
93
93
  private sessionId: string;
94
94
  private serverName?: string;
@@ -118,7 +118,7 @@ export class MCPClient {
118
118
 
119
119
  /**
120
120
  * Creates a new MCP client instance
121
- * Can be initialized with minimal options (identity + sessionId) for session restoration
121
+ * Can be initialized with minimal options (userId + sessionId) for session restoration
122
122
  * @param options - Client configuration options
123
123
  */
124
124
  constructor(options: MCPOAuthClientOptions) {
@@ -126,7 +126,7 @@ export class MCPClient {
126
126
  this.serverName = options.serverName;
127
127
  this.callbackUrl = options.callbackUrl;
128
128
  this.onRedirect = options.onRedirect;
129
- this.identity = options.identity;
129
+ this.userId = options.userId;
130
130
  this.serverId = options.serverId;
131
131
  this.sessionId = options.sessionId;
132
132
  this.transportType = options.transportType;
@@ -283,7 +283,7 @@ export class MCPClient {
283
283
  this.emitProgress('Loading session configuration...');
284
284
 
285
285
  if (!this.serverUrl || !this.callbackUrl || !this.serverId) {
286
- const sessionData = await storage.getSession(this.identity, this.sessionId);
286
+ const sessionData = await sessions.get(this.userId, this.sessionId);
287
287
  if (!sessionData) {
288
288
  throw new Error(`Session not found: ${this.sessionId}`);
289
289
  }
@@ -310,7 +310,7 @@ export class MCPClient {
310
310
  throw new Error('serverId required for OAuth provider initialization');
311
311
  }
312
312
  this.oauthProvider = new StorageOAuthClientProvider({
313
- identity: this.identity,
313
+ userId: this.userId,
314
314
  serverId: this.serverId,
315
315
  sessionId: this.sessionId,
316
316
  redirectUrl: this.callbackUrl!,
@@ -346,21 +346,21 @@ export class MCPClient {
346
346
  );
347
347
  }
348
348
 
349
- // Create session in storage if it doesn't exist yet
349
+ // Create session in the session store if it doesn't exist yet
350
350
  // This is needed BEFORE OAuth flow starts because the OAuth provider
351
351
  // will call saveCodeVerifier() which requires the session to exist
352
- const existingSession = await storage.getSession(this.identity, this.sessionId);
352
+ const existingSession = await sessions.get(this.userId, this.sessionId);
353
353
  if (!existingSession && this.serverId && this.serverUrl && this.callbackUrl) {
354
354
  this.createdAt = Date.now();
355
355
  console.log(`[MCPClient] Creating initial session ${this.sessionId} for OAuth flow`);
356
- await storage.createSession({
356
+ await sessions.create({
357
357
  sessionId: this.sessionId,
358
- identity: this.identity,
358
+ userId: this.userId,
359
359
  serverId: this.serverId,
360
360
  serverName: this.serverName,
361
361
  serverUrl: this.serverUrl,
362
362
  callbackUrl: this.callbackUrl,
363
- transportType: this.transportType || 'streamable_http',
363
+ transportType: this.transportType || 'streamable-http',
364
364
  headers: this.headers,
365
365
  createdAt: this.createdAt,
366
366
  active: false,
@@ -369,7 +369,7 @@ export class MCPClient {
369
369
  }
370
370
 
371
371
  /**
372
- * Saves current session state to storage
372
+ * Saves current session state to the session store
373
373
  * Creates new session if it doesn't exist, updates if it does
374
374
  * @param ttl - Time-to-live in seconds (defaults to 12hr for connected sessions)
375
375
  * @param active - Session status marker used to avoid unnecessary TTL rewrites
@@ -385,23 +385,23 @@ export class MCPClient {
385
385
 
386
386
  const sessionData = {
387
387
  sessionId: this.sessionId,
388
- identity: this.identity,
388
+ userId: this.userId,
389
389
  serverId: this.serverId,
390
390
  serverName: this.serverName,
391
391
  serverUrl: this.serverUrl,
392
392
  callbackUrl: this.callbackUrl,
393
- transportType: (this.transportType || 'streamable_http') as TransportType,
393
+ transportType: (this.transportType || 'streamable-http') as TransportType,
394
394
  headers: this.headers,
395
395
  createdAt: this.createdAt || Date.now(),
396
396
  active,
397
397
  };
398
398
 
399
399
  // Try to update first, create if doesn't exist
400
- const existingSession = await storage.getSession(this.identity, this.sessionId);
400
+ const existingSession = await sessions.get(this.userId, this.sessionId);
401
401
  if (existingSession) {
402
- await storage.updateSession(this.identity, this.sessionId, sessionData, ttl);
402
+ await sessions.update(this.userId, this.sessionId, sessionData, ttl);
403
403
  } else {
404
- await storage.createSession(sessionData, ttl);
404
+ await sessions.create(sessionData, ttl);
405
405
  }
406
406
  }
407
407
 
@@ -417,7 +417,7 @@ export class MCPClient {
417
417
  */
418
418
  const transportsToTry: TransportType[] = this.transportType
419
419
  ? [this.transportType]
420
- : ['streamable_http', 'sse'];
420
+ : ['streamable-http', 'sse'];
421
421
 
422
422
  let lastError: unknown;
423
423
 
@@ -505,7 +505,7 @@ export class MCPClient {
505
505
  this.emitProgress('Connected successfully');
506
506
 
507
507
  // Refresh session metadata on every successful connect so active sessions
508
- // record ongoing usage and don't look dormant to storage cleanup jobs.
508
+ // record ongoing usage and don't look dormant to session cleanup jobs.
509
509
  console.log(`[MCPClient] Saving session ${this.sessionId} with 12hr TTL (connect success)`);
510
510
  await this.saveSession(SESSION_TTL_SECONDS, true);
511
511
  } catch (error) {
@@ -540,7 +540,7 @@ export class MCPClient {
540
540
  // We remove it now to ensure the database remains lean, bypassing the
541
541
  // automated lifecycle sweep.
542
542
  try {
543
- await storage.removeSession(this.identity, this.sessionId);
543
+ await sessions.delete(this.userId, this.sessionId);
544
544
  } catch {
545
545
  // Non-blocking: Proactive cleanup failures are suppressed to prioritize
546
546
  // the original error context.
@@ -579,9 +579,9 @@ export class MCPClient {
579
579
  // Terminal Handshake Failure: only purge transient sessions. Active
580
580
  // sessions may still hold valid credentials for a later reconnect.
581
581
  try {
582
- const existingSession = await storage.getSession(this.identity, this.sessionId);
582
+ const existingSession = await sessions.get(this.userId, this.sessionId);
583
583
  if (!existingSession || existingSession.active !== true) {
584
- await storage.removeSession(this.identity, this.sessionId);
584
+ await sessions.delete(this.userId, this.sessionId);
585
585
  }
586
586
  } catch {
587
587
  // Non-blocking: Cleanup is performed on a best-effort basis and should
@@ -619,7 +619,7 @@ export class MCPClient {
619
619
  */
620
620
  const transportsToTry: TransportType[] = this.transportType
621
621
  ? [this.transportType]
622
- : ['streamable_http', 'sse'];
622
+ : ['streamable-http', 'sse'];
623
623
 
624
624
  let lastError: unknown;
625
625
  let tokensExchanged = false;
@@ -1020,7 +1020,7 @@ export class MCPClient {
1020
1020
  );
1021
1021
 
1022
1022
  // Use default logic to get transport, defaulting to what's stored or auto
1023
- const tt = this.transportType || 'streamable_http';
1023
+ const tt = this.transportType || 'streamable-http';
1024
1024
  this.transport = this.getTransport(tt);
1025
1025
 
1026
1026
  await this.client.connect(this.transport);
@@ -1041,7 +1041,7 @@ export class MCPClient {
1041
1041
  await (this.oauthProvider as any).invalidateCredentials('all');
1042
1042
  }
1043
1043
 
1044
- await storage.removeSession(this.identity, this.sessionId);
1044
+ await sessions.delete(this.userId, this.sessionId);
1045
1045
  this.disconnect();
1046
1046
  }
1047
1047
 
@@ -1119,10 +1119,10 @@ export class MCPClient {
1119
1119
 
1120
1120
  /**
1121
1121
  * Gets the transport type being used
1122
- * @returns Transport type (defaults to 'streamable_http')
1122
+ * @returns Transport type (defaults to 'streamable-http')
1123
1123
  */
1124
1124
  getTransportType(): TransportType {
1125
- return this.transportType || 'streamable_http';
1125
+ return this.transportType || 'streamable-http';
1126
1126
  }
1127
1127
 
1128
1128
  /**
@@ -1156,16 +1156,16 @@ export class MCPClient {
1156
1156
  * Gets MCP server configuration for all active user sessions
1157
1157
  * Loads sessions from Redis, validates OAuth tokens, refreshes if expired
1158
1158
  * Returns ready-to-use configuration with valid auth headers
1159
- * @param identity - User ID to fetch sessions for
1159
+ * @param userId - User ID to fetch sessions for
1160
1160
  * @returns Object keyed by sanitized server labels containing transport, url, headers, etc.
1161
1161
  * @static
1162
1162
  */
1163
- static async getMcpServerConfig(identity: string): Promise<Record<string, any>> {
1163
+ static async getMcpServerConfig(userId: string): Promise<Record<string, any>> {
1164
1164
  const mcpConfig: Record<string, any> = {};
1165
- const sessions = await storage.getIdentitySessionsData(identity);
1165
+ const sessionList = await sessions.list(userId);
1166
1166
 
1167
1167
  await Promise.all(
1168
- sessions.map(async (sessionData) => {
1168
+ sessionList.map(async (sessionData) => {
1169
1169
  const { sessionId } = sessionData;
1170
1170
 
1171
1171
  try {
@@ -1176,16 +1176,16 @@ export class MCPClient {
1176
1176
  !sessionData.serverUrl ||
1177
1177
  !sessionData.callbackUrl
1178
1178
  ) {
1179
- await storage.removeSession(identity, sessionId);
1179
+ await sessions.delete(userId, sessionId);
1180
1180
  return;
1181
1181
  }
1182
1182
 
1183
1183
  // Get OAuth headers if session requires authentication
1184
1184
  let headers: Record<string, string> | undefined;
1185
1185
  try {
1186
- // Inject existing session data to avoid redundant storage reads in initialize()
1186
+ // Inject existing session data to avoid redundant session store reads in initialize()
1187
1187
  const client = new MCPClient({
1188
- identity,
1188
+ userId,
1189
1189
  sessionId,
1190
1190
  serverId: sessionData.serverId,
1191
1191
  serverUrl: sessionData.serverUrl,
@@ -1223,7 +1223,7 @@ export class MCPClient {
1223
1223
  ...(headers && { headers }),
1224
1224
  };
1225
1225
  } catch (error) {
1226
- await storage.removeSession(identity, sessionId);
1226
+ await sessions.delete(userId, sessionId);
1227
1227
  console.warn(`[MCP] Failed to process session ${sessionId}:`, error);
1228
1228
  }
1229
1229
  })