@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.js
CHANGED
|
@@ -1741,12 +1741,12 @@ async function createStorage() {
|
|
|
1741
1741
|
}
|
|
1742
1742
|
if (type === "supabase") {
|
|
1743
1743
|
const url = process.env.SUPABASE_URL;
|
|
1744
|
-
const key = process.env.
|
|
1744
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1745
1745
|
if (!url || !key) {
|
|
1746
|
-
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and
|
|
1746
|
+
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and SUPABASE_SECRET_KEY.');
|
|
1747
1747
|
} else {
|
|
1748
|
-
if (!process.env.
|
|
1749
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1748
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1749
|
+
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.');
|
|
1750
1750
|
}
|
|
1751
1751
|
try {
|
|
1752
1752
|
const { createClient } = await import('@supabase/supabase-js');
|
|
@@ -1801,13 +1801,13 @@ async function createStorage() {
|
|
|
1801
1801
|
console.log(`[mcp-ts][Storage] Auto-detection: "sqlite" (${process.env.MCP_TS_STORAGE_SQLITE_PATH})`);
|
|
1802
1802
|
return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
|
|
1803
1803
|
}
|
|
1804
|
-
if (process.env.SUPABASE_URL && (process.env.
|
|
1804
|
+
if (process.env.SUPABASE_URL && (process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY)) {
|
|
1805
1805
|
try {
|
|
1806
1806
|
const { createClient } = await import('@supabase/supabase-js');
|
|
1807
1807
|
const url = process.env.SUPABASE_URL;
|
|
1808
|
-
const key = process.env.
|
|
1809
|
-
if (!process.env.
|
|
1810
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1808
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1809
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1810
|
+
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.');
|
|
1811
1811
|
}
|
|
1812
1812
|
const client = createClient(url, key);
|
|
1813
1813
|
console.log('[mcp-ts][Storage] Auto-detection: "supabase" (via SUPABASE_URL)');
|
|
@@ -2224,7 +2224,7 @@ var MCPClient = class {
|
|
|
2224
2224
|
* @param options - Client configuration options
|
|
2225
2225
|
*/
|
|
2226
2226
|
constructor(options) {
|
|
2227
|
-
__publicField(this, "client"
|
|
2227
|
+
__publicField(this, "client");
|
|
2228
2228
|
__publicField(this, "oauthProvider", null);
|
|
2229
2229
|
__publicField(this, "transport", null);
|
|
2230
2230
|
__publicField(this, "userId");
|
|
@@ -2265,6 +2265,21 @@ var MCPClient = class {
|
|
|
2265
2265
|
this.clientUri = options.clientUri;
|
|
2266
2266
|
this.logoUri = options.logoUri;
|
|
2267
2267
|
this.policyUri = options.policyUri;
|
|
2268
|
+
this.client = new index_js.Client(
|
|
2269
|
+
{
|
|
2270
|
+
name: MCP_CLIENT_NAME,
|
|
2271
|
+
version: MCP_CLIENT_VERSION
|
|
2272
|
+
},
|
|
2273
|
+
{
|
|
2274
|
+
capabilities: {
|
|
2275
|
+
extensions: {
|
|
2276
|
+
"io.modelcontextprotocol/ui": {
|
|
2277
|
+
mimeTypes: ["text/html+mcp"]
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
);
|
|
2268
2283
|
}
|
|
2269
2284
|
/**
|
|
2270
2285
|
* Emit a connection state change event
|
|
@@ -2375,7 +2390,6 @@ var MCPClient = class {
|
|
|
2375
2390
|
const response = await fetch(url, { ...init, signal });
|
|
2376
2391
|
const hasSessionHeader = init?.headers && new Headers(init.headers).has("mcp-session-id");
|
|
2377
2392
|
if (response.status === 404 && hasSessionHeader) {
|
|
2378
|
-
this.client = null;
|
|
2379
2393
|
throw new Error("MCP_SESSION_EXPIRED: Downstream session was not found on the server.");
|
|
2380
2394
|
}
|
|
2381
2395
|
return response;
|
|
@@ -2391,13 +2405,12 @@ var MCPClient = class {
|
|
|
2391
2405
|
}
|
|
2392
2406
|
}
|
|
2393
2407
|
/**
|
|
2394
|
-
*
|
|
2395
|
-
*
|
|
2396
|
-
* This method is idempotent and safe to call multiple times
|
|
2408
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
2409
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
2397
2410
|
* @private
|
|
2398
2411
|
*/
|
|
2399
|
-
async
|
|
2400
|
-
if (this.
|
|
2412
|
+
async ensureSession() {
|
|
2413
|
+
if (this.oauthProvider) {
|
|
2401
2414
|
return;
|
|
2402
2415
|
}
|
|
2403
2416
|
this.emitStateChange("INITIALIZING");
|
|
@@ -2440,23 +2453,6 @@ var MCPClient = class {
|
|
|
2440
2453
|
}
|
|
2441
2454
|
});
|
|
2442
2455
|
}
|
|
2443
|
-
if (!this.client) {
|
|
2444
|
-
this.client = new index_js.Client(
|
|
2445
|
-
{
|
|
2446
|
-
name: MCP_CLIENT_NAME,
|
|
2447
|
-
version: MCP_CLIENT_VERSION
|
|
2448
|
-
},
|
|
2449
|
-
{
|
|
2450
|
-
capabilities: {
|
|
2451
|
-
extensions: {
|
|
2452
|
-
"io.modelcontextprotocol/ui": {
|
|
2453
|
-
mimeTypes: ["text/html+mcp"]
|
|
2454
|
-
}
|
|
2455
|
-
}
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
);
|
|
2459
|
-
}
|
|
2460
2456
|
if (existingSession === null) {
|
|
2461
2457
|
existingSession = await sessions.get(this.userId, this.sessionId);
|
|
2462
2458
|
}
|
|
@@ -2573,17 +2569,16 @@ var MCPClient = class {
|
|
|
2573
2569
|
* @throws {Error} When connection fails for other reasons
|
|
2574
2570
|
*/
|
|
2575
2571
|
async connect() {
|
|
2576
|
-
if (this.client
|
|
2572
|
+
if (this.client.transport) {
|
|
2577
2573
|
this.transport = null;
|
|
2578
2574
|
try {
|
|
2579
2575
|
await this.client.close();
|
|
2580
2576
|
} catch {
|
|
2581
2577
|
}
|
|
2582
|
-
this.client = null;
|
|
2583
2578
|
}
|
|
2584
|
-
await this.
|
|
2585
|
-
if (!this.
|
|
2586
|
-
const error = "
|
|
2579
|
+
await this.ensureSession();
|
|
2580
|
+
if (!this.oauthProvider) {
|
|
2581
|
+
const error = "OAuth provider not initialized";
|
|
2587
2582
|
this.emitError(error, "connection");
|
|
2588
2583
|
this.emitStateChange("FAILED");
|
|
2589
2584
|
throw new Error(error);
|
|
@@ -2650,7 +2645,7 @@ var MCPClient = class {
|
|
|
2650
2645
|
async finishAuth(authCode, state) {
|
|
2651
2646
|
this.emitStateChange("AUTHENTICATING");
|
|
2652
2647
|
this.emitProgress("Exchanging authorization code for tokens...");
|
|
2653
|
-
await this.
|
|
2648
|
+
await this.ensureSession();
|
|
2654
2649
|
if (!this.oauthProvider) {
|
|
2655
2650
|
const error = "OAuth provider not initialized";
|
|
2656
2651
|
this.emitError(error, "auth");
|
|
@@ -2756,7 +2751,9 @@ var MCPClient = class {
|
|
|
2756
2751
|
method: "tools/list",
|
|
2757
2752
|
params: {}
|
|
2758
2753
|
};
|
|
2759
|
-
const result = await this.
|
|
2754
|
+
const result = await this.withRetry(
|
|
2755
|
+
() => this.client.request(request, types_js.ListToolsResultSchema)
|
|
2756
|
+
);
|
|
2760
2757
|
if (this.serverId) {
|
|
2761
2758
|
this._onConnectionEvent.fire({
|
|
2762
2759
|
type: "tools_discovered",
|
|
@@ -2796,7 +2793,9 @@ var MCPClient = class {
|
|
|
2796
2793
|
}
|
|
2797
2794
|
};
|
|
2798
2795
|
try {
|
|
2799
|
-
const result = await this.
|
|
2796
|
+
const result = await this.withRetry(
|
|
2797
|
+
() => this.client.request(request, types_js.CallToolResultSchema)
|
|
2798
|
+
);
|
|
2800
2799
|
this._onObservabilityEvent.fire({
|
|
2801
2800
|
type: "mcp:client:tool_call",
|
|
2802
2801
|
level: "info",
|
|
@@ -2848,7 +2847,9 @@ var MCPClient = class {
|
|
|
2848
2847
|
method: "prompts/list",
|
|
2849
2848
|
params: {}
|
|
2850
2849
|
};
|
|
2851
|
-
const result = await this.
|
|
2850
|
+
const result = await this.withRetry(
|
|
2851
|
+
() => this.client.request(request, types_js.ListPromptsResultSchema)
|
|
2852
|
+
);
|
|
2852
2853
|
this.emitStateChange("READY");
|
|
2853
2854
|
this.emitProgress(`Discovered ${result.prompts.length} prompts`);
|
|
2854
2855
|
return result;
|
|
@@ -2877,7 +2878,9 @@ var MCPClient = class {
|
|
|
2877
2878
|
arguments: args
|
|
2878
2879
|
}
|
|
2879
2880
|
};
|
|
2880
|
-
return await this.
|
|
2881
|
+
return await this.withRetry(
|
|
2882
|
+
() => this.client.request(request, types_js.GetPromptResultSchema)
|
|
2883
|
+
);
|
|
2881
2884
|
}
|
|
2882
2885
|
/**
|
|
2883
2886
|
* Lists all available resources from the connected MCP server
|
|
@@ -2894,7 +2897,9 @@ var MCPClient = class {
|
|
|
2894
2897
|
method: "resources/list",
|
|
2895
2898
|
params: {}
|
|
2896
2899
|
};
|
|
2897
|
-
const result = await this.
|
|
2900
|
+
const result = await this.withRetry(
|
|
2901
|
+
() => this.client.request(request, types_js.ListResourcesResultSchema)
|
|
2902
|
+
);
|
|
2898
2903
|
this.emitStateChange("READY");
|
|
2899
2904
|
this.emitProgress(`Discovered ${result.resources.length} resources`);
|
|
2900
2905
|
return result;
|
|
@@ -2921,7 +2926,35 @@ var MCPClient = class {
|
|
|
2921
2926
|
uri
|
|
2922
2927
|
}
|
|
2923
2928
|
};
|
|
2924
|
-
return await this.
|
|
2929
|
+
return await this.withRetry(
|
|
2930
|
+
() => this.client.request(request, types_js.ReadResourceResultSchema)
|
|
2931
|
+
);
|
|
2932
|
+
}
|
|
2933
|
+
/**
|
|
2934
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
2935
|
+
*
|
|
2936
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
2937
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
2938
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
2939
|
+
* and retries the request once.
|
|
2940
|
+
*
|
|
2941
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
2942
|
+
*/
|
|
2943
|
+
async withRetry(fn) {
|
|
2944
|
+
try {
|
|
2945
|
+
return await fn();
|
|
2946
|
+
} catch (error) {
|
|
2947
|
+
if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
|
|
2948
|
+
if (this.client.transport) {
|
|
2949
|
+
try {
|
|
2950
|
+
await this.client.close();
|
|
2951
|
+
} catch {
|
|
2952
|
+
}
|
|
2953
|
+
this.transport = null;
|
|
2954
|
+
}
|
|
2955
|
+
await this.reconnect();
|
|
2956
|
+
return await fn();
|
|
2957
|
+
}
|
|
2925
2958
|
}
|
|
2926
2959
|
/**
|
|
2927
2960
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
@@ -2930,20 +2963,9 @@ var MCPClient = class {
|
|
|
2930
2963
|
* @throws {Error} When OAuth provider is not initialized
|
|
2931
2964
|
*/
|
|
2932
2965
|
async reconnect() {
|
|
2933
|
-
await this.
|
|
2934
|
-
if (!this.oauthProvider)
|
|
2935
|
-
|
|
2936
|
-
}
|
|
2937
|
-
this.client = new index_js.Client(
|
|
2938
|
-
{
|
|
2939
|
-
name: MCP_CLIENT_NAME,
|
|
2940
|
-
version: MCP_CLIENT_VERSION
|
|
2941
|
-
},
|
|
2942
|
-
{ capabilities: {} }
|
|
2943
|
-
);
|
|
2944
|
-
const tt = this.transportType || "streamable-http";
|
|
2945
|
-
this.transport = this.getTransport(tt);
|
|
2946
|
-
await this.client.connect(this.transport);
|
|
2966
|
+
await this.ensureSession();
|
|
2967
|
+
if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
|
|
2968
|
+
await this.connect();
|
|
2947
2969
|
}
|
|
2948
2970
|
/**
|
|
2949
2971
|
* Completely removes the session from Redis including all OAuth data
|
|
@@ -2951,7 +2973,7 @@ var MCPClient = class {
|
|
|
2951
2973
|
*/
|
|
2952
2974
|
async clearSession() {
|
|
2953
2975
|
try {
|
|
2954
|
-
await this.
|
|
2976
|
+
await this.ensureSession();
|
|
2955
2977
|
} catch (error) {
|
|
2956
2978
|
console.warn("[MCPClient] Initialization failed during clearSession:", error);
|
|
2957
2979
|
}
|
|
@@ -2966,7 +2988,7 @@ var MCPClient = class {
|
|
|
2966
2988
|
* @returns True if connected, false otherwise
|
|
2967
2989
|
*/
|
|
2968
2990
|
isConnected() {
|
|
2969
|
-
return this.client !==
|
|
2991
|
+
return this.client.transport !== void 0;
|
|
2970
2992
|
}
|
|
2971
2993
|
/**
|
|
2972
2994
|
* Disconnects from the MCP server and cleans up resources.
|
|
@@ -2984,10 +3006,12 @@ var MCPClient = class {
|
|
|
2984
3006
|
} catch {
|
|
2985
3007
|
}
|
|
2986
3008
|
}
|
|
2987
|
-
if (this.client) {
|
|
2988
|
-
|
|
3009
|
+
if (this.client.transport) {
|
|
3010
|
+
try {
|
|
3011
|
+
await this.client.close();
|
|
3012
|
+
} catch {
|
|
3013
|
+
}
|
|
2989
3014
|
}
|
|
2990
|
-
this.client = null;
|
|
2991
3015
|
this.oauthProvider = null;
|
|
2992
3016
|
this.transport = null;
|
|
2993
3017
|
if (this.serverId) {
|
|
@@ -3130,6 +3154,18 @@ var MultiSessionClient = class {
|
|
|
3130
3154
|
getClients() {
|
|
3131
3155
|
return this.clients;
|
|
3132
3156
|
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Removes and disconnects a single session by ID.
|
|
3159
|
+
*
|
|
3160
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
3161
|
+
*/
|
|
3162
|
+
async removeSession(sessionId) {
|
|
3163
|
+
const idx = this.clients.findIndex((c) => c.getSessionId() === sessionId);
|
|
3164
|
+
if (idx === -1) return false;
|
|
3165
|
+
const [client] = this.clients.splice(idx, 1);
|
|
3166
|
+
await client.disconnect();
|
|
3167
|
+
return true;
|
|
3168
|
+
}
|
|
3133
3169
|
/**
|
|
3134
3170
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
3135
3171
|
*
|