@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.mjs
CHANGED
|
@@ -1944,6 +1944,15 @@ var StorageOAuthClientProvider = class {
|
|
|
1944
1944
|
if (data.clientId && !this._clientId) {
|
|
1945
1945
|
this._clientId = data.clientId;
|
|
1946
1946
|
}
|
|
1947
|
+
if (this._clientId && !data.clientId) {
|
|
1948
|
+
await this.patchCredentials({
|
|
1949
|
+
clientId: this._clientId,
|
|
1950
|
+
clientInformation: {
|
|
1951
|
+
client_id: this._clientId,
|
|
1952
|
+
...this.clientSecret ? { client_secret: this.clientSecret } : {}
|
|
1953
|
+
}
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1947
1956
|
if (data.clientInformation) {
|
|
1948
1957
|
return data.clientInformation;
|
|
1949
1958
|
}
|
|
@@ -2246,6 +2255,15 @@ var MCPClient = class {
|
|
|
2246
2255
|
__publicField(this, "_onObservabilityEvent", new Emitter());
|
|
2247
2256
|
__publicField(this, "onObservabilityEvent", this._onObservabilityEvent.event);
|
|
2248
2257
|
__publicField(this, "currentState", "DISCONNECTED");
|
|
2258
|
+
/**
|
|
2259
|
+
* In-memory cache for the remote server's full tools list.
|
|
2260
|
+
*
|
|
2261
|
+
* Populated on the first `fetchTools()` call and reused for the lifetime of
|
|
2262
|
+
* the connection. Cleared to `null` at the start of `connect()` so that a
|
|
2263
|
+
* reconnect always retrieves a fresh list, and also in `dispose()` to release
|
|
2264
|
+
* the memory when the client is no longer needed.
|
|
2265
|
+
*/
|
|
2266
|
+
__publicField(this, "cachedTools", null);
|
|
2249
2267
|
this.serverUrl = options.serverUrl;
|
|
2250
2268
|
this.serverName = options.serverName;
|
|
2251
2269
|
this.callbackUrl = options.callbackUrl;
|
|
@@ -2566,13 +2584,20 @@ var MCPClient = class {
|
|
|
2566
2584
|
throw lastError || new Error("No transports available");
|
|
2567
2585
|
}
|
|
2568
2586
|
/**
|
|
2569
|
-
* Connects to the MCP server
|
|
2570
|
-
*
|
|
2571
|
-
*
|
|
2572
|
-
*
|
|
2573
|
-
*
|
|
2587
|
+
* Connects to the MCP server.
|
|
2588
|
+
*
|
|
2589
|
+
* Automatically validates and refreshes OAuth tokens if needed.
|
|
2590
|
+
* Saves the session to Redis on first successful connection.
|
|
2591
|
+
*
|
|
2592
|
+
* The in-memory tools cache (`cachedTools`) is cleared at the start of every
|
|
2593
|
+
* call so that a reconnection always fetches a fresh tool list from the remote
|
|
2594
|
+
* server — even if the same `MCPClient` instance is reused.
|
|
2595
|
+
*
|
|
2596
|
+
* @throws {UnauthorizedError} When OAuth authorization is required.
|
|
2597
|
+
* @throws {Error} When connection fails for other reasons.
|
|
2574
2598
|
*/
|
|
2575
2599
|
async connect() {
|
|
2600
|
+
this.cachedTools = null;
|
|
2576
2601
|
if (this.client.transport) {
|
|
2577
2602
|
this.transport = null;
|
|
2578
2603
|
try {
|
|
@@ -2755,17 +2780,30 @@ var MCPClient = class {
|
|
|
2755
2780
|
}
|
|
2756
2781
|
}
|
|
2757
2782
|
/**
|
|
2758
|
-
* Lists all available tools from the connected MCP server without emitting
|
|
2759
|
-
*
|
|
2783
|
+
* Lists all available tools from the connected MCP server without emitting
|
|
2784
|
+
* discovery events. The result is cached in memory for the lifetime of the
|
|
2785
|
+
* connection — subsequent callers (e.g. `gateway.listTools()` running right
|
|
2786
|
+
* after `fetchTools()`) pay zero extra network cost.
|
|
2787
|
+
*
|
|
2788
|
+
* Gateways use this to apply a tool-access policy before publishing the
|
|
2789
|
+
* filtered list to agents or UI state.
|
|
2790
|
+
*
|
|
2791
|
+
* @returns The full `ListToolsResult` from the remote server.
|
|
2792
|
+
* @throws {Error} When the client is not connected or the request times out.
|
|
2760
2793
|
*/
|
|
2761
2794
|
async fetchTools() {
|
|
2795
|
+
if (this.cachedTools) {
|
|
2796
|
+
return this.cachedTools;
|
|
2797
|
+
}
|
|
2762
2798
|
const request = {
|
|
2763
2799
|
method: "tools/list",
|
|
2764
2800
|
params: {}
|
|
2765
2801
|
};
|
|
2766
|
-
|
|
2802
|
+
const result = await this.withRetry(
|
|
2767
2803
|
() => this.client.request(request, ListToolsResultSchema)
|
|
2768
2804
|
);
|
|
2805
|
+
this.cachedTools = result;
|
|
2806
|
+
return result;
|
|
2769
2807
|
}
|
|
2770
2808
|
/**
|
|
2771
2809
|
* Lists all available tools from the connected MCP server
|
|
@@ -3051,10 +3089,14 @@ var MCPClient = class {
|
|
|
3051
3089
|
this.emitStateChange("DISCONNECTED");
|
|
3052
3090
|
}
|
|
3053
3091
|
/**
|
|
3054
|
-
*
|
|
3055
|
-
*
|
|
3092
|
+
* Disposes all event emitters and releases cached state.
|
|
3093
|
+
*
|
|
3094
|
+
* Clears `cachedTools` to free memory, and disposes the connection and
|
|
3095
|
+
* observability event emitters so downstream listeners are unsubscribed.
|
|
3096
|
+
* Call this when the client is permanently shut down (not just disconnected).
|
|
3056
3097
|
*/
|
|
3057
3098
|
dispose() {
|
|
3099
|
+
this.cachedTools = null;
|
|
3058
3100
|
this._onConnectionEvent.dispose();
|
|
3059
3101
|
this._onObservabilityEvent.dispose();
|
|
3060
3102
|
}
|
|
@@ -3109,21 +3151,47 @@ var ToolPolicyGateway = class {
|
|
|
3109
3151
|
this.sessionId = sessionId;
|
|
3110
3152
|
this.client = client;
|
|
3111
3153
|
}
|
|
3154
|
+
/**
|
|
3155
|
+
* Returns whether the underlying MCP client transport is currently connected.
|
|
3156
|
+
*/
|
|
3112
3157
|
isConnected() {
|
|
3113
3158
|
return this.client.isConnected();
|
|
3114
3159
|
}
|
|
3160
|
+
/**
|
|
3161
|
+
* Returns the server ID from the underlying client, if available.
|
|
3162
|
+
*/
|
|
3115
3163
|
getServerId() {
|
|
3116
3164
|
return this.client.getServerId?.();
|
|
3117
3165
|
}
|
|
3166
|
+
/**
|
|
3167
|
+
* Returns the human-readable server name from the underlying client, if available.
|
|
3168
|
+
*/
|
|
3118
3169
|
getServerName() {
|
|
3119
3170
|
return this.client.getServerName?.();
|
|
3120
3171
|
}
|
|
3172
|
+
/**
|
|
3173
|
+
* Returns the server URL from the underlying client, if available.
|
|
3174
|
+
*/
|
|
3121
3175
|
getServerUrl() {
|
|
3122
3176
|
return this.client.getServerUrl?.();
|
|
3123
3177
|
}
|
|
3178
|
+
/**
|
|
3179
|
+
* Returns the session ID — prefers the value reported by the underlying
|
|
3180
|
+
* client, falling back to the one injected at construction time.
|
|
3181
|
+
*/
|
|
3124
3182
|
getSessionId() {
|
|
3125
3183
|
return this.client.getSessionId?.() ?? this.sessionId;
|
|
3126
3184
|
}
|
|
3185
|
+
/**
|
|
3186
|
+
* Returns the **policy-filtered** list of tools that the current session
|
|
3187
|
+
* is allowed to call.
|
|
3188
|
+
*
|
|
3189
|
+
* Internally calls `client.fetchTools()` (which is cache-backed) so no
|
|
3190
|
+
* extra network round-trip is incurred when called after `fetchTools()`.
|
|
3191
|
+
*
|
|
3192
|
+
* @returns A `ListToolsResult` containing only the permitted tools.
|
|
3193
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3194
|
+
*/
|
|
3127
3195
|
async listTools() {
|
|
3128
3196
|
const session = await this.getSession();
|
|
3129
3197
|
const result = await this.client.fetchTools();
|
|
@@ -3133,20 +3201,61 @@ var ToolPolicyGateway = class {
|
|
|
3133
3201
|
tools
|
|
3134
3202
|
};
|
|
3135
3203
|
}
|
|
3204
|
+
/**
|
|
3205
|
+
* Returns the **complete, unfiltered** list of tools from the remote server,
|
|
3206
|
+
* bypassing any tool-access policy.
|
|
3207
|
+
*
|
|
3208
|
+
* Used by the management UI to show all available tools (including blocked
|
|
3209
|
+
* ones) so users can toggle individual tool access in the dialog.
|
|
3210
|
+
*
|
|
3211
|
+
* @returns The raw `ListToolsResult` from the remote server.
|
|
3212
|
+
*/
|
|
3136
3213
|
async listAllTools() {
|
|
3137
3214
|
return await this.client.fetchTools();
|
|
3138
3215
|
}
|
|
3216
|
+
/**
|
|
3217
|
+
* Executes a tool call on the remote server after verifying that the tool
|
|
3218
|
+
* is permitted by the current session's policy.
|
|
3219
|
+
*
|
|
3220
|
+
* @param name - The exact tool name to invoke.
|
|
3221
|
+
* @param args - Key/value arguments to pass to the tool.
|
|
3222
|
+
* @returns The tool's `CallToolResult`.
|
|
3223
|
+
* @throws {Error} When the tool is blocked by the session's policy.
|
|
3224
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3225
|
+
*/
|
|
3139
3226
|
async callTool(name, args) {
|
|
3140
3227
|
const session = await this.getSession();
|
|
3141
3228
|
this.assertAllowed(session, name);
|
|
3142
3229
|
return await this.client.callTool(name, args);
|
|
3143
3230
|
}
|
|
3231
|
+
/**
|
|
3232
|
+
* Filters a raw tools array down to only those permitted by the session's
|
|
3233
|
+
* `toolPolicy`.
|
|
3234
|
+
*
|
|
3235
|
+
* @param session - The session whose policy should be applied.
|
|
3236
|
+
* @param tools - The unfiltered list of tools from the remote server.
|
|
3237
|
+
* @returns A subset of `tools` that the policy allows.
|
|
3238
|
+
*/
|
|
3144
3239
|
filterTools(session, tools) {
|
|
3145
3240
|
return filterToolsByPolicy(tools, session.toolPolicy, this.getPolicyServerId(session));
|
|
3146
3241
|
}
|
|
3242
|
+
/**
|
|
3243
|
+
* Throws if `toolName` is blocked by the session's policy.
|
|
3244
|
+
* Call this before proxying a `callTool` request to the remote server.
|
|
3245
|
+
*
|
|
3246
|
+
* @param session - The session whose policy should be enforced.
|
|
3247
|
+
* @param toolName - The tool being invoked.
|
|
3248
|
+
* @throws {Error} When the tool is not permitted.
|
|
3249
|
+
*/
|
|
3147
3250
|
assertAllowed(session, toolName) {
|
|
3148
3251
|
assertToolAllowed(session.toolPolicy, toolName, this.getPolicyServerId(session));
|
|
3149
3252
|
}
|
|
3253
|
+
/**
|
|
3254
|
+
* Loads the session from the store and throws if it does not exist.
|
|
3255
|
+
*
|
|
3256
|
+
* @returns The fully-hydrated `Session` record.
|
|
3257
|
+
* @throws {Error} When the session cannot be found.
|
|
3258
|
+
*/
|
|
3150
3259
|
async getSession() {
|
|
3151
3260
|
const session = await sessions.get(this.userId, this.sessionId);
|
|
3152
3261
|
if (!session) {
|
|
@@ -3154,6 +3263,11 @@ var ToolPolicyGateway = class {
|
|
|
3154
3263
|
}
|
|
3155
3264
|
return session;
|
|
3156
3265
|
}
|
|
3266
|
+
/**
|
|
3267
|
+
* Resolves the server ID to use when evaluating tool policy.
|
|
3268
|
+
* Prefers the value from the live client (most accurate) and falls back
|
|
3269
|
+
* to the server ID stored on the session record.
|
|
3270
|
+
*/
|
|
3157
3271
|
getPolicyServerId(session) {
|
|
3158
3272
|
return this.client.getServerId?.() ?? session.serverId;
|
|
3159
3273
|
}
|
|
@@ -3538,7 +3652,7 @@ var SSEConnectionManager = class {
|
|
|
3538
3652
|
* Connect to an MCP server
|
|
3539
3653
|
*/
|
|
3540
3654
|
async connect(params) {
|
|
3541
|
-
const { serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3655
|
+
const { serverName, serverUrl, callbackUrl, transportType, clientId, clientSecret } = params;
|
|
3542
3656
|
const headers = normalizeHeaders(params.headers);
|
|
3543
3657
|
const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : generateServerId();
|
|
3544
3658
|
const existingSessions = await sessions.list(this.userId);
|
|
@@ -3567,6 +3681,8 @@ var SSEConnectionManager = class {
|
|
|
3567
3681
|
callbackUrl,
|
|
3568
3682
|
transportType,
|
|
3569
3683
|
headers,
|
|
3684
|
+
clientId,
|
|
3685
|
+
clientSecret,
|
|
3570
3686
|
...clientMetadata
|
|
3571
3687
|
// Spread client metadata (clientName, clientUri, logoUri, policyUri)
|
|
3572
3688
|
});
|
|
@@ -3608,7 +3724,7 @@ var SSEConnectionManager = class {
|
|
|
3608
3724
|
* and creates a fresh connection while reusing the existing session credentials in a single RPC call.
|
|
3609
3725
|
*/
|
|
3610
3726
|
async reconnect(params) {
|
|
3611
|
-
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3727
|
+
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType, clientId, clientSecret } = params;
|
|
3612
3728
|
const headers = normalizeHeaders(params.headers);
|
|
3613
3729
|
const serverId = rawServerId && rawServerId.length <= 12 ? rawServerId : generateServerId();
|
|
3614
3730
|
const existingSessions = await sessions.list(this.userId);
|
|
@@ -3634,6 +3750,8 @@ var SSEConnectionManager = class {
|
|
|
3634
3750
|
callbackUrl,
|
|
3635
3751
|
transportType,
|
|
3636
3752
|
headers,
|
|
3753
|
+
clientId,
|
|
3754
|
+
clientSecret,
|
|
3637
3755
|
...clientMetadata
|
|
3638
3756
|
});
|
|
3639
3757
|
this.clients.set(sessionId, client);
|
|
@@ -3709,12 +3827,29 @@ var SSEConnectionManager = class {
|
|
|
3709
3827
|
this.clients.set(sessionId, client);
|
|
3710
3828
|
return client;
|
|
3711
3829
|
}
|
|
3830
|
+
/**
|
|
3831
|
+
* Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
|
|
3832
|
+
*
|
|
3833
|
+
* Two lists are always published together:
|
|
3834
|
+
* - `tools` — policy-filtered list that agents are allowed to call.
|
|
3835
|
+
* - `allTools` — the complete, unfiltered list used by the management UI so
|
|
3836
|
+
* that blocked tools still appear as checkboxes in the dialog.
|
|
3837
|
+
*
|
|
3838
|
+
* `fetchTools()` is called first (populates the in-memory cache), then
|
|
3839
|
+
* `gateway.listTools()` re-uses that cache internally — so only one remote
|
|
3840
|
+
* network round-trip is made regardless of how many callers follow.
|
|
3841
|
+
*
|
|
3842
|
+
* @param sessionId - The session whose tools should be discovered.
|
|
3843
|
+
* @returns The session record and the policy-filtered tool list.
|
|
3844
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3845
|
+
*/
|
|
3712
3846
|
async listPolicyFilteredTools(sessionId) {
|
|
3713
3847
|
const session = await sessions.get(this.userId, sessionId);
|
|
3714
3848
|
if (!session) {
|
|
3715
3849
|
throw new Error("Session not found");
|
|
3716
3850
|
}
|
|
3717
3851
|
const client = await this.getOrCreateClient(sessionId);
|
|
3852
|
+
const allTools = await client.fetchTools().catch(() => ({ tools: [] }));
|
|
3718
3853
|
const gateway = createToolPolicyGateway(this.userId, sessionId, client);
|
|
3719
3854
|
const result = await gateway.listTools();
|
|
3720
3855
|
this.emitConnectionEvent({
|
|
@@ -3723,12 +3858,15 @@ var SSEConnectionManager = class {
|
|
|
3723
3858
|
serverId: session.serverId ?? "unknown",
|
|
3724
3859
|
toolCount: result.tools.length,
|
|
3725
3860
|
tools: result.tools,
|
|
3861
|
+
allTools: allTools.tools,
|
|
3726
3862
|
timestamp: Date.now()
|
|
3727
3863
|
});
|
|
3728
3864
|
return { session, result };
|
|
3729
3865
|
}
|
|
3730
3866
|
/**
|
|
3731
|
-
*
|
|
3867
|
+
* Returns the policy-filtered tool list for a session (agent-facing).
|
|
3868
|
+
* Internally re-uses `listPolicyFilteredTools` which also emits a
|
|
3869
|
+
* `tools_discovered` SSE event to keep client state up to date.
|
|
3732
3870
|
*/
|
|
3733
3871
|
async listTools(params) {
|
|
3734
3872
|
const { sessionId } = params;
|
|
@@ -3765,7 +3903,15 @@ var SSEConnectionManager = class {
|
|
|
3765
3903
|
};
|
|
3766
3904
|
}
|
|
3767
3905
|
/**
|
|
3768
|
-
*
|
|
3906
|
+
* Persists a new tool access policy for a session and broadcasts the updated
|
|
3907
|
+
* filtered tool list to all connected browser clients via a `tools_discovered` event.
|
|
3908
|
+
*
|
|
3909
|
+
* Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
|
|
3910
|
+
* so the management UI can immediately reflect the new checkbox states without
|
|
3911
|
+
* an additional round-trip to the server.
|
|
3912
|
+
*
|
|
3913
|
+
* @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
|
|
3914
|
+
* @throws {Error} When the session does not exist or the policy references unknown tool IDs.
|
|
3769
3915
|
*/
|
|
3770
3916
|
async setToolPolicy(params) {
|
|
3771
3917
|
const { sessionId } = params;
|
|
@@ -3785,6 +3931,7 @@ var SSEConnectionManager = class {
|
|
|
3785
3931
|
serverId: session.serverId ?? "unknown",
|
|
3786
3932
|
toolCount: filteredTools.length,
|
|
3787
3933
|
tools: filteredTools,
|
|
3934
|
+
allTools: allTools.tools,
|
|
3788
3935
|
timestamp: Date.now()
|
|
3789
3936
|
});
|
|
3790
3937
|
return {
|
|
@@ -3795,7 +3942,8 @@ var SSEConnectionManager = class {
|
|
|
3795
3942
|
};
|
|
3796
3943
|
}
|
|
3797
3944
|
/**
|
|
3798
|
-
*
|
|
3945
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
3946
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
3799
3947
|
*/
|
|
3800
3948
|
async callTool(params) {
|
|
3801
3949
|
const { sessionId, toolName, toolArgs } = params;
|