@mcp-ts/sdk 2.5.1 → 2.5.2
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-B3GPsPsi.d.mts} +1 -1
- package/dist/{index-BEdyuz1M.d.ts → index-gNdSQTSz.d.ts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +148 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +148 -13
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CclWRxTD.d.mts → multi-session-client-CB4oDrQX.d.ts} +36 -10
- package/dist/{multi-session-client-DzvZD6Tt.d.ts → multi-session-client-xj3iQIv6.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 +148 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +148 -13
- 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-C-Mw1_BQ.d.ts} +1 -1
- package/dist/{tool-router-C9ECn3FX.d.mts → tool-router-CsKVXbQB.d.mts} +1 -1
- package/dist/{types-CbFbPkfQ.d.mts → types-6SmXege4.d.mts} +1 -0
- package/dist/{types-CbFbPkfQ.d.ts → types-6SmXege4.d.ts} +1 -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 +35 -3
- package/src/server/mcp/oauth-client.ts +44 -20
- 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/dist/server/index.mjs
CHANGED
|
@@ -2174,6 +2174,15 @@ var MCPClient = class {
|
|
|
2174
2174
|
__publicField(this, "_onObservabilityEvent", new Emitter());
|
|
2175
2175
|
__publicField(this, "onObservabilityEvent", this._onObservabilityEvent.event);
|
|
2176
2176
|
__publicField(this, "currentState", "DISCONNECTED");
|
|
2177
|
+
/**
|
|
2178
|
+
* In-memory cache for the remote server's full tools list.
|
|
2179
|
+
*
|
|
2180
|
+
* Populated on the first `fetchTools()` call and reused for the lifetime of
|
|
2181
|
+
* the connection. Cleared to `null` at the start of `connect()` so that a
|
|
2182
|
+
* reconnect always retrieves a fresh list, and also in `dispose()` to release
|
|
2183
|
+
* the memory when the client is no longer needed.
|
|
2184
|
+
*/
|
|
2185
|
+
__publicField(this, "cachedTools", null);
|
|
2177
2186
|
this.serverUrl = options.serverUrl;
|
|
2178
2187
|
this.serverName = options.serverName;
|
|
2179
2188
|
this.callbackUrl = options.callbackUrl;
|
|
@@ -2494,13 +2503,20 @@ var MCPClient = class {
|
|
|
2494
2503
|
throw lastError || new Error("No transports available");
|
|
2495
2504
|
}
|
|
2496
2505
|
/**
|
|
2497
|
-
* Connects to the MCP server
|
|
2498
|
-
*
|
|
2499
|
-
*
|
|
2500
|
-
*
|
|
2501
|
-
*
|
|
2506
|
+
* Connects to the MCP server.
|
|
2507
|
+
*
|
|
2508
|
+
* Automatically validates and refreshes OAuth tokens if needed.
|
|
2509
|
+
* Saves the session to Redis on first successful connection.
|
|
2510
|
+
*
|
|
2511
|
+
* The in-memory tools cache (`cachedTools`) is cleared at the start of every
|
|
2512
|
+
* call so that a reconnection always fetches a fresh tool list from the remote
|
|
2513
|
+
* server — even if the same `MCPClient` instance is reused.
|
|
2514
|
+
*
|
|
2515
|
+
* @throws {UnauthorizedError} When OAuth authorization is required.
|
|
2516
|
+
* @throws {Error} When connection fails for other reasons.
|
|
2502
2517
|
*/
|
|
2503
2518
|
async connect() {
|
|
2519
|
+
this.cachedTools = null;
|
|
2504
2520
|
if (this.client.transport) {
|
|
2505
2521
|
this.transport = null;
|
|
2506
2522
|
try {
|
|
@@ -2683,17 +2699,30 @@ var MCPClient = class {
|
|
|
2683
2699
|
}
|
|
2684
2700
|
}
|
|
2685
2701
|
/**
|
|
2686
|
-
* Lists all available tools from the connected MCP server without emitting
|
|
2687
|
-
*
|
|
2702
|
+
* Lists all available tools from the connected MCP server without emitting
|
|
2703
|
+
* discovery events. The result is cached in memory for the lifetime of the
|
|
2704
|
+
* connection — subsequent callers (e.g. `gateway.listTools()` running right
|
|
2705
|
+
* after `fetchTools()`) pay zero extra network cost.
|
|
2706
|
+
*
|
|
2707
|
+
* Gateways use this to apply a tool-access policy before publishing the
|
|
2708
|
+
* filtered list to agents or UI state.
|
|
2709
|
+
*
|
|
2710
|
+
* @returns The full `ListToolsResult` from the remote server.
|
|
2711
|
+
* @throws {Error} When the client is not connected or the request times out.
|
|
2688
2712
|
*/
|
|
2689
2713
|
async fetchTools() {
|
|
2714
|
+
if (this.cachedTools) {
|
|
2715
|
+
return this.cachedTools;
|
|
2716
|
+
}
|
|
2690
2717
|
const request = {
|
|
2691
2718
|
method: "tools/list",
|
|
2692
2719
|
params: {}
|
|
2693
2720
|
};
|
|
2694
|
-
|
|
2721
|
+
const result = await this.withRetry(
|
|
2695
2722
|
() => this.client.request(request, ListToolsResultSchema)
|
|
2696
2723
|
);
|
|
2724
|
+
this.cachedTools = result;
|
|
2725
|
+
return result;
|
|
2697
2726
|
}
|
|
2698
2727
|
/**
|
|
2699
2728
|
* Lists all available tools from the connected MCP server
|
|
@@ -2979,10 +3008,14 @@ var MCPClient = class {
|
|
|
2979
3008
|
this.emitStateChange("DISCONNECTED");
|
|
2980
3009
|
}
|
|
2981
3010
|
/**
|
|
2982
|
-
*
|
|
2983
|
-
*
|
|
3011
|
+
* Disposes all event emitters and releases cached state.
|
|
3012
|
+
*
|
|
3013
|
+
* Clears `cachedTools` to free memory, and disposes the connection and
|
|
3014
|
+
* observability event emitters so downstream listeners are unsubscribed.
|
|
3015
|
+
* Call this when the client is permanently shut down (not just disconnected).
|
|
2984
3016
|
*/
|
|
2985
3017
|
dispose() {
|
|
3018
|
+
this.cachedTools = null;
|
|
2986
3019
|
this._onConnectionEvent.dispose();
|
|
2987
3020
|
this._onObservabilityEvent.dispose();
|
|
2988
3021
|
}
|
|
@@ -3037,21 +3070,47 @@ var ToolPolicyGateway = class {
|
|
|
3037
3070
|
this.sessionId = sessionId;
|
|
3038
3071
|
this.client = client;
|
|
3039
3072
|
}
|
|
3073
|
+
/**
|
|
3074
|
+
* Returns whether the underlying MCP client transport is currently connected.
|
|
3075
|
+
*/
|
|
3040
3076
|
isConnected() {
|
|
3041
3077
|
return this.client.isConnected();
|
|
3042
3078
|
}
|
|
3079
|
+
/**
|
|
3080
|
+
* Returns the server ID from the underlying client, if available.
|
|
3081
|
+
*/
|
|
3043
3082
|
getServerId() {
|
|
3044
3083
|
return this.client.getServerId?.();
|
|
3045
3084
|
}
|
|
3085
|
+
/**
|
|
3086
|
+
* Returns the human-readable server name from the underlying client, if available.
|
|
3087
|
+
*/
|
|
3046
3088
|
getServerName() {
|
|
3047
3089
|
return this.client.getServerName?.();
|
|
3048
3090
|
}
|
|
3091
|
+
/**
|
|
3092
|
+
* Returns the server URL from the underlying client, if available.
|
|
3093
|
+
*/
|
|
3049
3094
|
getServerUrl() {
|
|
3050
3095
|
return this.client.getServerUrl?.();
|
|
3051
3096
|
}
|
|
3097
|
+
/**
|
|
3098
|
+
* Returns the session ID — prefers the value reported by the underlying
|
|
3099
|
+
* client, falling back to the one injected at construction time.
|
|
3100
|
+
*/
|
|
3052
3101
|
getSessionId() {
|
|
3053
3102
|
return this.client.getSessionId?.() ?? this.sessionId;
|
|
3054
3103
|
}
|
|
3104
|
+
/**
|
|
3105
|
+
* Returns the **policy-filtered** list of tools that the current session
|
|
3106
|
+
* is allowed to call.
|
|
3107
|
+
*
|
|
3108
|
+
* Internally calls `client.fetchTools()` (which is cache-backed) so no
|
|
3109
|
+
* extra network round-trip is incurred when called after `fetchTools()`.
|
|
3110
|
+
*
|
|
3111
|
+
* @returns A `ListToolsResult` containing only the permitted tools.
|
|
3112
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3113
|
+
*/
|
|
3055
3114
|
async listTools() {
|
|
3056
3115
|
const session = await this.getSession();
|
|
3057
3116
|
const result = await this.client.fetchTools();
|
|
@@ -3061,20 +3120,61 @@ var ToolPolicyGateway = class {
|
|
|
3061
3120
|
tools
|
|
3062
3121
|
};
|
|
3063
3122
|
}
|
|
3123
|
+
/**
|
|
3124
|
+
* Returns the **complete, unfiltered** list of tools from the remote server,
|
|
3125
|
+
* bypassing any tool-access policy.
|
|
3126
|
+
*
|
|
3127
|
+
* Used by the management UI to show all available tools (including blocked
|
|
3128
|
+
* ones) so users can toggle individual tool access in the dialog.
|
|
3129
|
+
*
|
|
3130
|
+
* @returns The raw `ListToolsResult` from the remote server.
|
|
3131
|
+
*/
|
|
3064
3132
|
async listAllTools() {
|
|
3065
3133
|
return await this.client.fetchTools();
|
|
3066
3134
|
}
|
|
3135
|
+
/**
|
|
3136
|
+
* Executes a tool call on the remote server after verifying that the tool
|
|
3137
|
+
* is permitted by the current session's policy.
|
|
3138
|
+
*
|
|
3139
|
+
* @param name - The exact tool name to invoke.
|
|
3140
|
+
* @param args - Key/value arguments to pass to the tool.
|
|
3141
|
+
* @returns The tool's `CallToolResult`.
|
|
3142
|
+
* @throws {Error} When the tool is blocked by the session's policy.
|
|
3143
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3144
|
+
*/
|
|
3067
3145
|
async callTool(name, args) {
|
|
3068
3146
|
const session = await this.getSession();
|
|
3069
3147
|
this.assertAllowed(session, name);
|
|
3070
3148
|
return await this.client.callTool(name, args);
|
|
3071
3149
|
}
|
|
3150
|
+
/**
|
|
3151
|
+
* Filters a raw tools array down to only those permitted by the session's
|
|
3152
|
+
* `toolPolicy`.
|
|
3153
|
+
*
|
|
3154
|
+
* @param session - The session whose policy should be applied.
|
|
3155
|
+
* @param tools - The unfiltered list of tools from the remote server.
|
|
3156
|
+
* @returns A subset of `tools` that the policy allows.
|
|
3157
|
+
*/
|
|
3072
3158
|
filterTools(session, tools) {
|
|
3073
3159
|
return filterToolsByPolicy(tools, session.toolPolicy, this.getPolicyServerId(session));
|
|
3074
3160
|
}
|
|
3161
|
+
/**
|
|
3162
|
+
* Throws if `toolName` is blocked by the session's policy.
|
|
3163
|
+
* Call this before proxying a `callTool` request to the remote server.
|
|
3164
|
+
*
|
|
3165
|
+
* @param session - The session whose policy should be enforced.
|
|
3166
|
+
* @param toolName - The tool being invoked.
|
|
3167
|
+
* @throws {Error} When the tool is not permitted.
|
|
3168
|
+
*/
|
|
3075
3169
|
assertAllowed(session, toolName) {
|
|
3076
3170
|
assertToolAllowed(session.toolPolicy, toolName, this.getPolicyServerId(session));
|
|
3077
3171
|
}
|
|
3172
|
+
/**
|
|
3173
|
+
* Loads the session from the store and throws if it does not exist.
|
|
3174
|
+
*
|
|
3175
|
+
* @returns The fully-hydrated `Session` record.
|
|
3176
|
+
* @throws {Error} When the session cannot be found.
|
|
3177
|
+
*/
|
|
3078
3178
|
async getSession() {
|
|
3079
3179
|
const session = await sessions.get(this.userId, this.sessionId);
|
|
3080
3180
|
if (!session) {
|
|
@@ -3082,6 +3182,11 @@ var ToolPolicyGateway = class {
|
|
|
3082
3182
|
}
|
|
3083
3183
|
return session;
|
|
3084
3184
|
}
|
|
3185
|
+
/**
|
|
3186
|
+
* Resolves the server ID to use when evaluating tool policy.
|
|
3187
|
+
* Prefers the value from the live client (most accurate) and falls back
|
|
3188
|
+
* to the server ID stored on the session record.
|
|
3189
|
+
*/
|
|
3085
3190
|
getPolicyServerId(session) {
|
|
3086
3191
|
return this.client.getServerId?.() ?? session.serverId;
|
|
3087
3192
|
}
|
|
@@ -3637,12 +3742,29 @@ var SSEConnectionManager = class {
|
|
|
3637
3742
|
this.clients.set(sessionId, client);
|
|
3638
3743
|
return client;
|
|
3639
3744
|
}
|
|
3745
|
+
/**
|
|
3746
|
+
* Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
|
|
3747
|
+
*
|
|
3748
|
+
* Two lists are always published together:
|
|
3749
|
+
* - `tools` — policy-filtered list that agents are allowed to call.
|
|
3750
|
+
* - `allTools` — the complete, unfiltered list used by the management UI so
|
|
3751
|
+
* that blocked tools still appear as checkboxes in the dialog.
|
|
3752
|
+
*
|
|
3753
|
+
* `fetchTools()` is called first (populates the in-memory cache), then
|
|
3754
|
+
* `gateway.listTools()` re-uses that cache internally — so only one remote
|
|
3755
|
+
* network round-trip is made regardless of how many callers follow.
|
|
3756
|
+
*
|
|
3757
|
+
* @param sessionId - The session whose tools should be discovered.
|
|
3758
|
+
* @returns The session record and the policy-filtered tool list.
|
|
3759
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3760
|
+
*/
|
|
3640
3761
|
async listPolicyFilteredTools(sessionId) {
|
|
3641
3762
|
const session = await sessions.get(this.userId, sessionId);
|
|
3642
3763
|
if (!session) {
|
|
3643
3764
|
throw new Error("Session not found");
|
|
3644
3765
|
}
|
|
3645
3766
|
const client = await this.getOrCreateClient(sessionId);
|
|
3767
|
+
const allTools = await client.fetchTools().catch(() => ({ tools: [] }));
|
|
3646
3768
|
const gateway = createToolPolicyGateway(this.userId, sessionId, client);
|
|
3647
3769
|
const result = await gateway.listTools();
|
|
3648
3770
|
this.emitConnectionEvent({
|
|
@@ -3651,12 +3773,15 @@ var SSEConnectionManager = class {
|
|
|
3651
3773
|
serverId: session.serverId ?? "unknown",
|
|
3652
3774
|
toolCount: result.tools.length,
|
|
3653
3775
|
tools: result.tools,
|
|
3776
|
+
allTools: allTools.tools,
|
|
3654
3777
|
timestamp: Date.now()
|
|
3655
3778
|
});
|
|
3656
3779
|
return { session, result };
|
|
3657
3780
|
}
|
|
3658
3781
|
/**
|
|
3659
|
-
*
|
|
3782
|
+
* Returns the policy-filtered tool list for a session (agent-facing).
|
|
3783
|
+
* Internally re-uses `listPolicyFilteredTools` which also emits a
|
|
3784
|
+
* `tools_discovered` SSE event to keep client state up to date.
|
|
3660
3785
|
*/
|
|
3661
3786
|
async listTools(params) {
|
|
3662
3787
|
const { sessionId } = params;
|
|
@@ -3693,7 +3818,15 @@ var SSEConnectionManager = class {
|
|
|
3693
3818
|
};
|
|
3694
3819
|
}
|
|
3695
3820
|
/**
|
|
3696
|
-
*
|
|
3821
|
+
* Persists a new tool access policy for a session and broadcasts the updated
|
|
3822
|
+
* filtered tool list to all connected browser clients via a `tools_discovered` event.
|
|
3823
|
+
*
|
|
3824
|
+
* Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
|
|
3825
|
+
* so the management UI can immediately reflect the new checkbox states without
|
|
3826
|
+
* an additional round-trip to the server.
|
|
3827
|
+
*
|
|
3828
|
+
* @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
|
|
3829
|
+
* @throws {Error} When the session does not exist or the policy references unknown tool IDs.
|
|
3697
3830
|
*/
|
|
3698
3831
|
async setToolPolicy(params) {
|
|
3699
3832
|
const { sessionId } = params;
|
|
@@ -3713,6 +3846,7 @@ var SSEConnectionManager = class {
|
|
|
3713
3846
|
serverId: session.serverId ?? "unknown",
|
|
3714
3847
|
toolCount: filteredTools.length,
|
|
3715
3848
|
tools: filteredTools,
|
|
3849
|
+
allTools: allTools.tools,
|
|
3716
3850
|
timestamp: Date.now()
|
|
3717
3851
|
});
|
|
3718
3852
|
return {
|
|
@@ -3723,7 +3857,8 @@ var SSEConnectionManager = class {
|
|
|
3723
3857
|
};
|
|
3724
3858
|
}
|
|
3725
3859
|
/**
|
|
3726
|
-
*
|
|
3860
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
3861
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
3727
3862
|
*/
|
|
3728
3863
|
async callTool(params) {
|
|
3729
3864
|
const { sessionId, toolName, toolArgs } = params;
|