@mcp-ts/sdk 1.4.0 → 1.5.0

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 (71) hide show
  1. package/README.md +20 -27
  2. package/dist/adapters/agui-adapter.d.mts +16 -0
  3. package/dist/adapters/agui-adapter.d.ts +16 -0
  4. package/dist/adapters/agui-adapter.js +185 -0
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +185 -0
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +2 -0
  9. package/dist/adapters/agui-middleware.d.ts +2 -0
  10. package/dist/adapters/agui-middleware.js.map +1 -1
  11. package/dist/adapters/agui-middleware.mjs.map +1 -1
  12. package/dist/adapters/ai-adapter.d.mts +21 -0
  13. package/dist/adapters/ai-adapter.d.ts +21 -0
  14. package/dist/adapters/ai-adapter.js +175 -0
  15. package/dist/adapters/ai-adapter.js.map +1 -1
  16. package/dist/adapters/ai-adapter.mjs +175 -0
  17. package/dist/adapters/ai-adapter.mjs.map +1 -1
  18. package/dist/adapters/langchain-adapter.d.mts +16 -0
  19. package/dist/adapters/langchain-adapter.d.ts +16 -0
  20. package/dist/adapters/langchain-adapter.js +179 -0
  21. package/dist/adapters/langchain-adapter.js.map +1 -1
  22. package/dist/adapters/langchain-adapter.mjs +179 -0
  23. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  24. package/dist/client/index.d.mts +2 -2
  25. package/dist/client/index.d.ts +2 -2
  26. package/dist/client/react.d.mts +14 -7
  27. package/dist/client/react.d.ts +14 -7
  28. package/dist/client/react.js +48 -23
  29. package/dist/client/react.js.map +1 -1
  30. package/dist/client/react.mjs +47 -24
  31. package/dist/client/react.mjs.map +1 -1
  32. package/dist/client/vue.d.mts +4 -4
  33. package/dist/client/vue.d.ts +4 -4
  34. package/dist/{index-CQr9q0bF.d.mts → index-DcYfpY3H.d.mts} +1 -1
  35. package/dist/{index-nE_7Io0I.d.ts → index-GfC_eNEv.d.ts} +1 -1
  36. package/dist/index.d.mts +4 -3
  37. package/dist/index.d.ts +4 -3
  38. package/dist/index.js +883 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mjs +868 -2
  41. package/dist/index.mjs.map +1 -1
  42. package/dist/server/index.d.mts +2 -2
  43. package/dist/server/index.d.ts +2 -2
  44. package/dist/server/index.js +3 -1
  45. package/dist/server/index.js.map +1 -1
  46. package/dist/server/index.mjs +3 -1
  47. package/dist/server/index.mjs.map +1 -1
  48. package/dist/shared/index.d.mts +86 -4
  49. package/dist/shared/index.d.ts +86 -4
  50. package/dist/shared/index.js +874 -0
  51. package/dist/shared/index.js.map +1 -1
  52. package/dist/shared/index.mjs +865 -1
  53. package/dist/shared/index.mjs.map +1 -1
  54. package/dist/tool-router-Bo8qZbsD.d.ts +325 -0
  55. package/dist/tool-router-XnWVxPzv.d.mts +325 -0
  56. package/dist/{types-CW6lghof.d.mts → types-CfCoIsWI.d.mts} +27 -1
  57. package/dist/{types-CW6lghof.d.ts → types-CfCoIsWI.d.ts} +27 -1
  58. package/package.json +3 -2
  59. package/src/adapters/agui-adapter.ts +79 -0
  60. package/src/adapters/ai-adapter.ts +75 -0
  61. package/src/adapters/langchain-adapter.ts +74 -0
  62. package/src/client/react/index.ts +2 -0
  63. package/src/client/react/use-mcp-apps.tsx +50 -32
  64. package/src/server/index.ts +2 -0
  65. package/src/server/mcp/oauth-client.ts +3 -1
  66. package/src/shared/index.ts +36 -0
  67. package/src/shared/meta-tools.ts +387 -0
  68. package/src/shared/schema-compressor.ts +124 -0
  69. package/src/shared/tool-index.ts +499 -0
  70. package/src/shared/tool-router.ts +469 -0
  71. package/src/shared/types.ts +30 -0
