@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/server/index.mjs
CHANGED
|
@@ -1666,12 +1666,12 @@ async function createStorage() {
|
|
|
1666
1666
|
}
|
|
1667
1667
|
if (type === "supabase") {
|
|
1668
1668
|
const url = process.env.SUPABASE_URL;
|
|
1669
|
-
const key = process.env.
|
|
1669
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1670
1670
|
if (!url || !key) {
|
|
1671
|
-
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and
|
|
1671
|
+
console.warn('[mcp-ts][Storage] Explicit selection "supabase" requires SUPABASE_URL and SUPABASE_SECRET_KEY.');
|
|
1672
1672
|
} else {
|
|
1673
|
-
if (!process.env.
|
|
1674
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1673
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1674
|
+
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.');
|
|
1675
1675
|
}
|
|
1676
1676
|
try {
|
|
1677
1677
|
const { createClient } = await import('@supabase/supabase-js');
|
|
@@ -1726,13 +1726,13 @@ async function createStorage() {
|
|
|
1726
1726
|
console.log(`[mcp-ts][Storage] Auto-detection: "sqlite" (${process.env.MCP_TS_STORAGE_SQLITE_PATH})`);
|
|
1727
1727
|
return await initializeStorage(new SqliteStorage({ path: process.env.MCP_TS_STORAGE_SQLITE_PATH }));
|
|
1728
1728
|
}
|
|
1729
|
-
if (process.env.SUPABASE_URL && (process.env.
|
|
1729
|
+
if (process.env.SUPABASE_URL && (process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY)) {
|
|
1730
1730
|
try {
|
|
1731
1731
|
const { createClient } = await import('@supabase/supabase-js');
|
|
1732
1732
|
const url = process.env.SUPABASE_URL;
|
|
1733
|
-
const key = process.env.
|
|
1734
|
-
if (!process.env.
|
|
1735
|
-
console.warn('[mcp-ts][Storage] \u26A0\uFE0F Warning: Using "SUPABASE_ANON_KEY" for server-side storage. You may encounter RLS policy violations. "
|
|
1733
|
+
const key = process.env.SUPABASE_SECRET_KEY || process.env.SUPABASE_ANON_KEY;
|
|
1734
|
+
if (!process.env.SUPABASE_SECRET_KEY) {
|
|
1735
|
+
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.');
|
|
1736
1736
|
}
|
|
1737
1737
|
const client = createClient(url, key);
|
|
1738
1738
|
console.log('[mcp-ts][Storage] Auto-detection: "supabase" (via SUPABASE_URL)');
|
|
@@ -2079,7 +2079,7 @@ var MCPClient = class {
|
|
|
2079
2079
|
* @param options - Client configuration options
|
|
2080
2080
|
*/
|
|
2081
2081
|
constructor(options) {
|
|
2082
|
-
__publicField(this, "client"
|
|
2082
|
+
__publicField(this, "client");
|
|
2083
2083
|
__publicField(this, "oauthProvider", null);
|
|
2084
2084
|
__publicField(this, "transport", null);
|
|
2085
2085
|
__publicField(this, "userId");
|
|
@@ -2120,6 +2120,21 @@ var MCPClient = class {
|
|
|
2120
2120
|
this.clientUri = options.clientUri;
|
|
2121
2121
|
this.logoUri = options.logoUri;
|
|
2122
2122
|
this.policyUri = options.policyUri;
|
|
2123
|
+
this.client = new Client(
|
|
2124
|
+
{
|
|
2125
|
+
name: MCP_CLIENT_NAME,
|
|
2126
|
+
version: MCP_CLIENT_VERSION
|
|
2127
|
+
},
|
|
2128
|
+
{
|
|
2129
|
+
capabilities: {
|
|
2130
|
+
extensions: {
|
|
2131
|
+
"io.modelcontextprotocol/ui": {
|
|
2132
|
+
mimeTypes: ["text/html+mcp"]
|
|
2133
|
+
}
|
|
2134
|
+
}
|
|
2135
|
+
}
|
|
2136
|
+
}
|
|
2137
|
+
);
|
|
2123
2138
|
}
|
|
2124
2139
|
/**
|
|
2125
2140
|
* Emit a connection state change event
|
|
@@ -2230,7 +2245,6 @@ var MCPClient = class {
|
|
|
2230
2245
|
const response = await fetch(url, { ...init, signal });
|
|
2231
2246
|
const hasSessionHeader = init?.headers && new Headers(init.headers).has("mcp-session-id");
|
|
2232
2247
|
if (response.status === 404 && hasSessionHeader) {
|
|
2233
|
-
this.client = null;
|
|
2234
2248
|
throw new Error("MCP_SESSION_EXPIRED: Downstream session was not found on the server.");
|
|
2235
2249
|
}
|
|
2236
2250
|
return response;
|
|
@@ -2246,13 +2260,12 @@ var MCPClient = class {
|
|
|
2246
2260
|
}
|
|
2247
2261
|
}
|
|
2248
2262
|
/**
|
|
2249
|
-
*
|
|
2250
|
-
*
|
|
2251
|
-
* This method is idempotent and safe to call multiple times
|
|
2263
|
+
* Ensures session metadata and OAuth provider are loaded.
|
|
2264
|
+
* Does NOT create the SDK Client — callers that need one create it themselves.
|
|
2252
2265
|
* @private
|
|
2253
2266
|
*/
|
|
2254
|
-
async
|
|
2255
|
-
if (this.
|
|
2267
|
+
async ensureSession() {
|
|
2268
|
+
if (this.oauthProvider) {
|
|
2256
2269
|
return;
|
|
2257
2270
|
}
|
|
2258
2271
|
this.emitStateChange("INITIALIZING");
|
|
@@ -2295,23 +2308,6 @@ var MCPClient = class {
|
|
|
2295
2308
|
}
|
|
2296
2309
|
});
|
|
2297
2310
|
}
|
|
2298
|
-
if (!this.client) {
|
|
2299
|
-
this.client = new Client(
|
|
2300
|
-
{
|
|
2301
|
-
name: MCP_CLIENT_NAME,
|
|
2302
|
-
version: MCP_CLIENT_VERSION
|
|
2303
|
-
},
|
|
2304
|
-
{
|
|
2305
|
-
capabilities: {
|
|
2306
|
-
extensions: {
|
|
2307
|
-
"io.modelcontextprotocol/ui": {
|
|
2308
|
-
mimeTypes: ["text/html+mcp"]
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2312
|
-
}
|
|
2313
|
-
);
|
|
2314
|
-
}
|
|
2315
2311
|
if (existingSession === null) {
|
|
2316
2312
|
existingSession = await sessions.get(this.userId, this.sessionId);
|
|
2317
2313
|
}
|
|
@@ -2428,17 +2424,16 @@ var MCPClient = class {
|
|
|
2428
2424
|
* @throws {Error} When connection fails for other reasons
|
|
2429
2425
|
*/
|
|
2430
2426
|
async connect() {
|
|
2431
|
-
if (this.client
|
|
2427
|
+
if (this.client.transport) {
|
|
2432
2428
|
this.transport = null;
|
|
2433
2429
|
try {
|
|
2434
2430
|
await this.client.close();
|
|
2435
2431
|
} catch {
|
|
2436
2432
|
}
|
|
2437
|
-
this.client = null;
|
|
2438
2433
|
}
|
|
2439
|
-
await this.
|
|
2440
|
-
if (!this.
|
|
2441
|
-
const error = "
|
|
2434
|
+
await this.ensureSession();
|
|
2435
|
+
if (!this.oauthProvider) {
|
|
2436
|
+
const error = "OAuth provider not initialized";
|
|
2442
2437
|
this.emitError(error, "connection");
|
|
2443
2438
|
this.emitStateChange("FAILED");
|
|
2444
2439
|
throw new Error(error);
|
|
@@ -2505,7 +2500,7 @@ var MCPClient = class {
|
|
|
2505
2500
|
async finishAuth(authCode, state) {
|
|
2506
2501
|
this.emitStateChange("AUTHENTICATING");
|
|
2507
2502
|
this.emitProgress("Exchanging authorization code for tokens...");
|
|
2508
|
-
await this.
|
|
2503
|
+
await this.ensureSession();
|
|
2509
2504
|
if (!this.oauthProvider) {
|
|
2510
2505
|
const error = "OAuth provider not initialized";
|
|
2511
2506
|
this.emitError(error, "auth");
|
|
@@ -2611,7 +2606,9 @@ var MCPClient = class {
|
|
|
2611
2606
|
method: "tools/list",
|
|
2612
2607
|
params: {}
|
|
2613
2608
|
};
|
|
2614
|
-
const result = await this.
|
|
2609
|
+
const result = await this.withRetry(
|
|
2610
|
+
() => this.client.request(request, ListToolsResultSchema)
|
|
2611
|
+
);
|
|
2615
2612
|
if (this.serverId) {
|
|
2616
2613
|
this._onConnectionEvent.fire({
|
|
2617
2614
|
type: "tools_discovered",
|
|
@@ -2651,7 +2648,9 @@ var MCPClient = class {
|
|
|
2651
2648
|
}
|
|
2652
2649
|
};
|
|
2653
2650
|
try {
|
|
2654
|
-
const result = await this.
|
|
2651
|
+
const result = await this.withRetry(
|
|
2652
|
+
() => this.client.request(request, CallToolResultSchema)
|
|
2653
|
+
);
|
|
2655
2654
|
this._onObservabilityEvent.fire({
|
|
2656
2655
|
type: "mcp:client:tool_call",
|
|
2657
2656
|
level: "info",
|
|
@@ -2703,7 +2702,9 @@ var MCPClient = class {
|
|
|
2703
2702
|
method: "prompts/list",
|
|
2704
2703
|
params: {}
|
|
2705
2704
|
};
|
|
2706
|
-
const result = await this.
|
|
2705
|
+
const result = await this.withRetry(
|
|
2706
|
+
() => this.client.request(request, ListPromptsResultSchema)
|
|
2707
|
+
);
|
|
2707
2708
|
this.emitStateChange("READY");
|
|
2708
2709
|
this.emitProgress(`Discovered ${result.prompts.length} prompts`);
|
|
2709
2710
|
return result;
|
|
@@ -2732,7 +2733,9 @@ var MCPClient = class {
|
|
|
2732
2733
|
arguments: args
|
|
2733
2734
|
}
|
|
2734
2735
|
};
|
|
2735
|
-
return await this.
|
|
2736
|
+
return await this.withRetry(
|
|
2737
|
+
() => this.client.request(request, GetPromptResultSchema)
|
|
2738
|
+
);
|
|
2736
2739
|
}
|
|
2737
2740
|
/**
|
|
2738
2741
|
* Lists all available resources from the connected MCP server
|
|
@@ -2749,7 +2752,9 @@ var MCPClient = class {
|
|
|
2749
2752
|
method: "resources/list",
|
|
2750
2753
|
params: {}
|
|
2751
2754
|
};
|
|
2752
|
-
const result = await this.
|
|
2755
|
+
const result = await this.withRetry(
|
|
2756
|
+
() => this.client.request(request, ListResourcesResultSchema)
|
|
2757
|
+
);
|
|
2753
2758
|
this.emitStateChange("READY");
|
|
2754
2759
|
this.emitProgress(`Discovered ${result.resources.length} resources`);
|
|
2755
2760
|
return result;
|
|
@@ -2776,7 +2781,35 @@ var MCPClient = class {
|
|
|
2776
2781
|
uri
|
|
2777
2782
|
}
|
|
2778
2783
|
};
|
|
2779
|
-
return await this.
|
|
2784
|
+
return await this.withRetry(
|
|
2785
|
+
() => this.client.request(request, ReadResourceResultSchema)
|
|
2786
|
+
);
|
|
2787
|
+
}
|
|
2788
|
+
/**
|
|
2789
|
+
* Wraps an MCP request with automatic transport-session recovery.
|
|
2790
|
+
*
|
|
2791
|
+
* When the downstream MCP server rejects the request with a 404 indicating
|
|
2792
|
+
* the transport session has expired, this method tears down the stale SDK
|
|
2793
|
+
* client and transport, calls {@link reconnect} to negotiate a fresh session,
|
|
2794
|
+
* and retries the request once.
|
|
2795
|
+
*
|
|
2796
|
+
* Non-transient errors (network failures, auth errors, etc.) propagate as-is.
|
|
2797
|
+
*/
|
|
2798
|
+
async withRetry(fn) {
|
|
2799
|
+
try {
|
|
2800
|
+
return await fn();
|
|
2801
|
+
} catch (error) {
|
|
2802
|
+
if (!(error instanceof Error && error.message.includes("MCP_SESSION_EXPIRED"))) throw error;
|
|
2803
|
+
if (this.client.transport) {
|
|
2804
|
+
try {
|
|
2805
|
+
await this.client.close();
|
|
2806
|
+
} catch {
|
|
2807
|
+
}
|
|
2808
|
+
this.transport = null;
|
|
2809
|
+
}
|
|
2810
|
+
await this.reconnect();
|
|
2811
|
+
return await fn();
|
|
2812
|
+
}
|
|
2780
2813
|
}
|
|
2781
2814
|
/**
|
|
2782
2815
|
* Reconnects to MCP server using existing OAuth provider from Redis
|
|
@@ -2785,20 +2818,9 @@ var MCPClient = class {
|
|
|
2785
2818
|
* @throws {Error} When OAuth provider is not initialized
|
|
2786
2819
|
*/
|
|
2787
2820
|
async reconnect() {
|
|
2788
|
-
await this.
|
|
2789
|
-
if (!this.oauthProvider)
|
|
2790
|
-
|
|
2791
|
-
}
|
|
2792
|
-
this.client = new Client(
|
|
2793
|
-
{
|
|
2794
|
-
name: MCP_CLIENT_NAME,
|
|
2795
|
-
version: MCP_CLIENT_VERSION
|
|
2796
|
-
},
|
|
2797
|
-
{ capabilities: {} }
|
|
2798
|
-
);
|
|
2799
|
-
const tt = this.transportType || "streamable-http";
|
|
2800
|
-
this.transport = this.getTransport(tt);
|
|
2801
|
-
await this.client.connect(this.transport);
|
|
2821
|
+
await this.ensureSession();
|
|
2822
|
+
if (!this.oauthProvider) throw new Error("OAuth provider not initialized");
|
|
2823
|
+
await this.connect();
|
|
2802
2824
|
}
|
|
2803
2825
|
/**
|
|
2804
2826
|
* Completely removes the session from Redis including all OAuth data
|
|
@@ -2806,7 +2828,7 @@ var MCPClient = class {
|
|
|
2806
2828
|
*/
|
|
2807
2829
|
async clearSession() {
|
|
2808
2830
|
try {
|
|
2809
|
-
await this.
|
|
2831
|
+
await this.ensureSession();
|
|
2810
2832
|
} catch (error) {
|
|
2811
2833
|
console.warn("[MCPClient] Initialization failed during clearSession:", error);
|
|
2812
2834
|
}
|
|
@@ -2821,7 +2843,7 @@ var MCPClient = class {
|
|
|
2821
2843
|
* @returns True if connected, false otherwise
|
|
2822
2844
|
*/
|
|
2823
2845
|
isConnected() {
|
|
2824
|
-
return this.client !==
|
|
2846
|
+
return this.client.transport !== void 0;
|
|
2825
2847
|
}
|
|
2826
2848
|
/**
|
|
2827
2849
|
* Disconnects from the MCP server and cleans up resources.
|
|
@@ -2839,10 +2861,12 @@ var MCPClient = class {
|
|
|
2839
2861
|
} catch {
|
|
2840
2862
|
}
|
|
2841
2863
|
}
|
|
2842
|
-
if (this.client) {
|
|
2843
|
-
|
|
2864
|
+
if (this.client.transport) {
|
|
2865
|
+
try {
|
|
2866
|
+
await this.client.close();
|
|
2867
|
+
} catch {
|
|
2868
|
+
}
|
|
2844
2869
|
}
|
|
2845
|
-
this.client = null;
|
|
2846
2870
|
this.oauthProvider = null;
|
|
2847
2871
|
this.transport = null;
|
|
2848
2872
|
if (this.serverId) {
|
|
@@ -2984,6 +3008,18 @@ var MultiSessionClient = class {
|
|
|
2984
3008
|
getClients() {
|
|
2985
3009
|
return this.clients;
|
|
2986
3010
|
}
|
|
3011
|
+
/**
|
|
3012
|
+
* Removes and disconnects a single session by ID.
|
|
3013
|
+
*
|
|
3014
|
+
* @returns `true` if the session was found and removed, `false` if not found.
|
|
3015
|
+
*/
|
|
3016
|
+
async removeSession(sessionId) {
|
|
3017
|
+
const idx = this.clients.findIndex((c) => c.getSessionId() === sessionId);
|
|
3018
|
+
if (idx === -1) return false;
|
|
3019
|
+
const [client] = this.clients.splice(idx, 1);
|
|
3020
|
+
await client.disconnect();
|
|
3021
|
+
return true;
|
|
3022
|
+
}
|
|
2987
3023
|
/**
|
|
2988
3024
|
* Gracefully disconnects all active MCP clients and clears the internal list.
|
|
2989
3025
|
*
|