@mcp-ts/sdk 2.5.1 → 2.5.3
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/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/react.d.mts +4 -4
- package/dist/client/react.d.ts +4 -4
- package/dist/client/react.js +1 -1
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +1 -1
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +5 -4
- package/dist/client/vue.d.ts +5 -4
- package/dist/client/vue.js +1 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +1 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{index-C99wE2Zf.d.mts → index-BRZO_JyI.d.mts} +1 -1
- package/dist/{index-BEdyuz1M.d.ts → index-C3YGagi2.d.ts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +163 -15
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +163 -15
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CclWRxTD.d.mts → multi-session-client-CuacvZaQ.d.ts} +36 -10
- package/dist/{multi-session-client-DzvZD6Tt.d.ts → multi-session-client-DqzT8Oo7.d.mts} +36 -10
- package/dist/server/index.d.mts +34 -7
- package/dist/server/index.d.ts +34 -7
- package/dist/server/index.js +163 -15
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +163 -15
- 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-CUSSk6lT.d.ts → tool-router-2qUyZ-cP.d.ts} +1 -1
- package/dist/{tool-router-C9ECn3FX.d.mts → tool-router-B0qpui-V.d.mts} +1 -1
- package/dist/{types-CbFbPkfQ.d.mts → types-BkJ_rgzo.d.mts} +3 -0
- package/dist/{types-CbFbPkfQ.d.ts → types-BkJ_rgzo.d.ts} +3 -0
- package/package.json +1 -1
- package/src/client/react/use-mcp.ts +1 -1
- package/src/client/vue/use-mcp.ts +2 -1
- package/src/server/handlers/sse-handler.ts +41 -5
- package/src/server/mcp/oauth-client.ts +44 -20
- package/src/server/mcp/storage-oauth-provider.ts +13 -0
- package/src/server/mcp/tool-policy-gateway.ts +98 -2
- package/src/server/storage/tool-policy.ts +102 -0
- package/src/shared/events.ts +1 -0
- package/src/shared/types.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -2016,6 +2016,15 @@ var StorageOAuthClientProvider = class {
|
|
|
2016
2016
|
if (data.clientId && !this._clientId) {
|
|
2017
2017
|
this._clientId = data.clientId;
|
|
2018
2018
|
}
|
|
2019
|
+
if (this._clientId && !data.clientId) {
|
|
2020
|
+
await this.patchCredentials({
|
|
2021
|
+
clientId: this._clientId,
|
|
2022
|
+
clientInformation: {
|
|
2023
|
+
client_id: this._clientId,
|
|
2024
|
+
...this.clientSecret ? { client_secret: this.clientSecret } : {}
|
|
2025
|
+
}
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2019
2028
|
if (data.clientInformation) {
|
|
2020
2029
|
return data.clientInformation;
|
|
2021
2030
|
}
|
|
@@ -2320,6 +2329,15 @@ var MCPClient = class {
|
|
|
2320
2329
|
__publicField(this, "_onObservabilityEvent", new Emitter());
|
|
2321
2330
|
__publicField(this, "onObservabilityEvent", this._onObservabilityEvent.event);
|
|
2322
2331
|
__publicField(this, "currentState", "DISCONNECTED");
|
|
2332
|
+
/**
|
|
2333
|
+
* In-memory cache for the remote server's full tools list.
|
|
2334
|
+
*
|
|
2335
|
+
* Populated on the first `fetchTools()` call and reused for the lifetime of
|
|
2336
|
+
* the connection. Cleared to `null` at the start of `connect()` so that a
|
|
2337
|
+
* reconnect always retrieves a fresh list, and also in `dispose()` to release
|
|
2338
|
+
* the memory when the client is no longer needed.
|
|
2339
|
+
*/
|
|
2340
|
+
__publicField(this, "cachedTools", null);
|
|
2323
2341
|
this.serverUrl = options.serverUrl;
|
|
2324
2342
|
this.serverName = options.serverName;
|
|
2325
2343
|
this.callbackUrl = options.callbackUrl;
|
|
@@ -2640,13 +2658,20 @@ var MCPClient = class {
|
|
|
2640
2658
|
throw lastError || new Error("No transports available");
|
|
2641
2659
|
}
|
|
2642
2660
|
/**
|
|
2643
|
-
* Connects to the MCP server
|
|
2644
|
-
*
|
|
2645
|
-
*
|
|
2646
|
-
*
|
|
2647
|
-
*
|
|
2661
|
+
* Connects to the MCP server.
|
|
2662
|
+
*
|
|
2663
|
+
* Automatically validates and refreshes OAuth tokens if needed.
|
|
2664
|
+
* Saves the session to Redis on first successful connection.
|
|
2665
|
+
*
|
|
2666
|
+
* The in-memory tools cache (`cachedTools`) is cleared at the start of every
|
|
2667
|
+
* call so that a reconnection always fetches a fresh tool list from the remote
|
|
2668
|
+
* server — even if the same `MCPClient` instance is reused.
|
|
2669
|
+
*
|
|
2670
|
+
* @throws {UnauthorizedError} When OAuth authorization is required.
|
|
2671
|
+
* @throws {Error} When connection fails for other reasons.
|
|
2648
2672
|
*/
|
|
2649
2673
|
async connect() {
|
|
2674
|
+
this.cachedTools = null;
|
|
2650
2675
|
if (this.client.transport) {
|
|
2651
2676
|
this.transport = null;
|
|
2652
2677
|
try {
|
|
@@ -2829,17 +2854,30 @@ var MCPClient = class {
|
|
|
2829
2854
|
}
|
|
2830
2855
|
}
|
|
2831
2856
|
/**
|
|
2832
|
-
* Lists all available tools from the connected MCP server without emitting
|
|
2833
|
-
*
|
|
2857
|
+
* Lists all available tools from the connected MCP server without emitting
|
|
2858
|
+
* discovery events. The result is cached in memory for the lifetime of the
|
|
2859
|
+
* connection — subsequent callers (e.g. `gateway.listTools()` running right
|
|
2860
|
+
* after `fetchTools()`) pay zero extra network cost.
|
|
2861
|
+
*
|
|
2862
|
+
* Gateways use this to apply a tool-access policy before publishing the
|
|
2863
|
+
* filtered list to agents or UI state.
|
|
2864
|
+
*
|
|
2865
|
+
* @returns The full `ListToolsResult` from the remote server.
|
|
2866
|
+
* @throws {Error} When the client is not connected or the request times out.
|
|
2834
2867
|
*/
|
|
2835
2868
|
async fetchTools() {
|
|
2869
|
+
if (this.cachedTools) {
|
|
2870
|
+
return this.cachedTools;
|
|
2871
|
+
}
|
|
2836
2872
|
const request = {
|
|
2837
2873
|
method: "tools/list",
|
|
2838
2874
|
params: {}
|
|
2839
2875
|
};
|
|
2840
|
-
|
|
2876
|
+
const result = await this.withRetry(
|
|
2841
2877
|
() => this.client.request(request, types_js.ListToolsResultSchema)
|
|
2842
2878
|
);
|
|
2879
|
+
this.cachedTools = result;
|
|
2880
|
+
return result;
|
|
2843
2881
|
}
|
|
2844
2882
|
/**
|
|
2845
2883
|
* Lists all available tools from the connected MCP server
|
|
@@ -3125,10 +3163,14 @@ var MCPClient = class {
|
|
|
3125
3163
|
this.emitStateChange("DISCONNECTED");
|
|
3126
3164
|
}
|
|
3127
3165
|
/**
|
|
3128
|
-
*
|
|
3129
|
-
*
|
|
3166
|
+
* Disposes all event emitters and releases cached state.
|
|
3167
|
+
*
|
|
3168
|
+
* Clears `cachedTools` to free memory, and disposes the connection and
|
|
3169
|
+
* observability event emitters so downstream listeners are unsubscribed.
|
|
3170
|
+
* Call this when the client is permanently shut down (not just disconnected).
|
|
3130
3171
|
*/
|
|
3131
3172
|
dispose() {
|
|
3173
|
+
this.cachedTools = null;
|
|
3132
3174
|
this._onConnectionEvent.dispose();
|
|
3133
3175
|
this._onObservabilityEvent.dispose();
|
|
3134
3176
|
}
|
|
@@ -3187,21 +3229,47 @@ var ToolPolicyGateway = class {
|
|
|
3187
3229
|
this.sessionId = sessionId;
|
|
3188
3230
|
this.client = client;
|
|
3189
3231
|
}
|
|
3232
|
+
/**
|
|
3233
|
+
* Returns whether the underlying MCP client transport is currently connected.
|
|
3234
|
+
*/
|
|
3190
3235
|
isConnected() {
|
|
3191
3236
|
return this.client.isConnected();
|
|
3192
3237
|
}
|
|
3238
|
+
/**
|
|
3239
|
+
* Returns the server ID from the underlying client, if available.
|
|
3240
|
+
*/
|
|
3193
3241
|
getServerId() {
|
|
3194
3242
|
return this.client.getServerId?.();
|
|
3195
3243
|
}
|
|
3244
|
+
/**
|
|
3245
|
+
* Returns the human-readable server name from the underlying client, if available.
|
|
3246
|
+
*/
|
|
3196
3247
|
getServerName() {
|
|
3197
3248
|
return this.client.getServerName?.();
|
|
3198
3249
|
}
|
|
3250
|
+
/**
|
|
3251
|
+
* Returns the server URL from the underlying client, if available.
|
|
3252
|
+
*/
|
|
3199
3253
|
getServerUrl() {
|
|
3200
3254
|
return this.client.getServerUrl?.();
|
|
3201
3255
|
}
|
|
3256
|
+
/**
|
|
3257
|
+
* Returns the session ID — prefers the value reported by the underlying
|
|
3258
|
+
* client, falling back to the one injected at construction time.
|
|
3259
|
+
*/
|
|
3202
3260
|
getSessionId() {
|
|
3203
3261
|
return this.client.getSessionId?.() ?? this.sessionId;
|
|
3204
3262
|
}
|
|
3263
|
+
/**
|
|
3264
|
+
* Returns the **policy-filtered** list of tools that the current session
|
|
3265
|
+
* is allowed to call.
|
|
3266
|
+
*
|
|
3267
|
+
* Internally calls `client.fetchTools()` (which is cache-backed) so no
|
|
3268
|
+
* extra network round-trip is incurred when called after `fetchTools()`.
|
|
3269
|
+
*
|
|
3270
|
+
* @returns A `ListToolsResult` containing only the permitted tools.
|
|
3271
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3272
|
+
*/
|
|
3205
3273
|
async listTools() {
|
|
3206
3274
|
const session = await this.getSession();
|
|
3207
3275
|
const result = await this.client.fetchTools();
|
|
@@ -3211,20 +3279,61 @@ var ToolPolicyGateway = class {
|
|
|
3211
3279
|
tools
|
|
3212
3280
|
};
|
|
3213
3281
|
}
|
|
3282
|
+
/**
|
|
3283
|
+
* Returns the **complete, unfiltered** list of tools from the remote server,
|
|
3284
|
+
* bypassing any tool-access policy.
|
|
3285
|
+
*
|
|
3286
|
+
* Used by the management UI to show all available tools (including blocked
|
|
3287
|
+
* ones) so users can toggle individual tool access in the dialog.
|
|
3288
|
+
*
|
|
3289
|
+
* @returns The raw `ListToolsResult` from the remote server.
|
|
3290
|
+
*/
|
|
3214
3291
|
async listAllTools() {
|
|
3215
3292
|
return await this.client.fetchTools();
|
|
3216
3293
|
}
|
|
3294
|
+
/**
|
|
3295
|
+
* Executes a tool call on the remote server after verifying that the tool
|
|
3296
|
+
* is permitted by the current session's policy.
|
|
3297
|
+
*
|
|
3298
|
+
* @param name - The exact tool name to invoke.
|
|
3299
|
+
* @param args - Key/value arguments to pass to the tool.
|
|
3300
|
+
* @returns The tool's `CallToolResult`.
|
|
3301
|
+
* @throws {Error} When the tool is blocked by the session's policy.
|
|
3302
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3303
|
+
*/
|
|
3217
3304
|
async callTool(name, args) {
|
|
3218
3305
|
const session = await this.getSession();
|
|
3219
3306
|
this.assertAllowed(session, name);
|
|
3220
3307
|
return await this.client.callTool(name, args);
|
|
3221
3308
|
}
|
|
3309
|
+
/**
|
|
3310
|
+
* Filters a raw tools array down to only those permitted by the session's
|
|
3311
|
+
* `toolPolicy`.
|
|
3312
|
+
*
|
|
3313
|
+
* @param session - The session whose policy should be applied.
|
|
3314
|
+
* @param tools - The unfiltered list of tools from the remote server.
|
|
3315
|
+
* @returns A subset of `tools` that the policy allows.
|
|
3316
|
+
*/
|
|
3222
3317
|
filterTools(session, tools) {
|
|
3223
3318
|
return filterToolsByPolicy(tools, session.toolPolicy, this.getPolicyServerId(session));
|
|
3224
3319
|
}
|
|
3320
|
+
/**
|
|
3321
|
+
* Throws if `toolName` is blocked by the session's policy.
|
|
3322
|
+
* Call this before proxying a `callTool` request to the remote server.
|
|
3323
|
+
*
|
|
3324
|
+
* @param session - The session whose policy should be enforced.
|
|
3325
|
+
* @param toolName - The tool being invoked.
|
|
3326
|
+
* @throws {Error} When the tool is not permitted.
|
|
3327
|
+
*/
|
|
3225
3328
|
assertAllowed(session, toolName) {
|
|
3226
3329
|
assertToolAllowed(session.toolPolicy, toolName, this.getPolicyServerId(session));
|
|
3227
3330
|
}
|
|
3331
|
+
/**
|
|
3332
|
+
* Loads the session from the store and throws if it does not exist.
|
|
3333
|
+
*
|
|
3334
|
+
* @returns The fully-hydrated `Session` record.
|
|
3335
|
+
* @throws {Error} When the session cannot be found.
|
|
3336
|
+
*/
|
|
3228
3337
|
async getSession() {
|
|
3229
3338
|
const session = await sessions.get(this.userId, this.sessionId);
|
|
3230
3339
|
if (!session) {
|
|
@@ -3232,6 +3341,11 @@ var ToolPolicyGateway = class {
|
|
|
3232
3341
|
}
|
|
3233
3342
|
return session;
|
|
3234
3343
|
}
|
|
3344
|
+
/**
|
|
3345
|
+
* Resolves the server ID to use when evaluating tool policy.
|
|
3346
|
+
* Prefers the value from the live client (most accurate) and falls back
|
|
3347
|
+
* to the server ID stored on the session record.
|
|
3348
|
+
*/
|
|
3235
3349
|
getPolicyServerId(session) {
|
|
3236
3350
|
return this.client.getServerId?.() ?? session.serverId;
|
|
3237
3351
|
}
|
|
@@ -3620,7 +3734,7 @@ var SSEConnectionManager = class {
|
|
|
3620
3734
|
* Connect to an MCP server
|
|
3621
3735
|
*/
|
|
3622
3736
|
async connect(params) {
|
|
3623
|
-
const { serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3737
|
+
const { serverName, serverUrl, callbackUrl, transportType, clientId, clientSecret } = params;
|
|
3624
3738
|
const headers = normalizeHeaders(params.headers);
|
|
3625
3739
|
const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : generateServerId();
|
|
3626
3740
|
const existingSessions = await sessions.list(this.userId);
|
|
@@ -3649,6 +3763,8 @@ var SSEConnectionManager = class {
|
|
|
3649
3763
|
callbackUrl,
|
|
3650
3764
|
transportType,
|
|
3651
3765
|
headers,
|
|
3766
|
+
clientId,
|
|
3767
|
+
clientSecret,
|
|
3652
3768
|
...clientMetadata
|
|
3653
3769
|
// Spread client metadata (clientName, clientUri, logoUri, policyUri)
|
|
3654
3770
|
});
|
|
@@ -3690,7 +3806,7 @@ var SSEConnectionManager = class {
|
|
|
3690
3806
|
* and creates a fresh connection while reusing the existing session credentials in a single RPC call.
|
|
3691
3807
|
*/
|
|
3692
3808
|
async reconnect(params) {
|
|
3693
|
-
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3809
|
+
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType, clientId, clientSecret } = params;
|
|
3694
3810
|
const headers = normalizeHeaders(params.headers);
|
|
3695
3811
|
const serverId = rawServerId && rawServerId.length <= 12 ? rawServerId : generateServerId();
|
|
3696
3812
|
const existingSessions = await sessions.list(this.userId);
|
|
@@ -3716,6 +3832,8 @@ var SSEConnectionManager = class {
|
|
|
3716
3832
|
callbackUrl,
|
|
3717
3833
|
transportType,
|
|
3718
3834
|
headers,
|
|
3835
|
+
clientId,
|
|
3836
|
+
clientSecret,
|
|
3719
3837
|
...clientMetadata
|
|
3720
3838
|
});
|
|
3721
3839
|
this.clients.set(sessionId, client);
|
|
@@ -3791,12 +3909,29 @@ var SSEConnectionManager = class {
|
|
|
3791
3909
|
this.clients.set(sessionId, client);
|
|
3792
3910
|
return client;
|
|
3793
3911
|
}
|
|
3912
|
+
/**
|
|
3913
|
+
* Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
|
|
3914
|
+
*
|
|
3915
|
+
* Two lists are always published together:
|
|
3916
|
+
* - `tools` — policy-filtered list that agents are allowed to call.
|
|
3917
|
+
* - `allTools` — the complete, unfiltered list used by the management UI so
|
|
3918
|
+
* that blocked tools still appear as checkboxes in the dialog.
|
|
3919
|
+
*
|
|
3920
|
+
* `fetchTools()` is called first (populates the in-memory cache), then
|
|
3921
|
+
* `gateway.listTools()` re-uses that cache internally — so only one remote
|
|
3922
|
+
* network round-trip is made regardless of how many callers follow.
|
|
3923
|
+
*
|
|
3924
|
+
* @param sessionId - The session whose tools should be discovered.
|
|
3925
|
+
* @returns The session record and the policy-filtered tool list.
|
|
3926
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3927
|
+
*/
|
|
3794
3928
|
async listPolicyFilteredTools(sessionId) {
|
|
3795
3929
|
const session = await sessions.get(this.userId, sessionId);
|
|
3796
3930
|
if (!session) {
|
|
3797
3931
|
throw new Error("Session not found");
|
|
3798
3932
|
}
|
|
3799
3933
|
const client = await this.getOrCreateClient(sessionId);
|
|
3934
|
+
const allTools = await client.fetchTools().catch(() => ({ tools: [] }));
|
|
3800
3935
|
const gateway = createToolPolicyGateway(this.userId, sessionId, client);
|
|
3801
3936
|
const result = await gateway.listTools();
|
|
3802
3937
|
this.emitConnectionEvent({
|
|
@@ -3805,12 +3940,15 @@ var SSEConnectionManager = class {
|
|
|
3805
3940
|
serverId: session.serverId ?? "unknown",
|
|
3806
3941
|
toolCount: result.tools.length,
|
|
3807
3942
|
tools: result.tools,
|
|
3943
|
+
allTools: allTools.tools,
|
|
3808
3944
|
timestamp: Date.now()
|
|
3809
3945
|
});
|
|
3810
3946
|
return { session, result };
|
|
3811
3947
|
}
|
|
3812
3948
|
/**
|
|
3813
|
-
*
|
|
3949
|
+
* Returns the policy-filtered tool list for a session (agent-facing).
|
|
3950
|
+
* Internally re-uses `listPolicyFilteredTools` which also emits a
|
|
3951
|
+
* `tools_discovered` SSE event to keep client state up to date.
|
|
3814
3952
|
*/
|
|
3815
3953
|
async listTools(params) {
|
|
3816
3954
|
const { sessionId } = params;
|
|
@@ -3847,7 +3985,15 @@ var SSEConnectionManager = class {
|
|
|
3847
3985
|
};
|
|
3848
3986
|
}
|
|
3849
3987
|
/**
|
|
3850
|
-
*
|
|
3988
|
+
* Persists a new tool access policy for a session and broadcasts the updated
|
|
3989
|
+
* filtered tool list to all connected browser clients via a `tools_discovered` event.
|
|
3990
|
+
*
|
|
3991
|
+
* Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
|
|
3992
|
+
* so the management UI can immediately reflect the new checkbox states without
|
|
3993
|
+
* an additional round-trip to the server.
|
|
3994
|
+
*
|
|
3995
|
+
* @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
|
|
3996
|
+
* @throws {Error} When the session does not exist or the policy references unknown tool IDs.
|
|
3851
3997
|
*/
|
|
3852
3998
|
async setToolPolicy(params) {
|
|
3853
3999
|
const { sessionId } = params;
|
|
@@ -3867,6 +4013,7 @@ var SSEConnectionManager = class {
|
|
|
3867
4013
|
serverId: session.serverId ?? "unknown",
|
|
3868
4014
|
toolCount: filteredTools.length,
|
|
3869
4015
|
tools: filteredTools,
|
|
4016
|
+
allTools: allTools.tools,
|
|
3870
4017
|
timestamp: Date.now()
|
|
3871
4018
|
});
|
|
3872
4019
|
return {
|
|
@@ -3877,7 +4024,8 @@ var SSEConnectionManager = class {
|
|
|
3877
4024
|
};
|
|
3878
4025
|
}
|
|
3879
4026
|
/**
|
|
3880
|
-
*
|
|
4027
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
4028
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
3881
4029
|
*/
|
|
3882
4030
|
async callTool(params) {
|
|
3883
4031
|
const { sessionId, toolName, toolArgs } = params;
|