@@ -0,0 +1,325 @@
1
+ import { Tool } from '@modelcontextprotocol/sdk/types.js';
2
+ import { u as ToolClientProvider, T as ToolClient } from './types-CfCoIsWI.mjs';
3
+
4
+ /**
5
+ * SchemaCompressor — Utilities for reducing tool schema token overhead.
6
+ *
7
+ * Provides compact representations of tools (name + description only,
8
+ * no inputSchema) and token savings estimation.
9
+ *
10
+ * @packageDocumentation
11
+ */
12
+
13
+ /**
14
+ * A minimal tool representation containing only what an LLM needs to
15
+ * *decide whether* to use a tool. The full `inputSchema` is deferred.
16
+ */
17
+ interface CompactTool {
18
+ name: string;
19
+ description?: string;
20
+ /**
21
+ * Human-readable hint about the expected parameters.
22
+ * e.g. "(location: string, unit?: 'celsius' | 'fahrenheit')"
23
+ */
24
+ parameterHint?: string;
25
+ }
26
+ interface CompressionStats {
27
+ /** Estimated tokens for the *full* tool list. */
28
+ fullTokens: number;
29
+ /** Estimated tokens for the *compact* tool list. */
30
+ compactTokens: number;
31
+ /** Absolute token savings. */
32
+ savedTokens: number;
33
+ /** Percentage savings as a human-readable string, e.g. "82.3%". */
34
+ savingsPercent: string;
35
+ }
36
+ declare class SchemaCompressor {
37
+ /**
38
+ * Convert a full MCP Tool definition to a compact summary.
39
+ *
40
+ * The compact form omits `inputSchema` entirely and optionally generates
41
+ * a short `parameterHint` from the schema's top-level properties.
42
+ */
43
+ static toCompact(tool: Tool): CompactTool;
44
+ /**
45
+ * Convert an array of tools to compact form, optionally limiting the count.
46
+ */
47
+ static compactAll(tools: Tool[], options?: {
48
+ maxTools?: number;
49
+ }): CompactTool[];
50
+ /**
51
+ * Estimate token savings from using compact vs full tool schemas.
52
+ */
53
+ static estimateSavings(tools: Tool[]): CompressionStats;
54
+ }
55
+
56
+ /**
57
+ * ToolIndex — Lightweight in-memory search index for MCP tool discovery.
58
+ *
59
+ * Supports two search methods:
60
+ * • BM25 – Okapi BM25 ranking over tokenized tool metadata (zero external deps)
61
+ * • regex – Pattern matching against tool names, descriptions, and parameters
62
+ * • embedding – (optional) cosine-similarity over caller-supplied vectors,
63
+ * blended with BM25 scores
64
+ *
65
+ * @packageDocumentation
66
+ */
67
+
68
+ /** Compact summary returned by search — intentionally lightweight. */
69
+ interface ToolSummary {
70
+ /** Fully qualified tool name (e.g. "tool_github_create_pr") */
71
+ name: string;
72
+ /** Human-readable description */
73
+ description: string;
74
+ /** Server that owns this tool */
75
+ serverName: string;
76
+ /** Session the tool belongs to */
77
+ sessionId: string;
78
+ /** Estimated token cost of the full inputSchema */
79
+ estimatedTokens: number;
80
+ }
81
+ /** A tool with routing metadata attached during indexing. */
82
+ interface IndexedTool extends Tool {
83
+ sessionId: string;
84
+ serverName: string;
85
+ }
86
+ /**
87
+ * An optional embedding function supplied by the consumer.
88
+ * Should accept an array of strings and return a matching array of
89
+ * float-number arrays (one embedding vector per input string).
90
+ */
91
+ type EmbedFn = (texts: string[]) => Promise<number[][]>;
92
+ interface ToolIndexOptions {
93
+ /**
94
+ * Custom embedding function for semantic search.
95
+ * When provided, `search()` uses cosine-similarity in addition to keywords.
96
+ * @example
97
+ * ```ts
98
+ * import { embed } from 'ai';
99
+ * const embedFn: EmbedFn = async (texts) => {
100
+ * const { embeddings } = await embed({ model: openai('text-embedding-3-small'), values: texts });
101
+ * return embeddings;
102
+ * };
103
+ * ```
104
+ */
105
+ embedFn?: EmbedFn;
106
+ /**
107
+ * Relative weight of keyword score vs embedding score when both are active.
108
+ * 0 = embedding only · 1 = keyword only · 0.4 (default) blends both.
109
+ * @default 0.4
110
+ */
111
+ keywordWeight?: number;
112
+ }
113
+ declare class ToolIndex {
114
+ /** All indexed tools keyed by name (supports duplicates). */
115
+ private tools;
116
+ /** Precomputed lightweight summaries keyed by document. */
117
+ private toolSummaries;
118
+ /** Pre-computed search text for keyword matching (lowercase), keyed by document. */
119
+ private searchTexts;
120
+ /** Pre-computed IDF values per token (computed once on build). */
121
+ private idf;
122
+ /** Per-tool TF vectors (Map<token, tf>). */
123
+ private tfVectors;
124
+ /** Optional: pre-computed embedding vectors per tool. */
125
+ private embeddings;
126
+ /** BM25: document lengths in tokens for each tool. */
127
+ private docLengths;
128
+ /** BM25: average document length across the entire index. */
129
+ private avgDocLength;
130
+ /** Cached total estimated token cost across all indexed tools. */
131
+ private totalTokenCost;
132
+ private options;
133
+ constructor(options?: ToolIndexOptions);
134
+ /**
135
+ * Build (or rebuild) the index from the given tool set.
136
+ * Call this after connecting / reconnecting to MCP servers.
137
+ */
138
+ buildIndex(tools: IndexedTool[]): Promise<void>;
139
+ /**
140
+ * Search the index and return the top-K most relevant tools.
141
+ *
142
+ * When an `embedFn` is configured the final score is a weighted blend of
143
+ * keyword TF-IDF similarity and embedding cosine-similarity:
144
+ *
145
+ * `score = keywordWeight × keyword_score + (1 - keywordWeight) × cosine_score`
146
+ */
147
+ search(query: string, topK?: number): Promise<ToolSummary[]>;
148
+ /**
149
+ * Search tools using a regex pattern.
150
+ * Matches against name, description, and parameter metadata.
151
+ */
152
+ searchRegex(pattern: string, topK?: number): ToolSummary[];
153
+ /**
154
+ * Get tool definition(s) by name.
155
+ * If namespace is provided, it tries to match sessionId or serverName.
156
+ */
157
+ getTool(name: string, namespace?: string): IndexedTool[];
158
+ /** All indexed tool names. */
159
+ getToolNames(): string[];
160
+ /** Number of indexed tools (including duplicates). */
161
+ get size(): number;
162
+ /** Total estimated token cost of all indexed tool schemas. */
163
+ getTotalTokenCost(): number;
164
+ /**
165
+ * Estimate token count of a tool's full schema (name + description + inputSchema).
166
+ *
167
+ * Uses character-class weighted counting calibrated against cl100k_base.
168
+ * Accuracy is typically within ±10% for JSON Schema payloads.
169
+ */
170
+ static estimateTokens(tool: Tool): number;
171
+ /** Build a single searchable string from tool metadata. */
172
+ private buildSearchableText;
173
+ private getDocumentKey;
174
+ /** Simple whitespace + camelCase + snake_case tokenizer. */
175
+ private tokenize;
176
+ /** Cosine similarity between two vectors. */
177
+ private cosineSimilarity;
178
+ }
179
+
180
+ type ToolRouterStrategy = 'all' | 'search' | 'groups';
181
+ interface ToolRouterOptions {
182
+ /**
183
+ * Strategy for tool selection.
184
+ *
185
+ * • `all` — Expose all tools (default, backward-compatible)
186
+ * • `search` — Expose only meta-tools; LLM discovers real tools via search
187
+ * • `groups` — Expose only tools from active groups
188
+ *
189
+ * @default 'all'
190
+ */
191
+ strategy?: ToolRouterStrategy;
192
+ /**
193
+ * Maximum tools to expose to the LLM at once.
194
+ * Only applies to `groups` strategy and search results.
195
+ * @default 40
196
+ */
197
+ maxTools?: number;
198
+ /**
199
+ * Tool groups configuration — map of group name to tool names.
200
+ * When not provided, groups are auto-generated from server names.
201
+ *
202
+ * @example
203
+ * ```ts
204
+ * groups: {
205
+ * database: ['query_db', 'list_tables', 'describe_table'],
206
+ * github: ['create_pr', 'list_issues', 'search_code'],
207
+ * }
208
+ * ```
209
+ */
210
+ groups?: Record<string, string[]>;
211
+ /**
212
+ * Active groups (when `strategy='groups'`).
213
+ * Only tools in these groups are exposed. Empty = all groups active.
214
+ */
215
+ activeGroups?: string[];
216
+ /**
217
+ * Whether to use compact schemas (name + description + parameterHint only, no inputSchema).
218
+ * Reduces token usage but requires 2-turn flow: LLM picks tool → get schema → call.
219
+ * @default false
220
+ */
221
+ compactSchemas?: boolean;
222
+ /**
223
+ * Optional embedding function for semantic search.
224
+ * When not provided, keyword TF-IDF matching is used.
225
+ */
226
+ embedFn?: EmbedFn;
227
+ /**
228
+ * Weight of keyword score vs embedding score (0–1).
229
+ * Only relevant when `embedFn` is provided.
230
+ * @default 0.4
231
+ */
232
+ keywordWeight?: number;
233
+ }
234
+ /** Information about a tool group. */
235
+ interface ToolGroupInfo {
236
+ tools: string[];
237
+ active: boolean;
238
+ }
239
+ /**
240
+ * Accepted client input for ToolRouter.
241
+ * Pass a `ToolClientProvider` (e.g. MultiSessionClient), or an array of `ToolClient` instances.
242
+ */
243
+ type ToolRouterClientInput = ToolClientProvider | ToolClient[];
244
+ declare class ToolRouter {
245
+ private client;
246
+ private options;
247
+ private index;
248
+ private allTools;
249
+ private groupsMap;
250
+ private strategy;
251
+ private maxTools;
252
+ private compactSchemas;
253
+ private activeGroups;
254
+ private customGroups?;
255
+ private initialized;
256
+ constructor(client: ToolRouterClientInput, options?: ToolRouterOptions);
257
+ /**
258
+ * Get tools filtered by the current strategy.
259
+ * This is the main method adapters should call.
260
+ *
261
+ * - `all` → returns all tools (unchanged behavior)
262
+ * - `search` → returns only meta-tools (mcp_search_tool_bm25, mcp_get_tool_schema, mcp_execute_tool)
263
+ * - `groups` → returns tools from active groups only
264
+ */
265
+ getFilteredTools(): Promise<Tool[]>;
266
+ /**
267
+ * Search tools by natural-language query.
268
+ * Works regardless of strategy.
269
+ */
270
+ searchTools(query: string, topK?: number): Promise<ToolSummary[]>;
271
+ /**
272
+ * Search tools by regex pattern.
273
+ * Matches against name, description, and parameter metadata.
274
+ */
275
+ searchToolsRegex(pattern: string, topK?: number): Promise<ToolSummary[]>;
276
+ /**
277
+ * Get the full tool definition by name.
278
+ * If tool name is ambiguous, use namespace to specify the server.
279
+ */
280
+ getToolSchema(toolName: string, namespace?: string): IndexedTool | undefined;
281
+ /**
282
+ * Get compact (schema-less) summaries for all tools.
283
+ */
284
+ getCompactTools(): CompactTool[];
285
+ /** Get all available groups with their tool lists and active status. */
286
+ getGroups(): Map<string, ToolGroupInfo>;
287
+ /** Activate specific groups. Pass empty array to activate all. */
288
+ setActiveGroups(groups: string[]): void;
289
+ /** Get the names of currently active groups. */
290
+ getActiveGroups(): string[];
291
+ /** Total token cost of all tools if loaded without filtering. */
292
+ getTotalTokenCost(): number;
293
+ /** Estimate token cost of the currently filtered tool set. */
294
+ getFilteredTokenCost(): Promise<number>;
295
+ /** Get compression stats showing savings from current strategy. */
296
+ getCompressionStats(): CompressionStats;
297
+ /** Number of total indexed tools. */
298
+ get totalToolCount(): number;
299
+ /** Change strategy at runtime. */
300
+ setStrategy(strategy: ToolRouterStrategy): void;
301
+ /**
302
+ * Force a re-index of tools from all connected clients.
303
+ * Call this after adding/removing MCP server connections.
304
+ */
305
+ refresh(): Promise<void>;
306
+ /**
307
+ * Execute a tool by routing to the correct MCP client.
308
+ * Used by the `mcp_execute_tool` meta-tool to proxy tool calls.
309
+ */
310
+ callTool(toolName: string, args: Record<string, unknown>, namespace?: string): Promise<any>;
311
+ /** Lazy initialization — fetches tools from all connected clients. */
312
+ private ensureInitialized;
313
+ /** Fetch tools from all connected MCP clients. */
314
+ private fetchAllTools;
315
+ /** Resolve the client input to a flat array of ToolClient instances. */
316
+ private getClients;
317
+ /** Build group map from custom config or auto-detect from server names. */
318
+ private buildGroups;
319
+ /** Return only tools belonging to currently active groups. */
320
+ private getGroupFilteredTools;
321
+ /** The 4 meta-tool definitions exposed in `search` strategy. */
322
+ private getMetaToolDefinitions;
323
+ }
324
+
325
+ export { type CompactTool as C, type EmbedFn as E, type IndexedTool as I, SchemaCompressor as S, type ToolGroupInfo as T, type CompressionStats as a, ToolIndex as b, type ToolIndexOptions as c, ToolRouter as d, type ToolRouterClientInput as e, type ToolRouterOptions as f, type ToolRouterStrategy as g, type ToolSummary as h };
@@ -4,6 +4,32 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js';
4
4
  * Type definitions for MCP operations
