@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.
Files changed (56) hide show
  1. package/dist/adapters/agui-adapter.d.mts +3 -3
  2. package/dist/adapters/agui-adapter.d.ts +3 -3
  3. package/dist/adapters/agui-middleware.d.mts +3 -3
  4. package/dist/adapters/agui-middleware.d.ts +3 -3
  5. package/dist/adapters/ai-adapter.d.mts +3 -3
  6. package/dist/adapters/ai-adapter.d.ts +3 -3
  7. package/dist/adapters/langchain-adapter.d.mts +3 -3
  8. package/dist/adapters/langchain-adapter.d.ts +3 -3
  9. package/dist/adapters/mastra-adapter.d.mts +2 -2
  10. package/dist/adapters/mastra-adapter.d.ts +2 -2
  11. package/dist/client/index.d.mts +2 -2
  12. package/dist/client/index.d.ts +2 -2
  13. package/dist/client/react.d.mts +4 -4
  14. package/dist/client/react.d.ts +4 -4
  15. package/dist/client/react.js +1 -1
  16. package/dist/client/react.js.map +1 -1
  17. package/dist/client/react.mjs +1 -1
  18. package/dist/client/react.mjs.map +1 -1
  19. package/dist/client/vue.d.mts +5 -4
  20. package/dist/client/vue.d.ts +5 -4
  21. package/dist/client/vue.js +1 -1
  22. package/dist/client/vue.js.map +1 -1
  23. package/dist/client/vue.mjs +1 -1
  24. package/dist/client/vue.mjs.map +1 -1
  25. package/dist/{index-C99wE2Zf.d.mts → index-B3GPsPsi.d.mts} +1 -1
  26. package/dist/{index-BEdyuz1M.d.ts → index-gNdSQTSz.d.ts} +1 -1
  27. package/dist/index.d.mts +4 -4
  28. package/dist/index.d.ts +4 -4
  29. package/dist/index.js +148 -13
  30. package/dist/index.js.map +1 -1
  31. package/dist/index.mjs +148 -13
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/{multi-session-client-CclWRxTD.d.mts → multi-session-client-CB4oDrQX.d.ts} +36 -10
  34. package/dist/{multi-session-client-DzvZD6Tt.d.ts → multi-session-client-xj3iQIv6.d.mts} +36 -10
  35. package/dist/server/index.d.mts +34 -7
  36. package/dist/server/index.d.ts +34 -7
  37. package/dist/server/index.js +148 -13
  38. package/dist/server/index.js.map +1 -1
  39. package/dist/server/index.mjs +148 -13
  40. package/dist/server/index.mjs.map +1 -1
  41. package/dist/shared/index.d.mts +4 -4
  42. package/dist/shared/index.d.ts +4 -4
  43. package/dist/shared/index.js.map +1 -1
  44. package/dist/shared/index.mjs.map +1 -1
  45. package/dist/{tool-router-CUSSk6lT.d.ts → tool-router-C-Mw1_BQ.d.ts} +1 -1
  46. package/dist/{tool-router-C9ECn3FX.d.mts → tool-router-CsKVXbQB.d.mts} +1 -1
  47. package/dist/{types-CbFbPkfQ.d.mts → types-6SmXege4.d.mts} +1 -0
  48. package/dist/{types-CbFbPkfQ.d.ts → types-6SmXege4.d.ts} +1 -0
  49. package/package.json +1 -1
  50. package/src/client/react/use-mcp.ts +1 -1
  51. package/src/client/vue/use-mcp.ts +2 -1
  52. package/src/server/handlers/sse-handler.ts +35 -3
  53. package/src/server/mcp/oauth-client.ts +44 -20
  54. package/src/server/mcp/tool-policy-gateway.ts +98 -2
  55. package/src/server/storage/tool-policy.ts +102 -0
  56. package/src/shared/events.ts +1 -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-CbFbPkfQ.mjs';
