@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
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider, T as ToolClient } from './types-
|
|
1
|
+
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider, T as ToolClient } from './types-BkJ_rgzo.js';
|
|
2
2
|
import { ListToolsResult, CallToolResult, ListPromptsResult, GetPromptResult, ListResourcesResult, ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
4
4
|
import { OAuthClientMetadata, OAuthClientInformationMixed, OAuthClientInformationFull, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
@@ -208,11 +208,17 @@ declare class MCPClient {
|
|
|
208
208
|
*/
|
|
209
209
|
private tryConnect;
|
|
210
210
|
/**
|
|
211
|
-
* Connects to the MCP server
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
211
|
+
* Connects to the MCP server.
|
|
212
|
+
*
|
|
213
|
+
* Automatically validates and refreshes OAuth tokens if needed.
|
|
214
|
+
* Saves the session to Redis on first successful connection.
|
|
215
|
+
*
|
|
216
|
+
* The in-memory tools cache (`cachedTools`) is cleared at the start of every
|
|
217
|
+
* call so that a reconnection always fetches a fresh tool list from the remote
|
|
218
|
+
* server — even if the same `MCPClient` instance is reused.
|
|
219
|
+
*
|
|
220
|
+
* @throws {UnauthorizedError} When OAuth authorization is required.
|
|
221
|
+
* @throws {Error} When connection fails for other reasons.
|
|
216
222
|
*/
|
|
217
223
|
connect(): Promise<void>;
|
|
218
224
|
/**
|
|
@@ -223,8 +229,25 @@ declare class MCPClient {
|
|
|
223
229
|
*/
|
|
224
230
|
finishAuth(authCode: string, state?: string): Promise<void>;
|
|
225
231
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
232
|
+
* In-memory cache for the remote server's full tools list.
|
|
233
|
+
*
|
|
234
|
+
* Populated on the first `fetchTools()` call and reused for the lifetime of
|
|
235
|
+
* the connection. Cleared to `null` at the start of `connect()` so that a
|
|
236
|
+
* reconnect always retrieves a fresh list, and also in `dispose()` to release
|
|
237
|
+
* the memory when the client is no longer needed.
|
|
238
|
+
*/
|
|
239
|
+
private cachedTools;
|
|
240
|
+
/**
|
|
241
|
+
* Lists all available tools from the connected MCP server without emitting
|
|
242
|
+
* discovery events. The result is cached in memory for the lifetime of the
|
|
243
|
+
* connection — subsequent callers (e.g. `gateway.listTools()` running right
|
|
244
|
+
* after `fetchTools()`) pay zero extra network cost.
|
|
245
|
+
*
|
|
246
|
+
* Gateways use this to apply a tool-access policy before publishing the
|
|
247
|
+
* filtered list to agents or UI state.
|
|
248
|
+
*
|
|
249
|
+
* @returns The full `ListToolsResult` from the remote server.
|
|
250
|
+
* @throws {Error} When the client is not connected or the request times out.
|
|
228
251
|
*/
|
|
229
252
|
fetchTools(): Promise<ListToolsResult>;
|
|
230
253
|
/**
|
|
@@ -307,8 +330,11 @@ declare class MCPClient {
|
|
|
307
330
|
*/
|
|
308
331
|
disconnect(): Promise<void>;
|
|
309
332
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
333
|
+
* Disposes all event emitters and releases cached state.
|
|
334
|
+
*
|
|
335
|
+
* Clears `cachedTools` to free memory, and disposes the connection and
|
|
336
|
+
* observability event emitters so downstream listeners are unsubscribed.
|
|
337
|
+
* Call this when the client is permanently shut down (not just disconnected).
|
|
312
338
|
*/
|
|
313
339
|
dispose(): void;
|
|
314
340
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider, T as ToolClient } from './types-
|
|
1
|
+
import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider, T as ToolClient } from './types-BkJ_rgzo.mjs';
|
|
2
2
|
import { ListToolsResult, CallToolResult, ListPromptsResult, GetPromptResult, ListResourcesResult, ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
|
|
3
3
|
import { OAuthClientProvider } from '@modelcontextprotocol/sdk/client/auth.js';
|
|
4
4
|
import { OAuthClientMetadata, OAuthClientInformationMixed, OAuthClientInformationFull, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
@@ -208,11 +208,17 @@ declare class MCPClient {
|
|
|
208
208
|
*/
|
|
209
209
|
private tryConnect;
|
|
210
210
|
/**
|
|
211
|
-
* Connects to the MCP server
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
211
|
+
* Connects to the MCP server.
|
|
212
|
+
*
|
|
213
|
+
* Automatically validates and refreshes OAuth tokens if needed.
|
|
214
|
+
* Saves the session to Redis on first successful connection.
|
|
215
|
+
*
|
|
216
|
+
* The in-memory tools cache (`cachedTools`) is cleared at the start of every
|
|
217
|
+
* call so that a reconnection always fetches a fresh tool list from the remote
|
|
218
|
+
* server — even if the same `MCPClient` instance is reused.
|
|
219
|
+
*
|
|
220
|
+
* @throws {UnauthorizedError} When OAuth authorization is required.
|
|
221
|
+
* @throws {Error} When connection fails for other reasons.
|
|
216
222
|
*/
|
|
217
223
|
connect(): Promise<void>;
|
|
218
224
|
/**
|
|
@@ -223,8 +229,25 @@ declare class MCPClient {
|
|
|
223
229
|
*/
|
|
224
230
|
finishAuth(authCode: string, state?: string): Promise<void>;
|
|
225
231
|
/**
|
|
226
|
-
*
|
|
227
|
-
*
|
|
232
|
+
* In-memory cache for the remote server's full tools list.
|
|
233
|
+
*
|
|
234
|
+
* Populated on the first `fetchTools()` call and reused for the lifetime of
|
|
235
|
+
* the connection. Cleared to `null` at the start of `connect()` so that a
|
|
236
|
+
* reconnect always retrieves a fresh list, and also in `dispose()` to release
|
|
237
|
+
* the memory when the client is no longer needed.
|
|
238
|
+
*/
|
|
239
|
+
private cachedTools;
|
|
240
|
+
/**
|
|
241
|
+
* Lists all available tools from the connected MCP server without emitting
|
|
242
|
+
* discovery events. The result is cached in memory for the lifetime of the
|
|
243
|
+
* connection — subsequent callers (e.g. `gateway.listTools()` running right
|
|
244
|
+
* after `fetchTools()`) pay zero extra network cost.
|
|
245
|
+
*
|
|
246
|
+
* Gateways use this to apply a tool-access policy before publishing the
|
|
247
|
+
* filtered list to agents or UI state.
|
|
248
|
+
*
|
|
249
|
+
* @returns The full `ListToolsResult` from the remote server.
|
|
250
|
+
* @throws {Error} When the client is not connected or the request times out.
|
|
228
251
|
*/
|
|
229
252
|
fetchTools(): Promise<ListToolsResult>;
|
|
230
253
|
/**
|
|
@@ -307,8 +330,11 @@ declare class MCPClient {
|
|
|
307
330
|
*/
|
|
308
331
|
disconnect(): Promise<void>;
|
|
309
332
|
/**
|
|
310
|
-
*
|
|
311
|
-
*
|
|
333
|
+
* Disposes all event emitters and releases cached state.
|
|
334
|
+
*
|
|
335
|
+
* Clears `cachedTools` to free memory, and disposes the connection and
|
|
336
|
+
* observability event emitters so downstream listeners are unsubscribed.
|
|
337
|
+
* Call this when the client is permanently shut down (not just disconnected).
|
|
312
338
|
*/
|
|
313
339
|
dispose(): void;
|
|
314
340
|
/**
|
package/dist/server/index.d.mts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-
|
|
2
|
-
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-
|
|
1
|
+
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-DqzT8Oo7.mjs';
|
|
2
|
+
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-DqzT8Oo7.mjs';
|
|
3
3
|
export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.mjs';
|
|
4
|
-
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-
|
|
5
|
-
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-
|
|
4
|
+
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-BkJ_rgzo.mjs';
|
|
5
|
+
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-BkJ_rgzo.mjs';
|
|
6
6
|
export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
7
7
|
export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import '@modelcontextprotocol/sdk/client/auth.js';
|
|
@@ -92,9 +92,27 @@ declare class SSEConnectionManager {
|
|
|
92
92
|
* Get an existing client or create and connect a new one for the session.
|
|
93
93
|
*/
|
|
94
94
|
private getOrCreateClient;
|
|
95
|
+
/**
|
|
96
|
+
* Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
|
|
97
|
+
*
|
|
98
|
+
* Two lists are always published together:
|
|
99
|
+
* - `tools` — policy-filtered list that agents are allowed to call.
|
|
100
|
+
* - `allTools` — the complete, unfiltered list used by the management UI so
|
|
101
|
+
* that blocked tools still appear as checkboxes in the dialog.
|
|
102
|
+
*
|
|
103
|
+
* `fetchTools()` is called first (populates the in-memory cache), then
|
|
104
|
+
* `gateway.listTools()` re-uses that cache internally — so only one remote
|
|
105
|
+
* network round-trip is made regardless of how many callers follow.
|
|
106
|
+
*
|
|
107
|
+
* @param sessionId - The session whose tools should be discovered.
|
|
108
|
+
* @returns The session record and the policy-filtered tool list.
|
|
109
|
+
* @throws {Error} When the session does not exist in the store.
|
|
110
|
+
*/
|
|
95
111
|
private listPolicyFilteredTools;
|
|
96
112
|
/**
|
|
97
|
-
*
|
|
113
|
+
* Returns the policy-filtered tool list for a session (agent-facing).
|
|
114
|
+
* Internally re-uses `listPolicyFilteredTools` which also emits a
|
|
115
|
+
* `tools_discovered` SSE event to keep client state up to date.
|
|
98
116
|
*/
|
|
99
117
|
private listTools;
|
|
100
118
|
/**
|
|
@@ -102,11 +120,20 @@ declare class SSEConnectionManager {
|
|
|
102
120
|
*/
|
|
103
121
|
private getToolPolicy;
|
|
104
122
|
/**
|
|
105
|
-
*
|
|
123
|
+
* Persists a new tool access policy for a session and broadcasts the updated
|
|
124
|
+
* filtered tool list to all connected browser clients via a `tools_discovered` event.
|
|
125
|
+
*
|
|
126
|
+
* Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
|
|
127
|
+
* so the management UI can immediately reflect the new checkbox states without
|
|
128
|
+
* an additional round-trip to the server.
|
|
129
|
+
*
|
|
130
|
+
* @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
|
|
131
|
+
* @throws {Error} When the session does not exist or the policy references unknown tool IDs.
|
|
106
132
|
*/
|
|
107
133
|
private setToolPolicy;
|
|
108
134
|
/**
|
|
109
|
-
*
|
|
135
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
136
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
110
137
|
*/
|
|
111
138
|
private callTool;
|
|
112
139
|
/**
|
package/dist/server/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-
|
|
2
|
-
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-
|
|
1
|
+
import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-CuacvZaQ.js';
|
|
2
|
+
export { M as MCPClient, a as MultiSessionClient, S as Session, b as SessionMutationEvent, d as SessionMutationType, f as StorageOAuthClientProvider } from '../multi-session-client-CuacvZaQ.js';
|
|
3
3
|
export { U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.js';
|
|
4
|
-
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-
|
|
5
|
-
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-
|
|
4
|
+
import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-BkJ_rgzo.js';
|
|
5
|
+
export { a as CallToolRequest, b as CallToolResponse, f as ConnectRequest, g as ConnectResponse, k as Disposable, E as Emitter, m as Event, q as ListToolsResponse, s as McpConnectionState, T as ToolClient, A as ToolClientProvider, B as ToolInfo } from '../types-BkJ_rgzo.js';
|
|
6
6
|
export { OAuthClientInformation, OAuthClientInformationFull, OAuthClientMetadata, OAuthTokens } from '@modelcontextprotocol/sdk/shared/auth.js';
|
|
7
7
|
export { CallToolResult, ListToolsResult, Tool } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
import '@modelcontextprotocol/sdk/client/auth.js';
|
|
@@ -92,9 +92,27 @@ declare class SSEConnectionManager {
|
|
|
92
92
|
* Get an existing client or create and connect a new one for the session.
|
|
93
93
|
*/
|
|
94
94
|
private getOrCreateClient;
|
|
95
|
+
/**
|
|
96
|
+
* Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
|
|
97
|
+
*
|
|
98
|
+
* Two lists are always published together:
|
|
99
|
+
* - `tools` — policy-filtered list that agents are allowed to call.
|
|
100
|
+
* - `allTools` — the complete, unfiltered list used by the management UI so
|
|
101
|
+
* that blocked tools still appear as checkboxes in the dialog.
|
|
102
|
+
*
|
|
103
|
+
* `fetchTools()` is called first (populates the in-memory cache), then
|
|
104
|
+
* `gateway.listTools()` re-uses that cache internally — so only one remote
|
|
105
|
+
* network round-trip is made regardless of how many callers follow.
|
|
106
|
+
*
|
|
107
|
+
* @param sessionId - The session whose tools should be discovered.
|
|
108
|
+
* @returns The session record and the policy-filtered tool list.
|
|
109
|
+
* @throws {Error} When the session does not exist in the store.
|
|
110
|
+
*/
|
|
95
111
|
private listPolicyFilteredTools;
|
|
96
112
|
/**
|
|
97
|
-
*
|
|
113
|
+
* Returns the policy-filtered tool list for a session (agent-facing).
|
|
114
|
+
* Internally re-uses `listPolicyFilteredTools` which also emits a
|
|
115
|
+
* `tools_discovered` SSE event to keep client state up to date.
|
|
98
116
|
*/
|
|
99
117
|
private listTools;
|
|
100
118
|
/**
|
|
@@ -102,11 +120,20 @@ declare class SSEConnectionManager {
|
|
|
102
120
|
*/
|
|
103
121
|
private getToolPolicy;
|
|
104
122
|
/**
|
|
105
|
-
*
|
|
123
|
+
* Persists a new tool access policy for a session and broadcasts the updated
|
|
124
|
+
* filtered tool list to all connected browser clients via a `tools_discovered` event.
|
|
125
|
+
*
|
|
126
|
+
* Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
|
|
127
|
+
* so the management UI can immediately reflect the new checkbox states without
|
|
128
|
+
* an additional round-trip to the server.
|
|
129
|
+
*
|
|
130
|
+
* @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
|
|
131
|
+
* @throws {Error} When the session does not exist or the policy references unknown tool IDs.
|
|
106
132
|
*/
|
|
107
133
|
private setToolPolicy;
|
|
108
134
|
/**
|
|
109
|
-
*
|
|
135
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
136
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
110
137
|
*/
|
|
111
138
|
private callTool;
|
|
112
139
|
/**
|
package/dist/server/index.js
CHANGED
|
@@ -2009,6 +2009,15 @@ var StorageOAuthClientProvider = class {
|
|
|
2009
2009
|
if (data.clientId && !this._clientId) {
|
|
2010
2010
|
this._clientId = data.clientId;
|
|
2011
2011
|
}
|
|
2012
|
+
if (this._clientId && !data.clientId) {
|
|
2013
|
+
await this.patchCredentials({
|
|
2014
|
+
clientId: this._clientId,
|
|
2015
|
+
clientInformation: {
|
|
2016
|
+
client_id: this._clientId,
|
|
2017
|
+
...this.clientSecret ? { client_secret: this.clientSecret } : {}
|
|
2018
|
+
}
|
|
2019
|
+
});
|
|
2020
|
+
}
|
|
2012
2021
|
if (data.clientInformation) {
|
|
2013
2022
|
return data.clientInformation;
|
|
2014
2023
|
}
|
|
@@ -2245,6 +2254,15 @@ var MCPClient = class {
|
|
|
2245
2254
|
__publicField(this, "_onObservabilityEvent", new Emitter());
|
|
2246
2255
|
__publicField(this, "onObservabilityEvent", this._onObservabilityEvent.event);
|
|
2247
2256
|
__publicField(this, "currentState", "DISCONNECTED");
|
|
2257
|
+
/**
|
|
2258
|
+
* In-memory cache for the remote server's full tools list.
|
|
2259
|
+
*
|
|
2260
|
+
* Populated on the first `fetchTools()` call and reused for the lifetime of
|
|
2261
|
+
* the connection. Cleared to `null` at the start of `connect()` so that a
|
|
2262
|
+
* reconnect always retrieves a fresh list, and also in `dispose()` to release
|
|
2263
|
+
* the memory when the client is no longer needed.
|
|
2264
|
+
*/
|
|
2265
|
+
__publicField(this, "cachedTools", null);
|
|
2248
2266
|
this.serverUrl = options.serverUrl;
|
|
2249
2267
|
this.serverName = options.serverName;
|
|
2250
2268
|
this.callbackUrl = options.callbackUrl;
|
|
@@ -2565,13 +2583,20 @@ var MCPClient = class {
|
|
|
2565
2583
|
throw lastError || new Error("No transports available");
|
|
2566
2584
|
}
|
|
2567
2585
|
/**
|
|
2568
|
-
* Connects to the MCP server
|
|
2569
|
-
*
|
|
2570
|
-
*
|
|
2571
|
-
*
|
|
2572
|
-
*
|
|
2586
|
+
* Connects to the MCP server.
|
|
2587
|
+
*
|
|
2588
|
+
* Automatically validates and refreshes OAuth tokens if needed.
|
|
2589
|
+
* Saves the session to Redis on first successful connection.
|
|
2590
|
+
*
|
|
2591
|
+
* The in-memory tools cache (`cachedTools`) is cleared at the start of every
|
|
2592
|
+
* call so that a reconnection always fetches a fresh tool list from the remote
|
|
2593
|
+
* server — even if the same `MCPClient` instance is reused.
|
|
2594
|
+
*
|
|
2595
|
+
* @throws {UnauthorizedError} When OAuth authorization is required.
|
|
2596
|
+
* @throws {Error} When connection fails for other reasons.
|
|
2573
2597
|
*/
|
|
2574
2598
|
async connect() {
|
|
2599
|
+
this.cachedTools = null;
|
|
2575
2600
|
if (this.client.transport) {
|
|
2576
2601
|
this.transport = null;
|
|
2577
2602
|
try {
|
|
@@ -2754,17 +2779,30 @@ var MCPClient = class {
|
|
|
2754
2779
|
}
|
|
2755
2780
|
}
|
|
2756
2781
|
/**
|
|
2757
|
-
* Lists all available tools from the connected MCP server without emitting
|
|
2758
|
-
*
|
|
2782
|
+
* Lists all available tools from the connected MCP server without emitting
|
|
2783
|
+
* discovery events. The result is cached in memory for the lifetime of the
|
|
2784
|
+
* connection — subsequent callers (e.g. `gateway.listTools()` running right
|
|
2785
|
+
* after `fetchTools()`) pay zero extra network cost.
|
|
2786
|
+
*
|
|
2787
|
+
* Gateways use this to apply a tool-access policy before publishing the
|
|
2788
|
+
* filtered list to agents or UI state.
|
|
2789
|
+
*
|
|
2790
|
+
* @returns The full `ListToolsResult` from the remote server.
|
|
2791
|
+
* @throws {Error} When the client is not connected or the request times out.
|
|
2759
2792
|
*/
|
|
2760
2793
|
async fetchTools() {
|
|
2794
|
+
if (this.cachedTools) {
|
|
2795
|
+
return this.cachedTools;
|
|
2796
|
+
}
|
|
2761
2797
|
const request = {
|
|
2762
2798
|
method: "tools/list",
|
|
2763
2799
|
params: {}
|
|
2764
2800
|
};
|
|
2765
|
-
|
|
2801
|
+
const result = await this.withRetry(
|
|
2766
2802
|
() => this.client.request(request, types_js.ListToolsResultSchema)
|
|
2767
2803
|
);
|
|
2804
|
+
this.cachedTools = result;
|
|
2805
|
+
return result;
|
|
2768
2806
|
}
|
|
2769
2807
|
/**
|
|
2770
2808
|
* Lists all available tools from the connected MCP server
|
|
@@ -3050,10 +3088,14 @@ var MCPClient = class {
|
|
|
3050
3088
|
this.emitStateChange("DISCONNECTED");
|
|
3051
3089
|
}
|
|
3052
3090
|
/**
|
|
3053
|
-
*
|
|
3054
|
-
*
|
|
3091
|
+
* Disposes all event emitters and releases cached state.
|
|
3092
|
+
*
|
|
3093
|
+
* Clears `cachedTools` to free memory, and disposes the connection and
|
|
3094
|
+
* observability event emitters so downstream listeners are unsubscribed.
|
|
3095
|
+
* Call this when the client is permanently shut down (not just disconnected).
|
|
3055
3096
|
*/
|
|
3056
3097
|
dispose() {
|
|
3098
|
+
this.cachedTools = null;
|
|
3057
3099
|
this._onConnectionEvent.dispose();
|
|
3058
3100
|
this._onObservabilityEvent.dispose();
|
|
3059
3101
|
}
|
|
@@ -3112,21 +3154,47 @@ var ToolPolicyGateway = class {
|
|
|
3112
3154
|
this.sessionId = sessionId;
|
|
3113
3155
|
this.client = client;
|
|
3114
3156
|
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Returns whether the underlying MCP client transport is currently connected.
|
|
3159
|
+
*/
|
|
3115
3160
|
isConnected() {
|
|
3116
3161
|
return this.client.isConnected();
|
|
3117
3162
|
}
|
|
3163
|
+
/**
|
|
3164
|
+
* Returns the server ID from the underlying client, if available.
|
|
3165
|
+
*/
|
|
3118
3166
|
getServerId() {
|
|
3119
3167
|
return this.client.getServerId?.();
|
|
3120
3168
|
}
|
|
3169
|
+
/**
|
|
3170
|
+
* Returns the human-readable server name from the underlying client, if available.
|
|
3171
|
+
*/
|
|
3121
3172
|
getServerName() {
|
|
3122
3173
|
return this.client.getServerName?.();
|
|
3123
3174
|
}
|
|
3175
|
+
/**
|
|
3176
|
+
* Returns the server URL from the underlying client, if available.
|
|
3177
|
+
*/
|
|
3124
3178
|
getServerUrl() {
|
|
3125
3179
|
return this.client.getServerUrl?.();
|
|
3126
3180
|
}
|
|
3181
|
+
/**
|
|
3182
|
+
* Returns the session ID — prefers the value reported by the underlying
|
|
3183
|
+
* client, falling back to the one injected at construction time.
|
|
3184
|
+
*/
|
|
3127
3185
|
getSessionId() {
|
|
3128
3186
|
return this.client.getSessionId?.() ?? this.sessionId;
|
|
3129
3187
|
}
|
|
3188
|
+
/**
|
|
3189
|
+
* Returns the **policy-filtered** list of tools that the current session
|
|
3190
|
+
* is allowed to call.
|
|
3191
|
+
*
|
|
3192
|
+
* Internally calls `client.fetchTools()` (which is cache-backed) so no
|
|
3193
|
+
* extra network round-trip is incurred when called after `fetchTools()`.
|
|
3194
|
+
*
|
|
3195
|
+
* @returns A `ListToolsResult` containing only the permitted tools.
|
|
3196
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3197
|
+
*/
|
|
3130
3198
|
async listTools() {
|
|
3131
3199
|
const session = await this.getSession();
|
|
3132
3200
|
const result = await this.client.fetchTools();
|
|
@@ -3136,20 +3204,61 @@ var ToolPolicyGateway = class {
|
|
|
3136
3204
|
tools
|
|
3137
3205
|
};
|
|
3138
3206
|
}
|
|
3207
|
+
/**
|
|
3208
|
+
* Returns the **complete, unfiltered** list of tools from the remote server,
|
|
3209
|
+
* bypassing any tool-access policy.
|
|
3210
|
+
*
|
|
3211
|
+
* Used by the management UI to show all available tools (including blocked
|
|
3212
|
+
* ones) so users can toggle individual tool access in the dialog.
|
|
3213
|
+
*
|
|
3214
|
+
* @returns The raw `ListToolsResult` from the remote server.
|
|
3215
|
+
*/
|
|
3139
3216
|
async listAllTools() {
|
|
3140
3217
|
return await this.client.fetchTools();
|
|
3141
3218
|
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Executes a tool call on the remote server after verifying that the tool
|
|
3221
|
+
* is permitted by the current session's policy.
|
|
3222
|
+
*
|
|
3223
|
+
* @param name - The exact tool name to invoke.
|
|
3224
|
+
* @param args - Key/value arguments to pass to the tool.
|
|
3225
|
+
* @returns The tool's `CallToolResult`.
|
|
3226
|
+
* @throws {Error} When the tool is blocked by the session's policy.
|
|
3227
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3228
|
+
*/
|
|
3142
3229
|
async callTool(name, args) {
|
|
3143
3230
|
const session = await this.getSession();
|
|
3144
3231
|
this.assertAllowed(session, name);
|
|
3145
3232
|
return await this.client.callTool(name, args);
|
|
3146
3233
|
}
|
|
3234
|
+
/**
|
|
3235
|
+
* Filters a raw tools array down to only those permitted by the session's
|
|
3236
|
+
* `toolPolicy`.
|
|
3237
|
+
*
|
|
3238
|
+
* @param session - The session whose policy should be applied.
|
|
3239
|
+
* @param tools - The unfiltered list of tools from the remote server.
|
|
3240
|
+
* @returns A subset of `tools` that the policy allows.
|
|
3241
|
+
*/
|
|
3147
3242
|
filterTools(session, tools) {
|
|
3148
3243
|
return filterToolsByPolicy(tools, session.toolPolicy, this.getPolicyServerId(session));
|
|
3149
3244
|
}
|
|
3245
|
+
/**
|
|
3246
|
+
* Throws if `toolName` is blocked by the session's policy.
|
|
3247
|
+
* Call this before proxying a `callTool` request to the remote server.
|
|
3248
|
+
*
|
|
3249
|
+
* @param session - The session whose policy should be enforced.
|
|
3250
|
+
* @param toolName - The tool being invoked.
|
|
3251
|
+
* @throws {Error} When the tool is not permitted.
|
|
3252
|
+
*/
|
|
3150
3253
|
assertAllowed(session, toolName) {
|
|
3151
3254
|
assertToolAllowed(session.toolPolicy, toolName, this.getPolicyServerId(session));
|
|
3152
3255
|
}
|
|
3256
|
+
/**
|
|
3257
|
+
* Loads the session from the store and throws if it does not exist.
|
|
3258
|
+
*
|
|
3259
|
+
* @returns The fully-hydrated `Session` record.
|
|
3260
|
+
* @throws {Error} When the session cannot be found.
|
|
3261
|
+
*/
|
|
3153
3262
|
async getSession() {
|
|
3154
3263
|
const session = await sessions.get(this.userId, this.sessionId);
|
|
3155
3264
|
if (!session) {
|
|
@@ -3157,6 +3266,11 @@ var ToolPolicyGateway = class {
|
|
|
3157
3266
|
}
|
|
3158
3267
|
return session;
|
|
3159
3268
|
}
|
|
3269
|
+
/**
|
|
3270
|
+
* Resolves the server ID to use when evaluating tool policy.
|
|
3271
|
+
* Prefers the value from the live client (most accurate) and falls back
|
|
3272
|
+
* to the server ID stored on the session record.
|
|
3273
|
+
*/
|
|
3160
3274
|
getPolicyServerId(session) {
|
|
3161
3275
|
return this.client.getServerId?.() ?? session.serverId;
|
|
3162
3276
|
}
|
|
@@ -3545,7 +3659,7 @@ var SSEConnectionManager = class {
|
|
|
3545
3659
|
* Connect to an MCP server
|
|
3546
3660
|
*/
|
|
3547
3661
|
async connect(params) {
|
|
3548
|
-
const { serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3662
|
+
const { serverName, serverUrl, callbackUrl, transportType, clientId, clientSecret } = params;
|
|
3549
3663
|
const headers = normalizeHeaders(params.headers);
|
|
3550
3664
|
const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : generateServerId();
|
|
3551
3665
|
const existingSessions = await sessions.list(this.userId);
|
|
@@ -3574,6 +3688,8 @@ var SSEConnectionManager = class {
|
|
|
3574
3688
|
callbackUrl,
|
|
3575
3689
|
transportType,
|
|
3576
3690
|
headers,
|
|
3691
|
+
clientId,
|
|
3692
|
+
clientSecret,
|
|
3577
3693
|
...clientMetadata
|
|
3578
3694
|
// Spread client metadata (clientName, clientUri, logoUri, policyUri)
|
|
3579
3695
|
});
|
|
@@ -3615,7 +3731,7 @@ var SSEConnectionManager = class {
|
|
|
3615
3731
|
* and creates a fresh connection while reusing the existing session credentials in a single RPC call.
|
|
3616
3732
|
*/
|
|
3617
3733
|
async reconnect(params) {
|
|
3618
|
-
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3734
|
+
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType, clientId, clientSecret } = params;
|
|
3619
3735
|
const headers = normalizeHeaders(params.headers);
|
|
3620
3736
|
const serverId = rawServerId && rawServerId.length <= 12 ? rawServerId : generateServerId();
|
|
3621
3737
|
const existingSessions = await sessions.list(this.userId);
|
|
@@ -3641,6 +3757,8 @@ var SSEConnectionManager = class {
|
|
|
3641
3757
|
callbackUrl,
|
|
3642
3758
|
transportType,
|
|
3643
3759
|
headers,
|
|
3760
|
+
clientId,
|
|
3761
|
+
clientSecret,
|
|
3644
3762
|
...clientMetadata
|
|
3645
3763
|
});
|
|
3646
3764
|
this.clients.set(sessionId, client);
|
|
@@ -3716,12 +3834,29 @@ var SSEConnectionManager = class {
|
|
|
3716
3834
|
this.clients.set(sessionId, client);
|
|
3717
3835
|
return client;
|
|
3718
3836
|
}
|
|
3837
|
+
/**
|
|
3838
|
+
* Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
|
|
3839
|
+
*
|
|
3840
|
+
* Two lists are always published together:
|
|
3841
|
+
* - `tools` — policy-filtered list that agents are allowed to call.
|
|
3842
|
+
* - `allTools` — the complete, unfiltered list used by the management UI so
|
|
3843
|
+
* that blocked tools still appear as checkboxes in the dialog.
|
|
3844
|
+
*
|
|
3845
|
+
* `fetchTools()` is called first (populates the in-memory cache), then
|
|
3846
|
+
* `gateway.listTools()` re-uses that cache internally — so only one remote
|
|
3847
|
+
* network round-trip is made regardless of how many callers follow.
|
|
3848
|
+
*
|
|
3849
|
+
* @param sessionId - The session whose tools should be discovered.
|
|
3850
|
+
* @returns The session record and the policy-filtered tool list.
|
|
3851
|
+
* @throws {Error} When the session does not exist in the store.
|
|
3852
|
+
*/
|
|
3719
3853
|
async listPolicyFilteredTools(sessionId) {
|
|
3720
3854
|
const session = await sessions.get(this.userId, sessionId);
|
|
3721
3855
|
if (!session) {
|
|
3722
3856
|
throw new Error("Session not found");
|
|
3723
3857
|
}
|
|
3724
3858
|
const client = await this.getOrCreateClient(sessionId);
|
|
3859
|
+
const allTools = await client.fetchTools().catch(() => ({ tools: [] }));
|
|
3725
3860
|
const gateway = createToolPolicyGateway(this.userId, sessionId, client);
|
|
3726
3861
|
const result = await gateway.listTools();
|
|
3727
3862
|
this.emitConnectionEvent({
|
|
@@ -3730,12 +3865,15 @@ var SSEConnectionManager = class {
|
|
|
3730
3865
|
serverId: session.serverId ?? "unknown",
|
|
3731
3866
|
toolCount: result.tools.length,
|
|
3732
3867
|
tools: result.tools,
|
|
3868
|
+
allTools: allTools.tools,
|
|
3733
3869
|
timestamp: Date.now()
|
|
3734
3870
|
});
|
|
3735
3871
|
return { session, result };
|
|
3736
3872
|
}
|
|
3737
3873
|
/**
|
|
3738
|
-
*
|
|
3874
|
+
* Returns the policy-filtered tool list for a session (agent-facing).
|
|
3875
|
+
* Internally re-uses `listPolicyFilteredTools` which also emits a
|
|
3876
|
+
* `tools_discovered` SSE event to keep client state up to date.
|
|
3739
3877
|
*/
|
|
3740
3878
|
async listTools(params) {
|
|
3741
3879
|
const { sessionId } = params;
|
|
@@ -3772,7 +3910,15 @@ var SSEConnectionManager = class {
|
|
|
3772
3910
|
};
|
|
3773
3911
|
}
|
|
3774
3912
|
/**
|
|
3775
|
-
*
|
|
3913
|
+
* Persists a new tool access policy for a session and broadcasts the updated
|
|
3914
|
+
* filtered tool list to all connected browser clients via a `tools_discovered` event.
|
|
3915
|
+
*
|
|
3916
|
+
* Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
|
|
3917
|
+
* so the management UI can immediately reflect the new checkbox states without
|
|
3918
|
+
* an additional round-trip to the server.
|
|
3919
|
+
*
|
|
3920
|
+
* @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
|
|
3921
|
+
* @throws {Error} When the session does not exist or the policy references unknown tool IDs.
|
|
3776
3922
|
*/
|
|
3777
3923
|
async setToolPolicy(params) {
|
|
3778
3924
|
const { sessionId } = params;
|
|
@@ -3792,6 +3938,7 @@ var SSEConnectionManager = class {
|
|
|
3792
3938
|
serverId: session.serverId ?? "unknown",
|
|
3793
3939
|
toolCount: filteredTools.length,
|
|
3794
3940
|
tools: filteredTools,
|
|
3941
|
+
allTools: allTools.tools,
|
|
3795
3942
|
timestamp: Date.now()
|
|
3796
3943
|
});
|
|
3797
3944
|
return {
|
|
@@ -3802,7 +3949,8 @@ var SSEConnectionManager = class {
|
|
|
3802
3949
|
};
|
|
3803
3950
|
}
|
|
3804
3951
|
/**
|
|
3805
|
-
*
|
|
3952
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
3953
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
3806
3954
|
*/
|
|
3807
3955
|
async callTool(params) {
|
|
3808
3956
|
const { sessionId, toolName, toolArgs } = params;
|