5
5
  */
6
6
 
7
+ /**
8
+ * A client that can list and execute MCP tools.
9
+ *
10
+ * This is the structural interface that `ToolRouter`, adapters, and other
11
+ * consumers use to interact with any MCP client implementation.
12
+ * Both `MCPClient` and `createMcpClient()` satisfy this interface.
13
+ */
14
+ interface ToolClient {
15
+ isConnected(): boolean;
16
+ listTools(): Promise<{
17
+ tools: Tool[];
18
+ }>;
19
+ callTool(name: string, args: Record<string, unknown>): Promise<any>;
20
+ getServerId?(): string | undefined;
21
+ getServerName?(): string | undefined;
22
+ getSessionId?(): string;
23
+ }
24
+ /**
25
+ * A provider that manages multiple `ToolClient` instances.
26
+ *
27
+ * `MultiSessionClient` satisfies this interface. Pass it directly
28
+ * to `ToolRouter` or adapters to aggregate tools from all connected servers.
29
+ */
30
+ interface ToolClientProvider {
31
+ getClients(): ToolClient[];
32
+ }
7
33
  interface ConnectRequest {
8
34
  serverUrl: string;
9
35
  callbackUrl: string;
@@ -156,4 +182,4 @@ interface ListResourcesResult {
156
182
  }>;
157
183
  }
