@mcp-ts/sdk 2.5.0 → 2.5.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 (58) 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/index.js +3 -0
  14. package/dist/client/index.js.map +1 -1
  15. package/dist/client/index.mjs +3 -0
  16. package/dist/client/index.mjs.map +1 -1
  17. package/dist/client/react.d.mts +4 -4
  18. package/dist/client/react.d.ts +4 -4
  19. package/dist/client/react.js +22 -37
  20. package/dist/client/react.js.map +1 -1
  21. package/dist/client/react.mjs +22 -37
  22. package/dist/client/react.mjs.map +1 -1
  23. package/dist/client/vue.d.mts +4 -4
  24. package/dist/client/vue.d.ts +4 -4
  25. package/dist/client/vue.js +3 -0
  26. package/dist/client/vue.js.map +1 -1
  27. package/dist/client/vue.mjs +3 -0
  28. package/dist/client/vue.mjs.map +1 -1
  29. package/dist/{index-sVcqrhf7.d.ts → index-BEdyuz1M.d.ts} +2 -1
  30. package/dist/{index-CTURVnom.d.mts → index-C99wE2Zf.d.mts} +2 -1
  31. package/dist/index.d.mts +4 -4
  32. package/dist/index.d.ts +4 -4
  33. package/dist/index.js +66 -0
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +66 -0
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/{multi-session-client-DMZGVABI.d.mts → multi-session-client-CclWRxTD.d.mts} +1 -1
  38. package/dist/{multi-session-client-CSPSHHla.d.ts → multi-session-client-DzvZD6Tt.d.ts} +1 -1
  39. package/dist/server/index.d.mts +9 -4
  40. package/dist/server/index.d.ts +9 -4
  41. package/dist/server/index.js +63 -0
  42. package/dist/server/index.js.map +1 -1
  43. package/dist/server/index.mjs +63 -0
  44. package/dist/server/index.mjs.map +1 -1
  45. package/dist/shared/index.d.mts +4 -4
  46. package/dist/shared/index.d.ts +4 -4
  47. package/dist/shared/index.js.map +1 -1
  48. package/dist/shared/index.mjs.map +1 -1
  49. package/dist/{tool-router-CVLBaCwH.d.mts → tool-router-C9ECn3FX.d.mts} +1 -1
  50. package/dist/{tool-router-CS9l0w4a.d.ts → tool-router-CUSSk6lT.d.ts} +1 -1
  51. package/dist/{types-DK_NGWd4.d.mts → types-CbFbPkfQ.d.mts} +3 -2
  52. package/dist/{types-DK_NGWd4.d.ts → types-CbFbPkfQ.d.ts} +3 -2
  53. package/package.json +2 -2
  54. package/src/client/core/sse-client.ts +4 -0
  55. package/src/client/react/oauth-popup.tsx +17 -24
  56. package/src/client/react/use-mcp.ts +6 -15
  57. package/src/server/handlers/sse-handler.ts +86 -0
  58. package/src/shared/types.ts +4 -0
@@ -1,5 +1,5 @@
1
1
  import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
- import { A as ToolClientProvider, T as ToolClient } from './types-DK_NGWd4.mjs';
2
+ import { A as ToolClientProvider, T as ToolClient } from './types-CbFbPkfQ.mjs';
3
3
 