1
+ import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider, T as ToolClient } from './types-6SmXege4.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
- * Automatically validates and refreshes OAuth tokens if needed
213
- * Saves session to Redis on first successful connection
214
- * @throws {UnauthorizedError} When OAuth authorization is required
215
- * @throws {Error} When connection fails for other reasons
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
- * Lists all available tools from the connected MCP server without emitting discovery events.
227
- * Gateways use this to apply policy before publishing tools to agents or UI state.
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
- * Dispose of all event emitters
311
- * Call this when the client is no longer needed
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-CbFbPkfQ.js';
1
+ import { m as Event, M as McpConnectionEvent, t as McpObservabilityEvent, s as McpConnectionState, A as ToolClientProvider, T as ToolClient } from './types-6SmXege4.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
- * Automatically validates and refreshes OAuth tokens if needed
213
- * Saves session to Redis on first successful connection
214
- * @throws {UnauthorizedError} When OAuth authorization is required
215
- * @throws {Error} When connection fails for other reasons
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
- * Lists all available tools from the connected MCP server without emitting discovery events.
227
- * Gateways use this to apply policy before publishing tools to agents or UI state.
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
- * Dispose of all event emitters
311
- * Call this when the client is no longer needed
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,8 +1,8 @@
1
- import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-CclWRxTD.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-CclWRxTD.mjs';
1
+ import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-xj3iQIv6.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-xj3iQIv6.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-CbFbPkfQ.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-CbFbPkfQ.mjs';
4
+ import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-6SmXege4.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-6SmXege4.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
- * List tools from a session
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
- * Update per-session tool access policy.
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
- * Call a tool on the MCP server
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
  /**
@@ -1,8 +1,8 @@
1
- import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-DzvZD6Tt.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-DzvZD6Tt.js';
1
+ import { c as SessionMutationListener, e as SessionStore } from '../multi-session-client-CB4oDrQX.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-CB4oDrQX.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-CbFbPkfQ.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-CbFbPkfQ.js';
4
+ import { M as McpConnectionEvent, t as McpObservabilityEvent, x as McpRpcResponse, w as McpRpcRequest } from '../types-6SmXege4.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-6SmXege4.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
- * List tools from a session
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
- * Update per-session tool access policy.
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
- * Call a tool on the MCP server
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
  /**
@@ -2245,6 +2245,15 @@ var MCPClient = class {
2245
2245
  __publicField(this, "_onObservabilityEvent", new Emitter());
2246
2246
  __publicField(this, "onObservabilityEvent", this._onObservabilityEvent.event);
2247
2247
  __publicField(this, "currentState", "DISCONNECTED");
2248
+ /**
2249
+ * In-memory cache for the remote server's full tools list.
2250
+ *
2251
+ * Populated on the first `fetchTools()` call and reused for the lifetime of
2252
+ * the connection. Cleared to `null` at the start of `connect()` so that a
2253
+ * reconnect always retrieves a fresh list, and also in `dispose()` to release
2254
+ * the memory when the client is no longer needed.
2255
+ */
2256
+ __publicField(this, "cachedTools", null);
2248
2257
  this.serverUrl = options.serverUrl;
2249
2258
  this.serverName = options.serverName;
2250
2259
  this.callbackUrl = options.callbackUrl;
@@ -2565,13 +2574,20 @@ var MCPClient = class {
2565
2574
  throw lastError || new Error("No transports available");
2566
2575
  }
2567
2576
  /**
2568
- * Connects to the MCP server
2569
- * Automatically validates and refreshes OAuth tokens if needed
2570
- * Saves session to Redis on first successful connection
2571
- * @throws {UnauthorizedError} When OAuth authorization is required
2572
- * @throws {Error} When connection fails for other reasons
2577
+ * Connects to the MCP server.
2578
+ *
2579
+ * Automatically validates and refreshes OAuth tokens if needed.
2580
+ * Saves the session to Redis on first successful connection.
2581
+ *
2582
+ * The in-memory tools cache (`cachedTools`) is cleared at the start of every
2583
+ * call so that a reconnection always fetches a fresh tool list from the remote
2584
+ * server — even if the same `MCPClient` instance is reused.
2585
+ *
2586
+ * @throws {UnauthorizedError} When OAuth authorization is required.
2587
+ * @throws {Error} When connection fails for other reasons.
2573
2588
  */