158
184
 
159
- export { type CallToolParams as C, type DisconnectParams as D, type FinishAuthParams as F, type GetPromptParams as G, type ListPromptsResult as L, type McpRpcMethod as M, type ReadResourceParams as R, type SessionInfo as S, type ToolInfo as T, type CallToolRequest as a, type CallToolResponse as b, type ConnectAuthRequiredResponse as c, type ConnectErrorResponse as d, type ConnectParams as e, type ConnectRequest as f, type ConnectResponse as g, type ConnectResult as h, type ConnectSuccessResponse as i, type DisconnectResult as j, type FinishAuthResult as k, type ListResourcesResult as l, type ListToolsResponse as m, type ListToolsRpcResult as n, type McpRpcParams as o, type McpRpcRequest as p, type McpRpcResponse as q, type RestoreSessionResult as r, type SessionListResult as s, type SessionParams as t, type TransportType as u, isCallToolSuccess as v, isConnectAuthRequired as w, isConnectError as x, isConnectSuccess as y, isListToolsSuccess as z };
185
+ export { isConnectSuccess as A, isListToolsSuccess as B, type CallToolParams as C, type DisconnectParams as D, type FinishAuthParams as F, type GetPromptParams as G, type ListPromptsResult as L, type McpRpcMethod as M, type ReadResourceParams as R, type SessionInfo as S, type ToolClient as T, type CallToolRequest as a, type CallToolResponse as b, type ConnectAuthRequiredResponse as c, type ConnectErrorResponse as d, type ConnectParams as e, type ConnectRequest as f, type ConnectResponse as g, type ConnectResult as h, type ConnectSuccessResponse as i, type DisconnectResult as j, type FinishAuthResult as k, type ListResourcesResult as l, type ListToolsResponse as m, type ListToolsRpcResult as n, type McpRpcParams as o, type McpRpcRequest as p, type McpRpcResponse as q, type RestoreSessionResult as r, type SessionListResult as s, type SessionParams as t, type ToolClientProvider as u, type ToolInfo as v, type TransportType as w, isCallToolSuccess as x, isConnectAuthRequired as y, isConnectError as z };
@@ -4,6 +4,32 @@ import { Tool } from '@modelcontextprotocol/sdk/types.js';
4
4
  * Type definitions for MCP operations
