@mcp-ts/sdk 2.5.0 → 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/index.js +3 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +3 -0
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +4 -4
- package/dist/client/react.d.ts +4 -4
- package/dist/client/react.js +23 -38
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +23 -38
- 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 +4 -1
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +4 -1
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{index-CTURVnom.d.mts → index-B3GPsPsi.d.mts} +2 -1
- package/dist/{index-sVcqrhf7.d.ts → index-gNdSQTSz.d.ts} +2 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +214 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +214 -13
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CSPSHHla.d.ts → multi-session-client-CB4oDrQX.d.ts} +36 -10
- package/dist/{multi-session-client-DMZGVABI.d.mts → multi-session-client-xj3iQIv6.d.mts} +36 -10
- package/dist/server/index.d.mts +39 -7
- package/dist/server/index.d.ts +39 -7
- package/dist/server/index.js +211 -13
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +211 -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-CS9l0w4a.d.ts → tool-router-C-Mw1_BQ.d.ts} +1 -1
- package/dist/{tool-router-CVLBaCwH.d.mts → tool-router-CsKVXbQB.d.mts} +1 -1
- package/dist/{types-DK_NGWd4.d.mts → types-6SmXege4.d.mts} +4 -2
- package/dist/{types-DK_NGWd4.d.ts → types-6SmXege4.d.ts} +4 -2
- package/package.json +2 -2
- package/src/client/core/sse-client.ts +4 -0
- package/src/client/react/oauth-popup.tsx +17 -24
- package/src/client/react/use-mcp.ts +7 -16
- package/src/client/vue/use-mcp.ts +2 -1
- package/src/server/handlers/sse-handler.ts +121 -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/src/shared/types.ts +4 -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-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
|
-
*
|
|
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-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
|
-
*
|
|
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-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-
|
|
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-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';
|
|
@@ -79,6 +79,11 @@ declare class SSEConnectionManager {
|
|
|
79
79
|
* Connect to an MCP server
|
|
80
80
|
*/
|
|
81
81
|
private connect;
|
|
82
|
+
/**
|
|
83
|
+
* Reconnect to an MCP server — tears down the active client transport/connection
|
|
84
|
+
* and creates a fresh connection while reusing the existing session credentials in a single RPC call.
|
|
85
|
+
*/
|
|
86
|
+
private reconnect;
|
|
82
87
|
/**
|
|
83
88
|
* Disconnect from an MCP server
|
|
84
89
|
*/
|
|
@@ -87,9 +92,27 @@ declare class SSEConnectionManager {
|
|
|
87
92
|
* Get an existing client or create and connect a new one for the session.
|
|
88
93
|
*/
|
|
89
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
|
+
*/
|
|
90
111
|
private listPolicyFilteredTools;
|
|
91
112
|
/**
|
|
92
|
-
*
|
|
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.
|
|
93
116
|
*/
|
|
94
117
|
private listTools;
|
|
95
118
|
/**
|
|
@@ -97,11 +120,20 @@ declare class SSEConnectionManager {
|
|
|
97
120
|
*/
|
|
98
121
|
private getToolPolicy;
|
|
99
122
|
/**
|
|
100
|
-
*
|
|
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.
|
|
101
132
|
*/
|
|
102
133
|
private setToolPolicy;
|
|
103
134
|
/**
|
|
104
|
-
*
|
|
135
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
136
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
105
137
|
*/
|
|
106
138
|
private callTool;
|
|
107
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-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-
|
|
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-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';
|
|
@@ -79,6 +79,11 @@ declare class SSEConnectionManager {
|
|
|
79
79
|
* Connect to an MCP server
|
|
80
80
|
*/
|
|
81
81
|
private connect;
|
|
82
|
+
/**
|
|
83
|
+
* Reconnect to an MCP server — tears down the active client transport/connection
|
|
84
|
+
* and creates a fresh connection while reusing the existing session credentials in a single RPC call.
|
|
85
|
+
*/
|
|
86
|
+
private reconnect;
|
|
82
87
|
/**
|
|
83
88
|
* Disconnect from an MCP server
|
|
84
89
|
*/
|
|
@@ -87,9 +92,27 @@ declare class SSEConnectionManager {
|
|
|
87
92
|
* Get an existing client or create and connect a new one for the session.
|
|
88
93
|
*/
|
|
89
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
|
+
*/
|
|
90
111
|
private listPolicyFilteredTools;
|
|
91
112
|
/**
|
|
92
|
-
*
|
|
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.
|
|
93
116
|
*/
|
|
94
117
|
private listTools;
|
|
95
118
|
/**
|
|
@@ -97,11 +120,20 @@ declare class SSEConnectionManager {
|
|
|
97
120
|
*/
|
|
98
121
|
private getToolPolicy;
|
|
99
122
|
/**
|
|
100
|
-
*
|
|
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.
|
|
101
132
|
*/
|
|
102
133
|
private setToolPolicy;
|
|
103
134
|
/**
|
|
104
|
-
*
|
|
135
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
136
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
105
137
|
*/
|
|
106
138
|
private callTool;
|
|
107
139
|
/**
|
package/dist/server/index.js
CHANGED
|
@@ -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
|
-
*
|
|
2570
|
-
*
|
|
2571
|
-
*
|
|
2572
|
-
*
|
|
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
|
|
2758
|
-
*
|
|
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
|
-
|
|
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
|
-
*
|
|
3054
|
-
*
|
|
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
|
}
|
|
@@ -3465,6 +3570,9 @@ var SSEConnectionManager = class {
|
|
|
3465
3570
|
case "connect":
|
|
3466
3571
|
result = await this.connect(request.params);
|
|
3467
3572
|
break;
|
|
3573
|
+
case "reconnect":
|
|
3574
|
+
result = await this.reconnect(request.params);
|
|
3575
|
+
break;
|
|
3468
3576
|
case "disconnect":
|
|
3469
3577
|
result = await this.disconnect(request.params);
|
|
3470
3578
|
break;
|
|
@@ -3607,6 +3715,66 @@ var SSEConnectionManager = class {
|
|
|
3607
3715
|
throw error;
|
|
3608
3716
|
}
|
|
3609
3717
|
}
|
|
3718
|
+
/**
|
|
3719
|
+
* Reconnect to an MCP server — tears down the active client transport/connection
|
|
3720
|
+
* and creates a fresh connection while reusing the existing session credentials in a single RPC call.
|
|
3721
|
+
*/
|
|
3722
|
+
async reconnect(params) {
|
|
3723
|
+
const { serverId: rawServerId, serverName, serverUrl, callbackUrl, transportType } = params;
|
|
3724
|
+
const headers = normalizeHeaders(params.headers);
|
|
3725
|
+
const serverId = rawServerId && rawServerId.length <= 12 ? rawServerId : generateServerId();
|
|
3726
|
+
const existingSessions = await sessions.list(this.userId);
|
|
3727
|
+
const duplicate = existingSessions.find(
|
|
3728
|
+
(s) => s.serverId === serverId || s.serverUrl === serverUrl
|
|
3729
|
+
);
|
|
3730
|
+
const sessionId = duplicate ? duplicate.sessionId : await sessions.generateSessionId();
|
|
3731
|
+
if (duplicate) {
|
|
3732
|
+
const existingClient = this.clients.get(duplicate.sessionId);
|
|
3733
|
+
if (existingClient) {
|
|
3734
|
+
await existingClient.disconnect();
|
|
3735
|
+
this.clients.delete(duplicate.sessionId);
|
|
3736
|
+
}
|
|
3737
|
+
}
|
|
3738
|
+
try {
|
|
3739
|
+
const clientMetadata = await this.getResolvedClientMetadata();
|
|
3740
|
+
const client = new MCPClient({
|
|
3741
|
+
userId: this.userId,
|
|
3742
|
+
sessionId,
|
|
3743
|
+
serverId,
|
|
3744
|
+
serverName,
|
|
3745
|
+
serverUrl,
|
|
3746
|
+
callbackUrl,
|
|
3747
|
+
transportType,
|
|
3748
|
+
headers,
|
|
3749
|
+
...clientMetadata
|
|
3750
|
+
});
|
|
3751
|
+
this.clients.set(sessionId, client);
|
|
3752
|
+
client.onConnectionEvent((event) => {
|
|
3753
|
+
this.emitConnectionEvent(event);
|
|
3754
|
+
});
|
|
3755
|
+
client.onObservabilityEvent((event) => {
|
|
3756
|
+
this.sendEvent(event);
|
|
3757
|
+
});
|
|
3758
|
+
await client.connect();
|
|
3759
|
+
await this.listPolicyFilteredTools(sessionId);
|
|
3760
|
+
return { sessionId, success: true };
|
|
3761
|
+
} catch (error) {
|
|
3762
|
+
if (error instanceof UnauthorizedError) {
|
|
3763
|
+
this.clients.delete(sessionId);
|
|
3764
|
+
return { sessionId, success: true };
|
|
3765
|
+
}
|
|
3766
|
+
this.emitConnectionEvent({
|
|
3767
|
+
type: "error",
|
|
3768
|
+
sessionId,
|
|
3769
|
+
serverId,
|
|
3770
|
+
error: error instanceof Error ? error.message : "Connection failed",
|
|
3771
|
+
errorType: "connection",
|
|
3772
|
+
timestamp: Date.now()
|
|
3773
|
+
});
|
|
3774
|
+
this.clients.delete(sessionId);
|
|
3775
|
+
throw error;
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3610
3778
|
/**
|
|
3611
3779
|
* Disconnect from an MCP server
|
|
3612
3780
|
*/
|
|
@@ -3653,12 +3821,29 @@ var SSEConnectionManager = class {
|
|
|
3653
3821
|
this.clients.set(sessionId, client);
|
|
3654
3822
|
return client;
|
|
3655
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
|
+
*/
|
|
3656
3840
|
async listPolicyFilteredTools(sessionId) {
|
|
3657
3841
|
const session = await sessions.get(this.userId, sessionId);
|
|
3658
3842
|
if (!session) {
|
|
3659
3843
|
throw new Error("Session not found");
|
|
3660
3844
|
}
|
|
3661
3845
|
const client = await this.getOrCreateClient(sessionId);
|
|
3846
|
+
const allTools = await client.fetchTools().catch(() => ({ tools: [] }));
|
|
3662
3847
|
const gateway = createToolPolicyGateway(this.userId, sessionId, client);
|
|
3663
3848
|
const result = await gateway.listTools();
|
|
3664
3849
|
this.emitConnectionEvent({
|
|
@@ -3667,12 +3852,15 @@ var SSEConnectionManager = class {
|
|
|
3667
3852
|
serverId: session.serverId ?? "unknown",
|
|
3668
3853
|
toolCount: result.tools.length,
|
|
3669
3854
|
tools: result.tools,
|
|
3855
|
+
allTools: allTools.tools,
|
|
3670
3856
|
timestamp: Date.now()
|
|
3671
3857
|
});
|
|
3672
3858
|
return { session, result };
|
|
3673
3859
|
}
|
|
3674
3860
|
/**
|
|
3675
|
-
*
|
|
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.
|
|
3676
3864
|
*/
|
|
3677
3865
|
async listTools(params) {
|
|
3678
3866
|
const { sessionId } = params;
|
|
@@ -3709,7 +3897,15 @@ var SSEConnectionManager = class {
|
|
|
3709
3897
|
};
|
|
3710
3898
|
}
|
|
3711
3899
|
/**
|
|
3712
|
-
*
|
|
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.
|
|
3713
3909
|
*/
|
|
3714
3910
|
async setToolPolicy(params) {
|
|
3715
3911
|
const { sessionId } = params;
|
|
@@ -3729,6 +3925,7 @@ var SSEConnectionManager = class {
|
|
|
3729
3925
|
serverId: session.serverId ?? "unknown",
|
|
3730
3926
|
toolCount: filteredTools.length,
|
|
3731
3927
|
tools: filteredTools,
|
|
3928
|
+
allTools: allTools.tools,
|
|
3732
3929
|
timestamp: Date.now()
|
|
3733
3930
|
});
|
|
3734
3931
|
return {
|
|
@@ -3739,7 +3936,8 @@ var SSEConnectionManager = class {
|
|
|
3739
3936
|
};
|
|
3740
3937
|
}
|
|
3741
3938
|
/**
|
|
3742
|
-
*
|
|
3939
|
+
* Proxies a tool invocation to the remote MCP server.
|
|
3940
|
+
* Resolves the client for the given session and delegates to the tool router.
|
|
3743
3941
|
*/
|
|
3744
3942
|
async callTool(params) {
|
|
3745
3943
|
const { sessionId, toolName, toolArgs } = params;
|