4
4
  /**
5
5
  * ToolIndex — Lightweight in-memory search index for MCP tool discovery.
@@ -1,5 +1,5 @@
1
1
  import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
- import { A as ToolClientProvider, T as ToolClient } from './types-DK_NGWd4.js';
2
+ import { A as ToolClientProvider, T as ToolClient } from './types-CbFbPkfQ.js';
3
3
 
4
4
  /**
5
5
  * ToolIndex — Lightweight in-memory search index for MCP tool discovery.
@@ -210,7 +210,7 @@ interface ToolPolicy {
210
210
  toolIds: string[];
211
211
  updatedAt: number;
212
212
  }
213
- type McpRpcMethod = 'connect' | 'disconnect' | 'listTools' | 'callTool' | 'listSessions' | 'getSession' | 'finishAuth' | 'listPrompts' | 'getPrompt' | 'listResources' | 'readResource' | 'setToolPolicy' | 'getToolPolicy';
213
+ type McpRpcMethod = 'connect' | 'disconnect' | 'reconnect' | 'listTools' | 'callTool' | 'listSessions' | 'getSession' | 'finishAuth' | 'listPrompts' | 'getPrompt' | 'listResources' | 'readResource' | 'setToolPolicy' | 'getToolPolicy';
214
214
  interface McpRpcRequest {
215
215
  id: string;
216
216
  method: McpRpcMethod;
@@ -235,6 +235,7 @@ interface ConnectParams {
235
235
  interface DisconnectParams {
236
236
  sessionId: string;
237
237
  }
238
+ type ReconnectParams = ConnectParams;
238
239
  interface SessionParams {
239
240
  sessionId: string;
240
241
  }
@@ -266,7 +267,7 @@ interface SetToolPolicyParams {
266
267
  interface GetToolPolicyParams {
267
268
  sessionId: string;
268
269
  }
269
- type McpRpcParams = ConnectParams | DisconnectParams | SessionParams | CallToolParams | GetPromptParams | ReadResourceParams | FinishAuthParams | SetToolPolicyParams | GetToolPolicyParams | undefined;
270
+ type McpRpcParams = ConnectParams | DisconnectParams | ReconnectParams | SessionParams | CallToolParams | GetPromptParams | ReadResourceParams | FinishAuthParams | SetToolPolicyParams | GetToolPolicyParams | undefined;
270
271
  interface SessionInfo {
271
272
  sessionId: string;
272
273
  serverId?: string;
@@ -210,7 +210,7 @@ interface ToolPolicy {
210
210
  toolIds: string[];
211
211
  updatedAt: number;
212
212
  }
213
- type McpRpcMethod = 'connect' | 'disconnect' | 'listTools' | 'callTool' | 'listSessions' | 'getSession' | 'finishAuth' | 'listPrompts' | 'getPrompt' | 'listResources' | 'readResource' | 'setToolPolicy' | 'getToolPolicy';
213
+ type McpRpcMethod = 'connect' | 'disconnect' | 'reconnect' | 'listTools' | 'callTool' | 'listSessions' | 'getSession' | 'finishAuth' | 'listPrompts' | 'getPrompt' | 'listResources' | 'readResource' | 'setToolPolicy' | 'getToolPolicy';
214
214
  interface McpRpcRequest {
215
215
  id: string;
216
216
  method: McpRpcMethod;
@@ -235,6 +235,7 @@ interface ConnectParams {
235
235
  interface DisconnectParams {
236
236
  sessionId: string;
237
237
  }
238
+ type ReconnectParams = ConnectParams;
238
239
  interface SessionParams {
239
240
  sessionId: string;
240
241
  }
@@ -266,7 +267,7 @@ interface SetToolPolicyParams {
266
267
  interface GetToolPolicyParams {
267
268
  sessionId: string;
268
269
  }
269
- type McpRpcParams = ConnectParams | DisconnectParams | SessionParams | CallToolParams | GetPromptParams | ReadResourceParams | FinishAuthParams | SetToolPolicyParams | GetToolPolicyParams | undefined;
270
+ type McpRpcParams = ConnectParams | DisconnectParams | ReconnectParams | SessionParams | CallToolParams | GetPromptParams | ReadResourceParams | FinishAuthParams | SetToolPolicyParams | GetToolPolicyParams | undefined;
270
271
  interface SessionInfo {
271
272
  sessionId: string;
272
273
  serverId?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-ts/sdk",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -206,4 +206,4 @@
206
206
  "engines": {
207
207
  "node": ">=18.0.0"
208
208
  }
209
- }
209
+ }
@@ -102,6 +102,10 @@ export class SSEClient {
102
102
  return this.sendRequest<DisconnectResult>('disconnect', { sessionId });
103
103
  }
104
104
 
105
+ async reconnectToServer(params: ConnectParams): Promise<ConnectResult> {
106
+ return this.sendRequest<ConnectResult>('reconnect', params);
107
+ }
108
+
105
109
  async setToolPolicy(
106
110
  sessionId: string,
107
111
  toolPolicy: Pick<ToolPolicy, 'mode'> & { toolIds?: string[] }
@@ -135,7 +135,6 @@ export function createOAuthPopupRedirectHandler(
135
135
  openCenteredPopup(url, {
136
136
  ...options,
137
137
  onBlocked: options.onBlocked ?? ((blockedUrl) => {
138
- window.alert('Popup blocked! Allow popups for this site to complete authentication.');
139
138
  window.location.href = blockedUrl;
140
139
  }),
141
140
  });
@@ -179,30 +178,26 @@ export function useMcpOAuthPopup<TConnection extends OAuthPopupConnectionLike>(
179
178
  : '';
180
179
  const targetSessionId = rawState ? parseOAuthState(rawState)?.sessionId || rawState : '';
181
180
 
182
- if (popupWindow && targetSessionId) {
181
+ if (targetSessionId) {
183
182
  pendingPopupsRef.current.set(targetSessionId, { popupWindow, state: rawState });
184
183
  }
185
184
 
186
185
  if (!targetSessionId) {
187
- if (popupWindow) {
188
- postPopupResult(popupWindow, {
189
- success: false,
190
- error: 'Missing OAuth session identifier',
191
- });
192
- }
186
+ postPopupResult(popupWindow, {
187
+ success: false,
188
+ error: 'Missing OAuth session identifier',
189
+ });
193
190
  return;
194
191
  }
195
192
 
196
193
  const targetSession = connections.find((connection) => connection.sessionId === targetSessionId);
197
194
  if (!targetSession) {
198
- if (popupWindow) {
199
- postPopupResult(popupWindow, {
200
- sessionId: targetSessionId,
201
- state: rawState,
202
- success: false,
203
- error: 'OAuth session not found in the current client state',
204
- });
205
- }
195
+ postPopupResult(popupWindow, {
196
+ sessionId: targetSessionId,
197
+ state: rawState,
198
+ success: false,
199
+ error: 'OAuth session not found in the current client state',
200
+ });
206
201
  return;
207
202
  }
208
203
 
@@ -217,14 +212,12 @@ export function useMcpOAuthPopup<TConnection extends OAuthPopupConnectionLike>(
217
212
  } catch (error) {
218
213
  processingCodesRef.current.delete(codeKey);
219
214
  pendingPopupsRef.current.delete(targetSession.sessionId);
220
- if (popupWindow) {
221
- postPopupResult(popupWindow, {
222
- sessionId: rawState,
223
- state: rawState,
224
- success: false,
225
- error: error instanceof Error ? error.message : 'Failed to finish auth',
226
- });
227
- }
215
+ postPopupResult(popupWindow, {
216
+ sessionId: rawState,
217
+ state: rawState,
218
+ success: false,
219
+ error: error instanceof Error ? error.message : 'Failed to finish auth',
220
+ });
228
221
  }
229
222
  };
230
223
 
@@ -516,24 +516,15 @@ export function useMcp(options: UseMcpOptions): McpClient {
516
516
  throw new Error('SSE client not initialized');
517
517
  }
518
518
 
519
- // Find and disconnect existing session for the same server
520
- const existing = connections.find(
521
- (c: McpConnection) => c.serverId === params.serverId || c.serverUrl === params.serverUrl
522
- );
523
- if (existing) {
524
- await clientRef.current.disconnectFromServer(existing.sessionId);
525
- if (isMountedRef.current) {
526
- setConnections((prev: McpConnection[]) =>
527
- prev.filter((c: McpConnection) => c.sessionId !== existing.sessionId)
528
- );
529
- }
530
- }
519
+ const result = await clientRef.current.reconnectToServer(params);
520
+
521
+ // The server emits connection events for the new session via SSE,
522
+ // so local state is kept in sync automatically. No manual removal
523
+ // of the old session or insertion of the new one needed here.
531
524
 
532
- // Connect fresh
533
- const result = await clientRef.current.connectToServer(params);
534
525
  return result.sessionId;
535
526
  },
536
- [connections]
527
+ []
537
528
  );
538
529
 
539
530
  /**
@@ -18,6 +18,7 @@ import type {
18
18
  McpRpcResponse,
19
19
  ConnectParams,
20
20
  DisconnectParams,
21
+ ReconnectParams,
21
22
  SessionParams,
22
23
  CallToolParams,
23
24
  GetPromptParams,
@@ -166,6 +167,10 @@ export class SSEConnectionManager {
166
167
  result = await this.connect(request.params as ConnectParams);
167
168
  break;
168
169
 
170
+ case 'reconnect':
171
+ result = await this.reconnect(request.params as ReconnectParams);
172
+ break;
173
+
169
174
  case 'disconnect':
170
175
  result = await this.disconnect(request.params as DisconnectParams);
171
176
  break;
@@ -363,6 +368,87 @@ export class SSEConnectionManager {
363
368
  }
364
369
  }
365
370
 
371
+ /**
372
+ * Reconnect to an MCP server — tears down the active client transport/connection
373
+ * and creates a fresh connection while reusing the existing session credentials in a single RPC call.
374
+ */
375
+ private async reconnect(params: ReconnectParams): Promise<ConnectResult> {
376
+ const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType } = params;
377
+ const headers = normalizeHeaders(params.headers);
378
+
379
+ // Normalize serverId the same way connect() does
380
+ const serverId = rawServerId && rawServerId.length <= 12
381
+ ? rawServerId
382
+ : generateServerId();
383
+
384
+ // Find existing session for the same server to reuse its session ID
385
+ const existingSessions = await sessions.list(this.userId);
386
+ const duplicate = existingSessions.find(s =>
387
+ s.serverId === serverId || s.serverUrl === serverUrl
388
+ );
389
+
390
+ // Reuse the duplicate sessionId if present, otherwise generate a new one
391
+ const sessionId = duplicate ? duplicate.sessionId : await sessions.generateSessionId();
392
+
393
+ if (duplicate) {
394
+ // Disconnect any active in-memory client transport without deleting the database session
395
+ const existingClient = this.clients.get(duplicate.sessionId);
396
+ if (existingClient) {
397
+ await existingClient.disconnect();
398
+ this.clients.delete(duplicate.sessionId);
399
+ }
400
+ }
401
+
402
+ try {
403
+ const clientMetadata = await this.getResolvedClientMetadata();
404
+
405
+ // Create a new client instantiating the reused session ID (which preserves DCR credentials and tokens)
406
+ const client = new MCPClient({
407
+ userId: this.userId,
408
+ sessionId,
409
+ serverId,
410
+ serverName,
411
+ serverUrl,
412
+ callbackUrl,
413
+ transportType,
414
+ headers,
415
+ ...clientMetadata,
416
+ });
417
+
418
+ this.clients.set(sessionId, client);
419
+
420
+ client.onConnectionEvent((event) => {
421
+ this.emitConnectionEvent(event);
422
+ });
423
+
424
+ client.onObservabilityEvent((event) => {
425
+ this.sendEvent(event);
426
+ });
427
+
428
+ await client.connect();
429
+ await this.listPolicyFilteredTools(sessionId);
430
+
431
+ return { sessionId, success: true };
432
+ } catch (error) {
433
+ if (error instanceof UnauthorizedError) {
434
+ this.clients.delete(sessionId);
435
+ return { sessionId, success: true };
436
+ }
437
+
438
+ this.emitConnectionEvent({
439
+ type: 'error',
440
+ sessionId,
441
+ serverId,
442
+ error: error instanceof Error ? error.message : 'Connection failed',
443
+ errorType: 'connection',
444
+ timestamp: Date.now(),
445
+ });
446
+
447
+ this.clients.delete(sessionId);
448
+ throw error;
449
+ }
450
+ }
451
+
366
452
  /**
367
453
  * Disconnect from an MCP server
368
454
  */
@@ -182,6 +182,7 @@ export interface ToolPolicy {
182
182
  export type McpRpcMethod =
183
183
  | 'connect'
184
184
  | 'disconnect'
185
+ | 'reconnect'
185
186
  | 'listTools'
186
187
  | 'callTool'
187
188
  | 'listSessions'
@@ -223,6 +224,8 @@ export interface DisconnectParams {
223
224
  sessionId: string;
224
225
  }
225
226
 
227
+ export type ReconnectParams = ConnectParams;
228
+
226
229
  export interface SessionParams {
227
230
  sessionId: string;
228
231
  }
@@ -264,6 +267,7 @@ export interface GetToolPolicyParams {
264
267
  export type McpRpcParams =
265
268
  | ConnectParams
266
269
  | DisconnectParams
270
+ | ReconnectParams
267
271
  | SessionParams
268
272
  | CallToolParams
269
273
  | GetPromptParams