5
5
  */
6
6
 
7
+ /**
8
+ * A client that can list and execute MCP tools.
9
+ *
10
+ * This is the structural interface that `ToolRouter`, adapters, and other
11
+ * consumers use to interact with any MCP client implementation.
12
+ * Both `MCPClient` and `createMcpClient()` satisfy this interface.
13
+ */
14
+ interface ToolClient {
15
+ isConnected(): boolean;
16
+ listTools(): Promise<{
17
+ tools: Tool[];
18
+ }>;
19
+ callTool(name: string, args: Record<string, unknown>): Promise<any>;
20
+ getServerId?(): string | undefined;
21
+ getServerName?(): string | undefined;
22
+ getSessionId?(): string;
23
+ }
24
+ /**
25
+ * A provider that manages multiple `ToolClient` instances.
26
+ *
27
+ * `MultiSessionClient` satisfies this interface. Pass it directly
28
+ * to `ToolRouter` or adapters to aggregate tools from all connected servers.
29
+ */
30
+ interface ToolClientProvider {
31
+ getClients(): ToolClient[];
32
+ }
7
33
  interface ConnectRequest {
8
34
  serverUrl: string;
9
35
  callbackUrl: string;
@@ -156,4 +182,4 @@ interface ListResourcesResult {
156
182
  }>;
157
183
  }