2574
2589
  async connect() {
2590
+ this.cachedTools = null;
2575
2591
  if (this.client.transport) {
2576
2592
  this.transport = null;
2577
2593
  try {
@@ -2754,17 +2770,30 @@ var MCPClient = class {
2754
2770
  }
2755
2771
  }
2756
2772
  /**
2757
- * Lists all available tools from the connected MCP server without emitting discovery events.
2758
- * Gateways use this to apply policy before publishing tools to agents or UI state.
2773
+ * Lists all available tools from the connected MCP server without emitting
2774
+ * discovery events. The result is cached in memory for the lifetime of the
2775
+ * connection — subsequent callers (e.g. `gateway.listTools()` running right
2776
+ * after `fetchTools()`) pay zero extra network cost.
2777
+ *
2778
+ * Gateways use this to apply a tool-access policy before publishing the
2779
+ * filtered list to agents or UI state.
2780
+ *
2781
+ * @returns The full `ListToolsResult` from the remote server.
2782
+ * @throws {Error} When the client is not connected or the request times out.
2759
2783
  */
2760
2784
  async fetchTools() {
2785
+ if (this.cachedTools) {
2786
+ return this.cachedTools;
2787
+ }
2761
2788
  const request = {
2762
2789
  method: "tools/list",
2763
2790
  params: {}
2764
2791
  };
2765
- return await this.withRetry(
2792
+ const result = await this.withRetry(
2766
2793
  () => this.client.request(request, types_js.ListToolsResultSchema)
2767
2794
  );
2795
+ this.cachedTools = result;
2796
+ return result;
2768
2797
  }
2769
2798
  /**
2770
2799
  * Lists all available tools from the connected MCP server
@@ -3050,10 +3079,14 @@ var MCPClient = class {
3050
3079
  this.emitStateChange("DISCONNECTED");
3051
3080
  }
3052
3081
  /**
3053
- * Dispose of all event emitters
3054
- * Call this when the client is no longer needed
3082
+ * Disposes all event emitters and releases cached state.
3083
+ *
3084
+ * Clears `cachedTools` to free memory, and disposes the connection and
3085
+ * observability event emitters so downstream listeners are unsubscribed.
3086
+ * Call this when the client is permanently shut down (not just disconnected).
3055
3087
  */
3056
3088
  dispose() {
3089
+ this.cachedTools = null;
3057
3090
  this._onConnectionEvent.dispose();
3058
3091
  this._onObservabilityEvent.dispose();
3059
3092
  }
@@ -3112,21 +3145,47 @@ var ToolPolicyGateway = class {
3112
3145
  this.sessionId = sessionId;
3113
3146
  this.client = client;
3114
3147
  }
3148
+ /**
3149
+ * Returns whether the underlying MCP client transport is currently connected.
3150
+ */
3115
3151
  isConnected() {
3116
3152
  return this.client.isConnected();
3117
3153
  }
3154
+ /**
3155
+ * Returns the server ID from the underlying client, if available.
3156
+ */
3118
3157
  getServerId() {
3119
3158
  return this.client.getServerId?.();
3120
3159
  }
3160
+ /**
3161
+ * Returns the human-readable server name from the underlying client, if available.
3162
+ */
3121
3163
  getServerName() {
3122
3164
  return this.client.getServerName?.();
3123
3165
  }
3166
+ /**
3167
+ * Returns the server URL from the underlying client, if available.
3168
+ */
3124
3169
  getServerUrl() {
3125
3170
  return this.client.getServerUrl?.();
3126
3171
  }
3172
+ /**
3173
+ * Returns the session ID — prefers the value reported by the underlying
3174
+ * client, falling back to the one injected at construction time.
3175
+ */
3127
3176
  getSessionId() {
3128
3177
  return this.client.getSessionId?.() ?? this.sessionId;
3129
3178
  }
3179
+ /**
3180
+ * Returns the **policy-filtered** list of tools that the current session
3181
+ * is allowed to call.
3182
+ *
3183
+ * Internally calls `client.fetchTools()` (which is cache-backed) so no
3184
+ * extra network round-trip is incurred when called after `fetchTools()`.
3185
+ *
3186
+ * @returns A `ListToolsResult` containing only the permitted tools.
3187
+ * @throws {Error} When the session does not exist in the store.
3188
+ */
3130
3189
  async listTools() {
3131
3190
  const session = await this.getSession();
3132
3191
  const result = await this.client.fetchTools();
@@ -3136,20 +3195,61 @@ var ToolPolicyGateway = class {
3136
3195
  tools
3137
3196
  };
3138
3197
  }
3198
+ /**
3199
+ * Returns the **complete, unfiltered** list of tools from the remote server,
3200
+ * bypassing any tool-access policy.
3201
+ *
3202
+ * Used by the management UI to show all available tools (including blocked
3203
+ * ones) so users can toggle individual tool access in the dialog.
3204
+ *
3205
+ * @returns The raw `ListToolsResult` from the remote server.
3206
+ */
3139
3207
  async listAllTools() {
3140
3208
  return await this.client.fetchTools();
3141
3209
  }
3210
+ /**
3211
+ * Executes a tool call on the remote server after verifying that the tool
3212
+ * is permitted by the current session's policy.
3213
+ *
3214
+ * @param name - The exact tool name to invoke.
3215
+ * @param args - Key/value arguments to pass to the tool.
3216
+ * @returns The tool's `CallToolResult`.
3217
+ * @throws {Error} When the tool is blocked by the session's policy.
3218
+ * @throws {Error} When the session does not exist in the store.
3219
+ */
3142
3220
  async callTool(name, args) {
3143
3221
  const session = await this.getSession();
3144
3222
  this.assertAllowed(session, name);
3145
3223
  return await this.client.callTool(name, args);
3146
3224
  }
3225
+ /**
3226
+ * Filters a raw tools array down to only those permitted by the session's
3227
+ * `toolPolicy`.
3228
+ *
3229
+ * @param session - The session whose policy should be applied.
3230
+ * @param tools - The unfiltered list of tools from the remote server.
3231
+ * @returns A subset of `tools` that the policy allows.
3232
+ */
3147
3233
  filterTools(session, tools) {
3148
3234
  return filterToolsByPolicy(tools, session.toolPolicy, this.getPolicyServerId(session));
3149
3235
  }
3236
+ /**
3237
+ * Throws if `toolName` is blocked by the session's policy.
3238
+ * Call this before proxying a `callTool` request to the remote server.
3239
+ *
3240
+ * @param session - The session whose policy should be enforced.
3241
+ * @param toolName - The tool being invoked.
3242
+ * @throws {Error} When the tool is not permitted.
3243
+ */
3150
3244
  assertAllowed(session, toolName) {
3151
3245
  assertToolAllowed(session.toolPolicy, toolName, this.getPolicyServerId(session));
3152
3246
  }
3247
+ /**
3248
+ * Loads the session from the store and throws if it does not exist.
3249
+ *
3250
+ * @returns The fully-hydrated `Session` record.
3251
+ * @throws {Error} When the session cannot be found.
3252
+ */
3153
3253
  async getSession() {
3154
3254
  const session = await sessions.get(this.userId, this.sessionId);
3155
3255
  if (!session) {
@@ -3157,6 +3257,11 @@ var ToolPolicyGateway = class {
3157
3257
  }
3158
3258
  return session;
3159
3259
  }
3260
+ /**
3261
+ * Resolves the server ID to use when evaluating tool policy.
3262
+ * Prefers the value from the live client (most accurate) and falls back
3263
+ * to the server ID stored on the session record.
3264
+ */
3160
3265
  getPolicyServerId(session) {
3161
3266
  return this.client.getServerId?.() ?? session.serverId;
3162
3267
  }
@@ -3716,12 +3821,29 @@ var SSEConnectionManager = class {
3716
3821
  this.clients.set(sessionId, client);
3717
3822
  return client;
3718
3823
  }
3824
+ /**
3825
+ * Fetches all tools from the remote MCP server and emits a `tools_discovered` event.
3826
+ *
3827
+ * Two lists are always published together:
3828
+ * - `tools` — policy-filtered list that agents are allowed to call.
3829
+ * - `allTools` — the complete, unfiltered list used by the management UI so
3830
+ * that blocked tools still appear as checkboxes in the dialog.
3831
+ *
3832
+ * `fetchTools()` is called first (populates the in-memory cache), then
3833
+ * `gateway.listTools()` re-uses that cache internally — so only one remote
3834
+ * network round-trip is made regardless of how many callers follow.
3835
+ *
3836
+ * @param sessionId - The session whose tools should be discovered.
3837
+ * @returns The session record and the policy-filtered tool list.
3838
+ * @throws {Error} When the session does not exist in the store.
3839
+ */
3719
3840
  async listPolicyFilteredTools(sessionId) {
3720
3841
  const session = await sessions.get(this.userId, sessionId);
3721
3842
  if (!session) {
3722
3843
  throw new Error("Session not found");
3723
3844
  }
3724
3845
  const client = await this.getOrCreateClient(sessionId);
3846
+ const allTools = await client.fetchTools().catch(() => ({ tools: [] }));
3725
3847
  const gateway = createToolPolicyGateway(this.userId, sessionId, client);
3726
3848
  const result = await gateway.listTools();
3727
3849
  this.emitConnectionEvent({
@@ -3730,12 +3852,15 @@ var SSEConnectionManager = class {
3730
3852
  serverId: session.serverId ?? "unknown",
3731
3853
  toolCount: result.tools.length,
3732
3854
  tools: result.tools,
3855
+ allTools: allTools.tools,
3733
3856
  timestamp: Date.now()
3734
3857
  });
3735
3858
  return { session, result };
3736
3859
  }
3737
3860
  /**
3738
- * List tools from a session
3861
+ * Returns the policy-filtered tool list for a session (agent-facing).
3862
+ * Internally re-uses `listPolicyFilteredTools` which also emits a
3863
+ * `tools_discovered` SSE event to keep client state up to date.
3739
3864
  */
3740
3865
  async listTools(params) {
3741
3866
  const { sessionId } = params;
@@ -3772,7 +3897,15 @@ var SSEConnectionManager = class {
3772
3897
  };
3773
3898
  }
3774
3899
  /**
3775
- * Update per-session tool access policy.
3900
+ * Persists a new tool access policy for a session and broadcasts the updated
3901
+ * filtered tool list to all connected browser clients via a `tools_discovered` event.
3902
+ *
3903
+ * Both `tools` (policy-filtered) and `allTools` (complete list) are emitted
3904
+ * so the management UI can immediately reflect the new checkbox states without
3905
+ * an additional round-trip to the server.
3906
+ *
3907
+ * @param params - Session ID and the new `{ mode, toolIds }` policy to apply.
3908
+ * @throws {Error} When the session does not exist or the policy references unknown tool IDs.
3776
3909
  */
3777
3910
  async setToolPolicy(params) {
3778
3911
  const { sessionId } = params;
@@ -3792,6 +3925,7 @@ var SSEConnectionManager = class {
3792
3925
  serverId: session.serverId ?? "unknown",
3793
3926
  toolCount: filteredTools.length,
3794
3927
  tools: filteredTools,
3928
+ allTools: allTools.tools,
3795
3929
  timestamp: Date.now()
3796
3930
  });
3797
3931
  return {
@@ -3802,7 +3936,8 @@ var SSEConnectionManager = class {
3802
3936
  };
3803
3937
  }
3804
3938
  /**
3805
- * Call a tool on the MCP server
3939
+ * Proxies a tool invocation to the remote MCP server.
3940
+ * Resolves the client for the given session and delegates to the tool router.
3806
3941
  */
3807
3942
  async callTool(params) {
3808
3943
  const { sessionId, toolName, toolArgs } = params;