@mcp-ts/sdk 2.4.2 → 2.4.4
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.
- package/dist/adapters/agui-adapter.d.mts +3 -3
- package/dist/adapters/agui-adapter.d.ts +3 -3
- package/dist/adapters/agui-middleware.d.mts +3 -3
- package/dist/adapters/agui-middleware.d.ts +3 -3
- package/dist/adapters/ai-adapter.d.mts +3 -3
- package/dist/adapters/ai-adapter.d.ts +3 -3
- package/dist/adapters/langchain-adapter.d.mts +3 -3
- package/dist/adapters/langchain-adapter.d.ts +3 -3
- package/dist/adapters/mastra-adapter.d.mts +2 -2
- package/dist/adapters/mastra-adapter.d.ts +2 -2
- package/dist/bin/mcp-ts.js +5 -5
- package/dist/bin/mcp-ts.js.map +1 -1
- package/dist/bin/mcp-ts.mjs +5 -5
- package/dist/bin/mcp-ts.mjs.map +1 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/react.d.mts +4 -5
- package/dist/client/react.d.ts +4 -5
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +4 -5
- package/dist/client/vue.d.ts +4 -5
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{index-B8kJSrBJ.d.ts → index-CZk2gu2E.d.ts} +1 -1
- package/dist/{index-DiJsm_lK.d.mts → index-CkM3p0eE.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +99 -63
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +99 -63
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CWs-AE78.d.mts → multi-session-client-ChQrBZhF.d.mts} +21 -5
- package/dist/{multi-session-client-BluyCPo9.d.ts → multi-session-client-QOOPdEVp.d.ts} +21 -5
- package/dist/server/index.d.mts +4 -4
- package/dist/server/index.d.ts +4 -4
- package/dist/server/index.js +99 -63
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +99 -63
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +4 -4
- package/dist/shared/index.d.ts +4 -4
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{tool-router-CbG4Tum6.d.mts → tool-router-CGs3IDOJ.d.mts} +1 -1
- package/dist/{tool-router-ChIhPwgP.d.ts → tool-router-DQ-HrD7W.d.ts} +1 -1
- package/dist/{types-CjczQwNX.d.mts → types-Bf-7GOLW.d.mts} +0 -2
- package/dist/{types-CjczQwNX.d.ts → types-Bf-7GOLW.d.ts} +0 -2
- package/package.json +1 -1
- package/src/bin/mcp-ts.ts +5 -5
- package/src/client/react/use-mcp.ts +0 -1
- package/src/client/vue/use-mcp.ts +0 -1
- package/src/server/mcp/multi-session-client.ts +13 -0
- package/src/server/mcp/oauth-client.ts +82 -75
- package/src/server/storage/index.ts +8 -8
- package/src/shared/events.ts +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider } from './types-
|
|
1
|
+
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider } from './types-Bf-7GOLW.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';
|
|
@@ -184,12 +184,11 @@ declare class MCPClient {
|
|
|
184
184
|
*/
|
|
185
185
|
private getTransport;
|
|
186
186
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* This method is idempotent and safe to call multiple times
|
|
187
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
188
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
190
189
|
* @private
|
|
191
190
|
*/
|
|
192
|
-
private
|
|
191
|
+
private ensureSession;
|
|
193
192
|
/**
|
|
194
193
|
* Saves current session state to the session store
|
|
195
194
|
* Creates new session if it doesn't exist, updates if it does
|
|
@@ -264,6 +263,17 @@ declare class MCPClient {
|
|
|
264
263
|
* @throws {Error} When client is not connected
|
|
265
264
|
*/
|
|
266
265
|
readResource(uri: string): Promise<ReadResourceResult>;
|
|
266
|
+
/**
|
|
267
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
268
|
+
*
|
|
269
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
270
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
271
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
272
|
+
* and retries the request once.
|
|
273
|
+
*
|
|
274
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
275
|
+
*/
|
|
276
|
+
private withRetry;
|
|
267
277
|
/**
|
|
268
278
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
269
279
|
* Used for session restoration in serverless environments
|
|
@@ -534,6 +544,12 @@ declare class MultiSessionClient implements ToolClientProvider {
|
|
|
534
544
|
* or to route a tool call to the right client by `serverId`.
|
|
535
545
|
*/
|
|
536
546
|
getClients(): MCPClient[];
|
|
547
|
+
/**
|
|
548
|
+
* Removes and disconnects a single session by ID.
|
|
549
|
+
*
|
|
550
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
551
|
+
*/
|
|
552
|
+
removeSession(sessionId: string): Promise<boolean>;
|
|
537
553
|
/**
|
|
538
554
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
539
555
|
*
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider } from './types-
|
|
1
|
+
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider } from './types-Bf-7GOLW.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';
|
|
@@ -184,12 +184,11 @@ declare class MCPClient {
|
|
|
184
184
|
*/
|
|
185
185
|
private getTransport;
|
|
186
186
|
/**
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* This method is idempotent and safe to call multiple times
|
|
187
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
188
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
190
189
|
* @private
|
|
191
190
|
*/
|
|
192
|
-
private
|
|
191
|
+
private ensureSession;
|
|
193
192
|
/**
|
|
194
193
|
* Saves current session state to the session store
|
|
195
194
|
* Creates new session if it doesn't exist, updates if it does
|
|
@@ -264,6 +263,17 @@ declare class MCPClient {
|
|
|
264
263
|
* @throws {Error} When client is not connected
|
|
265
264
|
*/
|
|
266
265
|
readResource(uri: string): Promise<ReadResourceResult>;
|
|
266
|
+
/**
|
|
267
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
268
|
+
*
|
|
269
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
270
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
271
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
272
|
+
* and retries the request once.
|
|
273
|
+
*
|
|
274
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
275
|
+
*/
|
|
276
|
+
private withRetry;
|
|
267
277
|
/**
|
|
268
278
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
269
279
|
* Used for session restoration in serverless environments
|
|
@@ -534,6 +544,12 @@ declare class MultiSessionClient implements ToolClientProvider {
|
|
|
534
544
|
* or to route a tool call to the right client by `serverId`.
|
|
535
545
|
*/
|
|
536
546
|
getClients(): MCPClient[];
|
|
547
|
+
/**
|
|
548
|
+
* Removes and disconnects a single session by ID.
|
|
549
|
+
*
|
|
550
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
551
|
+
*/
|
|
552
|
+
removeSession(sessionId: string): Promise<boolean>;
|
|
537
553
|
/**
|
|
538
554
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
539
555
|
*
|
package/dist/server/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-
|
|
2
|
-
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-
|
|
1
|
+
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-ChQrBZhF.mjs';
|
|
2
|
+
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-ChQrBZhF.mjs';
|
|
3
3
|
export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.mjs';
|
|
4
|
-
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-
|
|
5
|
-
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-
|
|
4
|
+
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-Bf-7GOLW.mjs';
|
|
5
|
+
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-Bf-7GOLW.mjs';
|
|
6
6
|
export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
7
7
|
export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import '@modelcontextprotocol/sdk/client/auth.js';
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-
|
|
2
|
-
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-
|
|
1
|
+
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-QOOPdEVp.js';
|
|
2
|
+
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-QOOPdEVp.js';
|
|
3
3
|
export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.js';
|
|
4
|
-
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-
|
|
5
|
-
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-
|
|
4
|
+
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-Bf-7GOLW.js';
|
|
5
|
+
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-Bf-7GOLW.js';
|
|
6
6
|
export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
7
7
|
export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import '@modelcontextprotocol/sdk/client/auth.js';
|
package/dist/server/index.js
CHANGED
|
@@ -1734,12 +1734,12 @@ async function createStorage() {
|
|
|
1734
1734
|
}
|
|
1735
1735
|
if (type === "supabase") {
|
|
1736
1736
|
const url = process.env.SUPABASE_URL;
|
|
1737
|
-
const key = process.env.
|
|
1737
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1738
1738
|
if (!url || !key) {
|
|
1739
|
-
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and
|
|
1739
|
+
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and SUPABASE_SECRET_KEY.');
|
|
1740
1740
|
} else {
|
|
1741
|
-
if (!process.env.
|
|
1742
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1741
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1742
|
+
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "SUPABASE_SECRET_KEY" is recommended.');
|
|
1743
1743
|
}
|
|
1744
1744
|
try {
|
|
1745
1745
|
const { createClient } = await import('@supabase/supabase-js');
|
|
@@ -1794,13 +1794,13 @@ async function createStorage() {
|
|
|
1794
1794
|
console.log(`[mcp-ts][Storage] Auto-detection: "sqlite" (${process.env.MCP_TS_STORAGE_SQLITE_PATH})`);
|
|
1795
1795
|
return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
|
|
1796
1796
|
}
|
|
1797
|
-
if (process.env.SUPABASE_URL && (process.env.
|
|
1797
|
+
if (process.env.SUPABASE_URL && (process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY)) {
|
|
1798
1798
|
try {
|
|
1799
1799
|
const { createClient } = await import('@supabase/supabase-js');
|
|
1800
1800
|
const url = process.env.SUPABASE_URL;
|
|
1801
|
-
const key = process.env.
|
|
1802
|
-
if (!process.env.
|
|
1803
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1801
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1802
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1803
|
+
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "SUPABASE_SECRET_KEY" is recommended.');
|
|
1804
1804
|
}
|
|
1805
1805
|
const client = createClient(url, key);
|
|
1806
1806
|
console.log('[mcp-ts][Storage] Auto-detection: "supabase" (via SUPABASE_URL)');
|
|
@@ -2149,7 +2149,7 @@ var MCPClient = class {
|
|
|
2149
2149
|
* @param options - Client configuration options
|
|
2150
2150
|
*/
|
|
2151
2151
|
constructor(options) {
|
|
2152
|
-
__publicField(this, "client"
|
|
2152
|
+
__publicField(this, "client");
|
|
2153
2153
|
__publicField(this, "oauthProvider", null);
|
|
2154
2154
|
__publicField(this, "transport", null);
|
|
2155
2155
|
__publicField(this, "userId");
|
|
@@ -2190,6 +2190,21 @@ var MCPClient = class {
|
|
|
2190
2190
|
this.clientUri = options.clientUri;
|
|
2191
2191
|
this.logoUri = options.logoUri;
|
|
2192
2192
|
this.policyUri = options.policyUri;
|
|
2193
|
+
this.client = new index_js.Client(
|
|
2194
|
+
{
|
|
2195
|
+
name: MCP_CLIENT_NAME,
|
|
2196
|
+
version: MCP_CLIENT_VERSION
|
|
2197
|
+
},
|
|
2198
|
+
{
|
|
2199
|
+
capabilities: {
|
|
2200
|
+
extensions: {
|
|
2201
|
+
"io.modelcontextprotocol/ui": {
|
|
2202
|
+
mimeTypes: ["text/html+mcp"]
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
);
|
|
2193
2208
|
}
|
|
2194
2209
|
/**
|
|
2195
2210
|
* Emit a connection state change event
|
|
@@ -2300,7 +2315,6 @@ var MCPClient = class {
|
|
|
2300
2315
|
const response = await fetch(url, { ...init, signal });
|
|
2301
2316
|
const hasSessionHeader = init?.headers && new Headers(init.headers).has("mcp-session-id");
|
|
2302
2317
|
if (response.status === 404 && hasSessionHeader) {
|
|
2303
|
-
this.client = null;
|
|
2304
2318
|
throw new Error("MCP_SESSION_EXPIRED: Downstream session was not found on the server.");
|
|
2305
2319
|
}
|
|
2306
2320
|
return response;
|
|
@@ -2316,13 +2330,12 @@ var MCPClient = class {
|
|
|
2316
2330
|
}
|
|
2317
2331
|
}
|
|
2318
2332
|
/**
|
|
2319
|
-
*
|
|
2320
|
-
*
|
|
2321
|
-
* This method is idempotent and safe to call multiple times
|
|
2333
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
2334
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
2322
2335
|
* @private
|
|
2323
2336
|
*/
|
|
2324
|
-
async
|
|
2325
|
-
if (this.
|
|
2337
|
+
async ensureSession() {
|
|
2338
|
+
if (this.oauthProvider) {
|
|
2326
2339
|
return;
|
|
2327
2340
|
}
|
|
2328
2341
|
this.emitStateChange("INITIALIZING");
|
|
@@ -2365,23 +2378,6 @@ var MCPClient = class {
|
|
|
2365
2378
|
}
|
|
2366
2379
|
});
|
|
2367
2380
|
}
|
|
2368
|
-
if (!this.client) {
|
|
2369
|
-
this.client = new index_js.Client(
|
|
2370
|
-
{
|
|
2371
|
-
name: MCP_CLIENT_NAME,
|
|
2372
|
-
version: MCP_CLIENT_VERSION
|
|
2373
|
-
},
|
|
2374
|
-
{
|
|
2375
|
-
capabilities: {
|
|
2376
|
-
extensions: {
|
|
2377
|
-
"io.modelcontextprotocol/ui": {
|
|
2378
|
-
mimeTypes: ["text/html+mcp"]
|
|
2379
|
-
}
|
|
2380
|
-
}
|
|
2381
|
-
}
|
|
2382
|
-
}
|
|
2383
|
-
);
|
|
2384
|
-
}
|
|
2385
2381
|
if (existingSession === null) {
|
|
2386
2382
|
existingSession = await sessions.get(this.userId, this.sessionId);
|
|
2387
2383
|
}
|
|
@@ -2498,17 +2494,16 @@ var MCPClient = class {
|
|
|
2498
2494
|
* @throws {Error} When connection fails for other reasons
|
|
2499
2495
|
*/
|
|
2500
2496
|
async connect() {
|
|
2501
|
-
if (this.client
|
|
2497
|
+
if (this.client.transport) {
|
|
2502
2498
|
this.transport = null;
|
|
2503
2499
|
try {
|
|
2504
2500
|
await this.client.close();
|
|
2505
2501
|
} catch {
|
|
2506
2502
|
}
|
|
2507
|
-
this.client = null;
|
|
2508
2503
|
}
|
|
2509
|
-
await this.
|
|
2510
|
-
if (!this.
|
|
2511
|
-
const error = "
|
|
2504
|
+
await this.ensureSession();
|
|
2505
|
+
if (!this.oauthProvider) {
|
|
2506
|
+
const error = "OAuth provider not initialized";
|
|
2512
2507
|
this.emitError(error, "connection");
|
|
2513
2508
|
this.emitStateChange("FAILED");
|
|
2514
2509
|
throw new Error(error);
|
|
@@ -2575,7 +2570,7 @@ var MCPClient = class {
|
|
|
2575
2570
|
async finishAuth(authCode, state) {
|
|
2576
2571
|
this.emitStateChange("AUTHENTICATING");
|
|
2577
2572
|
this.emitProgress("Exchanging authorization code for tokens...");
|
|
2578
|
-
await this.
|
|
2573
|
+
await this.ensureSession();
|
|
2579
2574
|
if (!this.oauthProvider) {
|
|
2580
2575
|
const error = "OAuth provider not initialized";
|
|
2581
2576
|
this.emitError(error, "auth");
|
|
@@ -2681,7 +2676,9 @@ var MCPClient = class {
|
|
|
2681
2676
|
method: "tools/list",
|
|
2682
2677
|
params: {}
|
|
2683
2678
|
};
|
|
2684
|
-
const result = await this.
|
|
2679
|
+
const result = await this.withRetry(
|
|
2680
|
+
() => this.client.request(request, types_js.ListToolsResultSchema)
|
|
2681
|
+
);
|
|
2685
2682
|
if (this.serverId) {
|
|
2686
2683
|
this._onConnectionEvent.fire({
|
|
2687
2684
|
type: "tools_discovered",
|
|
@@ -2721,7 +2718,9 @@ var MCPClient = class {
|
|
|
2721
2718
|
}
|
|
2722
2719
|
};
|
|
2723
2720
|
try {
|
|
2724
|
-
const result = await this.
|
|
2721
|
+
const result = await this.withRetry(
|
|
2722
|
+
() => this.client.request(request, types_js.CallToolResultSchema)
|
|
2723
|
+
);
|
|
2725
2724
|
this._onObservabilityEvent.fire({
|
|
2726
2725
|
type: "mcp:client:tool_call",
|
|
2727
2726
|
level: "info",
|
|
@@ -2773,7 +2772,9 @@ var MCPClient = class {
|
|
|
2773
2772
|
method: "prompts/list",
|
|
2774
2773
|
params: {}
|
|
2775
2774
|
};
|
|
2776
|
-
const result = await this.
|
|
2775
|
+
const result = await this.withRetry(
|
|
2776
|
+
() => this.client.request(request, types_js.ListPromptsResultSchema)
|
|
2777
|
+
);
|
|
2777
2778
|
this.emitStateChange("READY");
|
|
2778
2779
|
this.emitProgress(`Discovered ${result.prompts.length} prompts`);
|
|
2779
2780
|
return result;
|
|
@@ -2802,7 +2803,9 @@ var MCPClient = class {
|
|
|
2802
2803
|
arguments: args
|
|
2803
2804
|
}
|
|
2804
2805
|
};
|
|
2805
|
-
return await this.
|
|
2806
|
+
return await this.withRetry(
|
|
2807
|
+
() => this.client.request(request, types_js.GetPromptResultSchema)
|
|
2808
|
+
);
|
|
2806
2809
|
}
|
|
2807
2810
|
/**
|
|
2808
2811
|
* Lists all available resources from the connected MCP server
|
|
@@ -2819,7 +2822,9 @@ var MCPClient = class {
|
|
|
2819
2822
|
method: "resources/list",
|
|
2820
2823
|
params: {}
|
|
2821
2824
|
};
|
|
2822
|
-
const result = await this.
|
|
2825
|
+
const result = await this.withRetry(
|
|
2826
|
+
() => this.client.request(request, types_js.ListResourcesResultSchema)
|
|
2827
|
+
);
|
|
2823
2828
|
this.emitStateChange("READY");
|
|
2824
2829
|
this.emitProgress(`Discovered ${result.resources.length} resources`);
|
|
2825
2830
|
return result;
|
|
@@ -2846,7 +2851,35 @@ var MCPClient = class {
|
|
|
2846
2851
|
uri
|
|
2847
2852
|
}
|
|
2848
2853
|
};
|
|
2849
|
-
return await this.
|
|
2854
|
+
return await this.withRetry(
|
|
2855
|
+
() => this.client.request(request, types_js.ReadResourceResultSchema)
|
|
2856
|
+
);
|
|
2857
|
+
}
|
|
2858
|
+
/**
|
|
2859
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
2860
|
+
*
|
|
2861
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
2862
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
2863
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
2864
|
+
* and retries the request once.
|
|
2865
|
+
*
|
|
2866
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
2867
|
+
*/
|
|
2868
|
+
async withRetry(fn) {
|
|
2869
|
+
try {
|
|
2870
|
+
return await fn();
|
|
2871
|
+
} catch (error) {
|
|
2872
|
+
if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
|
|
2873
|
+
if (this.client.transport) {
|
|
2874
|
+
try {
|
|
2875
|
+
await this.client.close();
|
|
2876
|
+
} catch {
|
|
2877
|
+
}
|
|
2878
|
+
this.transport = null;
|
|
2879
|
+
}
|
|
2880
|
+
await this.reconnect();
|
|
2881
|
+
return await fn();
|
|
2882
|
+
}
|
|
2850
2883
|
}
|
|
2851
2884
|
/**
|
|
2852
2885
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
@@ -2855,20 +2888,9 @@ var MCPClient = class {
|
|
|
2855
2888
|
* @throws {Error} When OAuth provider is not initialized
|
|
2856
2889
|
*/
|
|
2857
2890
|
async reconnect() {
|
|
2858
|
-
await this.
|
|
2859
|
-
if (!this.oauthProvider)
|
|
2860
|
-
|
|
2861
|
-
}
|
|
2862
|
-
this.client = new index_js.Client(
|
|
2863
|
-
{
|
|
2864
|
-
name: MCP_CLIENT_NAME,
|
|
2865
|
-
version: MCP_CLIENT_VERSION
|
|
2866
|
-
},
|
|
2867
|
-
{ capabilities: {} }
|
|
2868
|
-
);
|
|
2869
|
-
const tt = this.transportType || "streamable-http";
|
|
2870
|
-
this.transport = this.getTransport(tt);
|
|
2871
|
-
await this.client.connect(this.transport);
|
|
2891
|
+
await this.ensureSession();
|
|
2892
|
+
if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
|
|
2893
|
+
await this.connect();
|
|
2872
2894
|
}
|
|
2873
2895
|
/**
|
|
2874
2896
|
* Completely removes the session from Redis including all OAuth data
|
|
@@ -2876,7 +2898,7 @@ var MCPClient = class {
|
|
|
2876
2898
|
*/
|
|
2877
2899
|
async clearSession() {
|
|
2878
2900
|
try {
|
|
2879
|
-
await this.
|
|
2901
|
+
await this.ensureSession();
|
|
2880
2902
|
} catch (error) {
|
|
2881
2903
|
console.warn("[MCPClient] Initialization failed during clearSession:", error);
|
|
2882
2904
|
}
|
|
@@ -2891,7 +2913,7 @@ var MCPClient = class {
|
|
|
2891
2913
|
* @returns True if connected, false otherwise
|
|
2892
2914
|
*/
|
|
2893
2915
|
isConnected() {
|
|
2894
|
-
return this.client !==
|
|
2916
|
+
return this.client.transport !== void 0;
|
|
2895
2917
|
}
|
|
2896
2918
|
/**
|
|
2897
2919
|
* Disconnects from the MCP server and cleans up resources.
|
|
@@ -2909,10 +2931,12 @@ var MCPClient = class {
|
|
|
2909
2931
|
} catch {
|
|
2910
2932
|
}
|
|
2911
2933
|
}
|
|
2912
|
-
if (this.client) {
|
|
2913
|
-
|
|
2934
|
+
if (this.client.transport) {
|
|
2935
|
+
try {
|
|
2936
|
+
await this.client.close();
|
|
2937
|
+
} catch {
|
|
2938
|
+
}
|
|
2914
2939
|
}
|
|
2915
|
-
this.client = null;
|
|
2916
2940
|
this.oauthProvider = null;
|
|
2917
2941
|
this.transport = null;
|
|
2918
2942
|
if (this.serverId) {
|
|
@@ -3055,6 +3079,18 @@ var MultiSessionClient = class {
|
|
|
3055
3079
|
getClients() {
|
|
3056
3080
|
return this.clients;
|
|
3057
3081
|
}
|
|
3082
|
+
/**
|
|
3083
|
+
* Removes and disconnects a single session by ID.
|
|
3084
|
+
*
|
|
3085
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
3086
|
+
*/
|
|
3087
|
+
async removeSession(sessionId) {
|
|
3088
|
+
const idx = this.clients.findIndex((c) => c.getSessionId() === sessionId);
|
|
3089
|
+
if (idx === -1) return false;
|
|
3090
|
+
const [client] = this.clients.splice(idx, 1);
|
|
3091
|
+
await client.disconnect();
|
|
3092
|
+
return true;
|
|
3093
|
+
}
|
|
3058
3094
|
/**
|
|
3059
3095
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
3060
3096
|
*
|