158
184
 
159
- export { type CallToolParams as C, type DisconnectParams as D, type FinishAuthParams as F, type GetPromptParams as G, type ListPromptsResult as L, type McpRpcMethod as M, type ReadResourceParams as R, type SessionInfo as S, type ToolInfo as T, type CallToolRequest as a, type CallToolResponse as b, type ConnectAuthRequiredResponse as c, type ConnectErrorResponse as d, type ConnectParams as e, type ConnectRequest as f, type ConnectResponse as g, type ConnectResult as h, type ConnectSuccessResponse as i, type DisconnectResult as j, type FinishAuthResult as k, type ListResourcesResult as l, type ListToolsResponse as m, type ListToolsRpcResult as n, type McpRpcParams as o, type McpRpcRequest as p, type McpRpcResponse as q, type RestoreSessionResult as r, type SessionListResult as s, type SessionParams as t, type TransportType as u, isCallToolSuccess as v, isConnectAuthRequired as w, isConnectError as x, isConnectSuccess as y, isListToolsSuccess as z };
185
+ export { isConnectSuccess as A, isListToolsSuccess as B, type CallToolParams as C, type DisconnectParams as D, type FinishAuthParams as F, type GetPromptParams as G, type ListPromptsResult as L, type McpRpcMethod as M, type ReadResourceParams as R, type SessionInfo as S, type ToolClient as T, type CallToolRequest as a, type CallToolResponse as b, type ConnectAuthRequiredResponse as c, type ConnectErrorResponse as d, type ConnectParams as e, type ConnectRequest as f, type ConnectResponse as g, type ConnectResult as h, type ConnectSuccessResponse as i, type DisconnectResult as j, type FinishAuthResult as k, type ListResourcesResult as l, type ListToolsResponse as m, type ListToolsRpcResult as n, type McpRpcParams as o, type McpRpcRequest as p, type McpRpcResponse as q, type RestoreSessionResult as r, type SessionListResult as s, type SessionParams as t, type ToolClientProvider as u, type ToolInfo as v, type TransportType as w, isCallToolSuccess as x, isConnectAuthRequired as y, isConnectError as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mcp-ts/sdk",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -86,7 +86,8 @@
86
86
  "test:debug": "npx playwright test --debug",
87
87
  "supabase:push": "supabase db push",
88
88
  "supabase:reset": "supabase db reset",
89
- "supabase:status": "supabase status"
89
+ "supabase:status": "supabase status",
90
+ "mcp-docs": "npm run start --prefix packages/mcp-server-docs"
90
91
  },
91
92
  "keywords": [
92
93
  "mcp",
@@ -28,6 +28,8 @@
28
28
 
29
29
  import { MCPClient } from '../server/mcp/oauth-client.js';
30
30
  import { MultiSessionClient } from '../server/mcp/multi-session-client.js';
31
+ import { ToolRouter } from '../shared/tool-router.js';
32
+ import { executeMetaTool, isMetaTool } from '../shared/meta-tools.js';
31
33
 
32
34
  /**
33
35
  * Extended JSON Schema properties that Pydantic's strict validation rejects.
@@ -96,6 +98,11 @@ export interface AguiAdapterOptions {
96
98
  * @default serverId or 'mcp'
97
99
  */
98
100
  prefix?: string;
101
+
102
+ /**
103
+ * Optional ToolRouter for intelligent tool selection.
104
+ */
105
+ toolRouter?: ToolRouter;
99
106
  }
