@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
package/dist/index.mjs
CHANGED
|
@@ -1670,12 +1670,12 @@ async function createStorage() {
|
|
|
1670
1670
|
}
|
|
1671
1671
|
if (type === "supabase") {
|
|
1672
1672
|
const url = process.env.SUPABASE_URL;
|
|
1673
|
-
const key = process.env.
|
|
1673
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1674
1674
|
if (!url || !key) {
|
|
1675
|
-
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and
|
|
1675
|
+
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and SUPABASE_SECRET_KEY.');
|
|
1676
1676
|
} else {
|
|
1677
|
-
if (!process.env.
|
|
1678
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1677
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1678
|
+
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.');
|
|
1679
1679
|
}
|
|
1680
1680
|
try {
|
|
1681
1681
|
const { createClient } = await import('@supabase/supabase-js');
|
|
@@ -1730,13 +1730,13 @@ async function createStorage() {
|
|
|
1730
1730
|
console.log(`[mcp-ts][Storage] Auto-detection: "sqlite" (${process.env.MCP_TS_STORAGE_SQLITE_PATH})`);
|
|
1731
1731
|
return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
|
|
1732
1732
|
}
|
|
1733
|
-
if (process.env.SUPABASE_URL && (process.env.
|
|
1733
|
+
if (process.env.SUPABASE_URL && (process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY)) {
|
|
1734
1734
|
try {
|
|
1735
1735
|
const { createClient } = await import('@supabase/supabase-js');
|
|
1736
1736
|
const url = process.env.SUPABASE_URL;
|
|
1737
|
-
const key = process.env.
|
|
1738
|
-
if (!process.env.
|
|
1739
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1737
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1738
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1739
|
+
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.');
|
|
1740
1740
|
}
|
|
1741
1741
|
const client = createClient(url, key);
|
|
1742
1742
|
console.log('[mcp-ts][Storage] Auto-detection: "supabase" (via SUPABASE_URL)');
|
|
@@ -2151,7 +2151,7 @@ var MCPClient = class {
|
|
|
2151
2151
|
* @param options - Client configuration options
|
|
2152
2152
|
*/
|
|
2153
2153
|
constructor(options) {
|
|
2154
|
-
__publicField(this, "client"
|
|
2154
|
+
__publicField(this, "client");
|
|
2155
2155
|
__publicField(this, "oauthProvider", null);
|
|
2156
2156
|
__publicField(this, "transport", null);
|
|
2157
2157
|
__publicField(this, "userId");
|
|
@@ -2192,6 +2192,21 @@ var MCPClient = class {
|
|
|
2192
2192
|
this.clientUri = options.clientUri;
|
|
2193
2193
|
this.logoUri = options.logoUri;
|
|
2194
2194
|
this.policyUri = options.policyUri;
|
|
2195
|
+
this.client = new Client(
|
|
2196
|
+
{
|
|
2197
|
+
name: MCP_CLIENT_NAME,
|
|
2198
|
+
version: MCP_CLIENT_VERSION
|
|
2199
|
+
},
|
|
2200
|
+
{
|
|
2201
|
+
capabilities: {
|
|
2202
|
+
extensions: {
|
|
2203
|
+
"io.modelcontextprotocol/ui": {
|
|
2204
|
+
mimeTypes: ["text/html+mcp"]
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
}
|
|
2208
|
+
}
|
|
2209
|
+
);
|
|
2195
2210
|
}
|
|
2196
2211
|
/**
|
|
2197
2212
|
* Emit a connection state change event
|
|
@@ -2302,7 +2317,6 @@ var MCPClient = class {
|
|
|
2302
2317
|
const response = await fetch(url, { ...init, signal });
|
|
2303
2318
|
const hasSessionHeader = init?.headers && new Headers(init.headers).has("mcp-session-id");
|
|
2304
2319
|
if (response.status === 404 && hasSessionHeader) {
|
|
2305
|
-
this.client = null;
|
|
2306
2320
|
throw new Error("MCP_SESSION_EXPIRED: Downstream session was not found on the server.");
|
|
2307
2321
|
}
|
|
2308
2322
|
return response;
|
|
@@ -2318,13 +2332,12 @@ var MCPClient = class {
|
|
|
2318
2332
|
}
|
|
2319
2333
|
}
|
|
2320
2334
|
/**
|
|
2321
|
-
*
|
|
2322
|
-
*
|
|
2323
|
-
* This method is idempotent and safe to call multiple times
|
|
2335
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
2336
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
2324
2337
|
* @private
|
|
2325
2338
|
*/
|
|
2326
|
-
async
|
|
2327
|
-
if (this.
|
|
2339
|
+
async ensureSession() {
|
|
2340
|
+
if (this.oauthProvider) {
|
|
2328
2341
|
return;
|
|
2329
2342
|
}
|
|
2330
2343
|
this.emitStateChange("INITIALIZING");
|
|
@@ -2367,23 +2380,6 @@ var MCPClient = class {
|
|
|
2367
2380
|
}
|
|
2368
2381
|
});
|
|
2369
2382
|
}
|
|
2370
|
-
if (!this.client) {
|
|
2371
|
-
this.client = new Client(
|
|
2372
|
-
{
|
|
2373
|
-
name: MCP_CLIENT_NAME,
|
|
2374
|
-
version: MCP_CLIENT_VERSION
|
|
2375
|
-
},
|
|
2376
|
-
{
|
|
2377
|
-
capabilities: {
|
|
2378
|
-
extensions: {
|
|
2379
|
-
"io.modelcontextprotocol/ui": {
|
|
2380
|
-
mimeTypes: ["text/html+mcp"]
|
|
2381
|
-
}
|
|
2382
|
-
}
|
|
2383
|
-
}
|
|
2384
|
-
}
|
|
2385
|
-
);
|
|
2386
|
-
}
|
|
2387
2383
|
if (existingSession === null) {
|
|
2388
2384
|
existingSession = await sessions.get(this.userId, this.sessionId);
|
|
2389
2385
|
}
|
|
@@ -2500,17 +2496,16 @@ var MCPClient = class {
|
|
|
2500
2496
|
* @throws {Error} When connection fails for other reasons
|
|
2501
2497
|
*/
|
|
2502
2498
|
async connect() {
|
|
2503
|
-
if (this.client
|
|
2499
|
+
if (this.client.transport) {
|
|
2504
2500
|
this.transport = null;
|
|
2505
2501
|
try {
|
|
2506
2502
|
await this.client.close();
|
|
2507
2503
|
} catch {
|
|
2508
2504
|
}
|
|
2509
|
-
this.client = null;
|
|
2510
2505
|
}
|
|
2511
|
-
await this.
|
|
2512
|
-
if (!this.
|
|
2513
|
-
const error = "
|
|
2506
|
+
await this.ensureSession();
|
|
2507
|
+
if (!this.oauthProvider) {
|
|
2508
|
+
const error = "OAuth provider not initialized";
|
|
2514
2509
|
this.emitError(error, "connection");
|
|
2515
2510
|
this.emitStateChange("FAILED");
|
|
2516
2511
|
throw new Error(error);
|
|
@@ -2577,7 +2572,7 @@ var MCPClient = class {
|
|
|
2577
2572
|
async finishAuth(authCode, state) {
|
|
2578
2573
|
this.emitStateChange("AUTHENTICATING");
|
|
2579
2574
|
this.emitProgress("Exchanging authorization code for tokens...");
|
|
2580
|
-
await this.
|
|
2575
|
+
await this.ensureSession();
|
|
2581
2576
|
if (!this.oauthProvider) {
|
|
2582
2577
|
const error = "OAuth provider not initialized";
|
|
2583
2578
|
this.emitError(error, "auth");
|
|
@@ -2683,7 +2678,9 @@ var MCPClient = class {
|
|
|
2683
2678
|
method: "tools/list",
|
|
2684
2679
|
params: {}
|
|
2685
2680
|
};
|
|
2686
|
-
const result = await this.
|
|
2681
|
+
const result = await this.withRetry(
|
|
2682
|
+
() => this.client.request(request, ListToolsResultSchema)
|
|
2683
|
+
);
|
|
2687
2684
|
if (this.serverId) {
|
|
2688
2685
|
this._onConnectionEvent.fire({
|
|
2689
2686
|
type: "tools_discovered",
|
|
@@ -2723,7 +2720,9 @@ var MCPClient = class {
|
|
|
2723
2720
|
}
|
|
2724
2721
|
};
|
|
2725
2722
|
try {
|
|
2726
|
-
const result = await this.
|
|
2723
|
+
const result = await this.withRetry(
|
|
2724
|
+
() => this.client.request(request, CallToolResultSchema)
|
|
2725
|
+
);
|
|
2727
2726
|
this._onObservabilityEvent.fire({
|
|
2728
2727
|
type: "mcp:client:tool_call",
|
|
2729
2728
|
level: "info",
|
|
@@ -2775,7 +2774,9 @@ var MCPClient = class {
|
|
|
2775
2774
|
method: "prompts/list",
|
|
2776
2775
|
params: {}
|
|
2777
2776
|
};
|
|
2778
|
-
const result = await this.
|
|
2777
|
+
const result = await this.withRetry(
|
|
2778
|
+
() => this.client.request(request, ListPromptsResultSchema)
|
|
2779
|
+
);
|
|
2779
2780
|
this.emitStateChange("READY");
|
|
2780
2781
|
this.emitProgress(`Discovered ${result.prompts.length} prompts`);
|
|
2781
2782
|
return result;
|
|
@@ -2804,7 +2805,9 @@ var MCPClient = class {
|
|
|
2804
2805
|
arguments: args
|
|
2805
2806
|
}
|
|
2806
2807
|
};
|
|
2807
|
-
return await this.
|
|
2808
|
+
return await this.withRetry(
|
|
2809
|
+
() => this.client.request(request, GetPromptResultSchema)
|
|
2810
|
+
);
|
|
2808
2811
|
}
|
|
2809
2812
|
/**
|
|
2810
2813
|
* Lists all available resources from the connected MCP server
|
|
@@ -2821,7 +2824,9 @@ var MCPClient = class {
|
|
|
2821
2824
|
method: "resources/list",
|
|
2822
2825
|
params: {}
|
|
2823
2826
|
};
|
|
2824
|
-
const result = await this.
|
|
2827
|
+
const result = await this.withRetry(
|
|
2828
|
+
() => this.client.request(request, ListResourcesResultSchema)
|
|
2829
|
+
);
|
|
2825
2830
|
this.emitStateChange("READY");
|
|
2826
2831
|
this.emitProgress(`Discovered ${result.resources.length} resources`);
|
|
2827
2832
|
return result;
|
|
@@ -2848,7 +2853,35 @@ var MCPClient = class {
|
|
|
2848
2853
|
uri
|
|
2849
2854
|
}
|
|
2850
2855
|
};
|
|
2851
|
-
return await this.
|
|
2856
|
+
return await this.withRetry(
|
|
2857
|
+
() => this.client.request(request, ReadResourceResultSchema)
|
|
2858
|
+
);
|
|
2859
|
+
}
|
|
2860
|
+
/**
|
|
2861
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
2862
|
+
*
|
|
2863
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
2864
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
2865
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
2866
|
+
* and retries the request once.
|
|
2867
|
+
*
|
|
2868
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
2869
|
+
*/
|
|
2870
|
+
async withRetry(fn) {
|
|
2871
|
+
try {
|
|
2872
|
+
return await fn();
|
|
2873
|
+
} catch (error) {
|
|
2874
|
+
if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
|
|
2875
|
+
if (this.client.transport) {
|
|
2876
|
+
try {
|
|
2877
|
+
await this.client.close();
|
|
2878
|
+
} catch {
|
|
2879
|
+
}
|
|
2880
|
+
this.transport = null;
|
|
2881
|
+
}
|
|
2882
|
+
await this.reconnect();
|
|
2883
|
+
return await fn();
|
|
2884
|
+
}
|
|
2852
2885
|
}
|
|
2853
2886
|
/**
|
|
2854
2887
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
@@ -2857,20 +2890,9 @@ var MCPClient = class {
|
|
|
2857
2890
|
* @throws {Error} When OAuth provider is not initialized
|
|
2858
2891
|
*/
|
|
2859
2892
|
async reconnect() {
|
|
2860
|
-
await this.
|
|
2861
|
-
if (!this.oauthProvider)
|
|
2862
|
-
|
|
2863
|
-
}
|
|
2864
|
-
this.client = new Client(
|
|
2865
|
-
{
|
|
2866
|
-
name: MCP_CLIENT_NAME,
|
|
2867
|
-
version: MCP_CLIENT_VERSION
|
|
2868
|
-
},
|
|
2869
|
-
{ capabilities: {} }
|
|
2870
|
-
);
|
|
2871
|
-
const tt = this.transportType || "streamable-http";
|
|
2872
|
-
this.transport = this.getTransport(tt);
|
|
2873
|
-
await this.client.connect(this.transport);
|
|
2893
|
+
await this.ensureSession();
|
|
2894
|
+
if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
|
|
2895
|
+
await this.connect();
|
|
2874
2896
|
}
|
|
2875
2897
|
/**
|
|
2876
2898
|
* Completely removes the session from Redis including all OAuth data
|
|
@@ -2878,7 +2900,7 @@ var MCPClient = class {
|
|
|
2878
2900
|
*/
|
|
2879
2901
|
async clearSession() {
|
|
2880
2902
|
try {
|
|
2881
|
-
await this.
|
|
2903
|
+
await this.ensureSession();
|
|
2882
2904
|
} catch (error) {
|
|
2883
2905
|
console.warn("[MCPClient] Initialization failed during clearSession:", error);
|
|
2884
2906
|
}
|
|
@@ -2893,7 +2915,7 @@ var MCPClient = class {
|
|
|
2893
2915
|
* @returns True if connected, false otherwise
|
|
2894
2916
|
*/
|
|
2895
2917
|
isConnected() {
|
|
2896
|
-
return this.client !==
|
|
2918
|
+
return this.client.transport !== void 0;
|
|
2897
2919
|
}
|
|
2898
2920
|
/**
|
|
2899
2921
|
* Disconnects from the MCP server and cleans up resources.
|
|
@@ -2911,10 +2933,12 @@ var MCPClient = class {
|
|
|
2911
2933
|
} catch {
|
|
2912
2934
|
}
|
|
2913
2935
|
}
|
|
2914
|
-
if (this.client) {
|
|
2915
|
-
|
|
2936
|
+
if (this.client.transport) {
|
|
2937
|
+
try {
|
|
2938
|
+
await this.client.close();
|
|
2939
|
+
} catch {
|
|
2940
|
+
}
|
|
2916
2941
|
}
|
|
2917
|
-
this.client = null;
|
|
2918
2942
|
this.oauthProvider = null;
|
|
2919
2943
|
this.transport = null;
|
|
2920
2944
|
if (this.serverId) {
|
|
@@ -3056,6 +3080,18 @@ var MultiSessionClient = class {
|
|
|
3056
3080
|
getClients() {
|
|
3057
3081
|
return this.clients;
|
|
3058
3082
|
}
|
|
3083
|
+
/**
|
|
3084
|
+
* Removes and disconnects a single session by ID.
|
|
3085
|
+
*
|
|
3086
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
3087
|
+
*/
|
|
3088
|
+
async removeSession(sessionId) {
|
|
3089
|
+
const idx = this.clients.findIndex((c) => c.getSessionId() === sessionId);
|
|
3090
|
+
if (idx === -1) return false;
|
|
3091
|
+
const [client] = this.clients.splice(idx, 1);
|
|
3092
|
+
await client.disconnect();
|
|
3093
|
+
return true;
|
|
3094
|
+
}
|
|
3059
3095
|
/**
|
|
3060
3096
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
3061
3097
|
*
|