100
107
 
101
108
  /**
@@ -132,6 +139,10 @@ export class AguiAdapter {
132
139
  * Get tools with handlers for MCP tool execution.
133
140
  */
134
141
  async getTools(): Promise<AguiTool[]> {
142
+ if (this.options.toolRouter) {
143
+ return this.getToolsViaRouter(this.options.toolRouter);
144
+ }
145
+
135
146
  if (this.isMultiSession()) {
136
147
  const clients = (this.client as MultiSessionClient).getClients();
137
148
  const allTools: AguiTool[] = [];
@@ -147,6 +158,10 @@ export class AguiAdapter {
147
158
  * Get tool definitions in JSON Schema format for passing to remote agents.
148
159
  */
149
160
  async getToolDefinitions(): Promise<AguiToolDefinition[]> {
161
+ if (this.options.toolRouter) {
162
+ return this.getToolDefinitionsViaRouter(this.options.toolRouter);
163
+ }
164
+
150
165
  if (this.isMultiSession()) {
151
166
  const clients = (this.client as MultiSessionClient).getClients();
152
167
  const allTools: AguiToolDefinition[] = [];
@@ -219,4 +234,68 @@ export class AguiAdapter {
219
234
  };
220
235
  });
221
236
  }
237
+
238
+ /**
239
+ * Build AG-UI tools from a ToolRouter's filtered output.
240
+ *
241
+ * In `search` strategy, only meta-tools are registered with the framework.
242
+ * Real tool execution is proxied through `mcp_execute_tool` which uses
243
+ * `router.callTool()` to route to the correct MCP client.
244
+ */
245
+ private async getToolsViaRouter(router: ToolRouter): Promise<AguiTool[]> {
246
+ const filteredTools = await router.getFilteredTools();
247
+
248
+ return filteredTools.map(tool => {
249
+ const routedTool = tool as typeof tool & { sessionId?: string; serverName?: string };
250
+ const namespace = routedTool.serverName ?? routedTool.sessionId;
251
+ return {
252
+ name: isMetaTool(tool.name)
253
+ ? tool.name
254
+ : this.getRouterToolKey(tool.name, routedTool.sessionId, routedTool.serverName),
255
+ description: tool.description || `Execute ${tool.name}`,
256
+ parameters: cleanSchema(tool.inputSchema),
257
+ handler: async (args: any) => {
258
+ if (isMetaTool(tool.name)) {
259
+ const result = await executeMetaTool(
260
+ tool.name,
261
+ args,
262
+ router,
263
+ (name, toolArgs, namespace) => router.callTool(name, toolArgs, namespace)
264
+ );
265
+ if (result) {
266
+ return result.content.map((c: any) => c.text ?? '').join('\n');
267
+ }
268
+ return "Failed to execute meta-tool";
269
+ }
270
+
271
+ // For non-meta tools in 'all' or 'groups' strategy,
272
+ // route directly to the correct MCP client
273
+ return await router.callTool(tool.name, args, namespace);
274
+ }
275
+ };
276
+ });
277
+ }
278
+
279
+ private async getToolDefinitionsViaRouter(router: ToolRouter): Promise<AguiToolDefinition[]> {
280
+ const filteredTools = await router.getFilteredTools();
281
+ return filteredTools.map(tool => {
282
+ const routedTool = tool as typeof tool & { sessionId?: string; serverName?: string };
283
+ return {
284
+ name: isMetaTool(tool.name)
285
+ ? tool.name
286
+ : this.getRouterToolKey(tool.name, routedTool.sessionId, routedTool.serverName),
287
+ description: tool.description || `Execute ${tool.name}`,
288
+ parameters: cleanSchema(tool.inputSchema)
289
+ };
290
+ });
291
+ }
292
+
293
+ private getRouterToolKey(toolName: string, sessionId?: string, serverName?: string): string {
294
+ const namespace = sessionId ?? serverName ?? 'mcp';
295
+ const normalized = namespace
296
+ .toLowerCase()
297
+ .replace(/[^a-z0-9]+/g, '_')
298
+ .replace(/^_+|_+$/g, '') || 'mcp';
299
+ return `tool_${normalized}_${toolName}`;
300
+ }
222
301
  }
@@ -2,6 +2,8 @@ import { MCPClient } from '../server/mcp/oauth-client';
2
2
  import { MultiSessionClient } from '../server/mcp/multi-session-client';
3
3
  import type { JSONSchema7 } from 'json-schema';
4
4
  import type { ToolSet } from 'ai';
5
+ import { ToolRouter } from '../shared/tool-router.js';
6
+ import { executeMetaTool, isMetaTool } from '../shared/meta-tools.js';
5
7
 
6
8
  export interface AIAdapterOptions {
7
9
  /**
@@ -9,6 +11,17 @@ export interface AIAdapterOptions {
9
11
  * Defaults to the client's serverId.
10
12
  */
11
13
  prefix?: string;
14
+
15
+ /**
16
+ * Optional ToolRouter for intelligent tool selection.
17
+ *
18
+ * When provided with `strategy: 'search'`, the adapter exposes only
19
+ * meta-tools (search_tools, get_tool_schema) instead of all tool schemas,
20
+ * reducing context window usage by 80–95%.
21
+ *
22
+ * When not provided, all tools are returned as before (backward-compatible).
23
+ */
24
+ toolRouter?: ToolRouter;
12
25
  }
13
26
 
14
27
  /**
@@ -80,6 +93,11 @@ export class AIAdapter {
80
93
  async getTools(): Promise<ToolSet> {
81
94
  await this.ensureJsonSchema();
82
95
 
96
+ // If a ToolRouter is provided, use its filtered output
97
+ if (this.options.toolRouter) {
98
+ return this.getToolsViaRouter(this.options.toolRouter);
99
+ }
100
+
83
101
  // Use duck typing instead of instanceof to handle module bundling issues
84
102
  // MultiSessionClient has getClients(), MCPClient does not
85
103
  const isMultiSession = typeof (this.client as any).getClients === 'function';
@@ -106,6 +124,63 @@ export class AIAdapter {
106
124
  return results.reduce((acc, tools) => ({ ...acc, ...tools }), {});
107
125
  }
108
126
 
127
+ /**
128
+ * Build a ToolSet from a ToolRouter's filtered output.
129
+ *
130
+ * In `search` strategy, only meta-tools are registered with the framework.
131
+ * Real tool execution is proxied through `mcp_execute_tool` which uses
132
+ * `router.callTool()` to route to the correct MCP client.
133
+ */
134
+ private async getToolsViaRouter(router: ToolRouter): Promise<ToolSet> {
135
+ const filteredTools = await router.getFilteredTools();
136
+
137
+ // @ts-ignore: ToolSet type inference can be tricky with dynamic imports
138
+ return Object.fromEntries(
139
+ filteredTools.map((tool) => {
140
+ const routedTool = tool as typeof tool & { sessionId?: string; serverName?: string };
141
+ const namespace = routedTool.serverName ?? routedTool.sessionId;
142
+ const toolKey = isMetaTool(tool.name)
143
+ ? tool.name
144
+ : this.getRouterToolKey(tool.name, routedTool.sessionId, routedTool.serverName);
145
+
146
+ return [
147
+ toolKey,
148
+ {
149
+ description: tool.description,
150
+ inputSchema: this.jsonSchema!(tool.inputSchema as JSONSchema7),
151
+ execute: async (args: any) => {
152
+ // Handle meta-tool calls via the router
153
+ if (isMetaTool(tool.name)) {
154
+ const result = await executeMetaTool(
155
+ tool.name,
156
+ args,
157
+ router,
158
+ (name, toolArgs, targetNamespace) => router.callTool(name, toolArgs, targetNamespace)
159
+ );
160
+ if (result) {
161
+ return result;
162
+ }
163
+ }
164
+
165
+ // For non-meta tools in 'all' or 'groups' strategy,
166
+ // route directly to the correct MCP client
167
+ return await router.callTool(tool.name, args, namespace);
168
+ },
169
+ },
170
+ ];
171
+ })
172
+ );
173
+ }
174
+
175
+ private getRouterToolKey(toolName: string, sessionId?: string, serverName?: string): string {
176
+ const namespace = sessionId ?? serverName ?? 'mcp';
177
+ const normalized = namespace
178
+ .toLowerCase()
179
+ .replace(/[^a-z0-9]+/g, '_')
180
+ .replace(/^_+|_+$/g, '') || 'mcp';
181
+ return `tool_${normalized}_${toolName}`;
182
+ }
183
+
109
184
  /**
110
185
  * Convenience static method to fetch tools in a single line.
111
186
  */