@mcp-ts/sdk 1.4.0 → 1.5.1
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/README.md +20 -27
- package/dist/adapters/agui-adapter.d.mts +16 -0
- package/dist/adapters/agui-adapter.d.ts +16 -0
- package/dist/adapters/agui-adapter.js +185 -0
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +185 -0
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +2 -0
- package/dist/adapters/agui-middleware.d.ts +2 -0
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/adapters/ai-adapter.d.mts +21 -0
- package/dist/adapters/ai-adapter.d.ts +21 -0
- package/dist/adapters/ai-adapter.js +175 -0
- package/dist/adapters/ai-adapter.js.map +1 -1
- package/dist/adapters/ai-adapter.mjs +175 -0
- package/dist/adapters/ai-adapter.mjs.map +1 -1
- package/dist/adapters/langchain-adapter.d.mts +16 -0
- package/dist/adapters/langchain-adapter.d.ts +16 -0
- package/dist/adapters/langchain-adapter.js +179 -0
- package/dist/adapters/langchain-adapter.js.map +1 -1
- package/dist/adapters/langchain-adapter.mjs +179 -0
- package/dist/adapters/langchain-adapter.mjs.map +1 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/react.d.mts +94 -8
- package/dist/client/react.d.ts +94 -8
- package/dist/client/react.js +364 -26
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +358 -27
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +4 -4
- package/dist/client/vue.d.ts +4 -4
- package/dist/client/vue.js +11 -2
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +11 -2
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{index-CQr9q0bF.d.mts → index-DcYfpY3H.d.mts} +1 -1
- package/dist/{index-nE_7Io0I.d.ts → index-GfC_eNEv.d.ts} +1 -1
- package/dist/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +938 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +923 -13
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +58 -12
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +58 -12
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +86 -4
- package/dist/shared/index.d.ts +86 -4
- package/dist/shared/index.js +874 -0
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +865 -1
- package/dist/shared/index.mjs.map +1 -1
- package/dist/tool-router-Bo8qZbsD.d.ts +325 -0
- package/dist/tool-router-XnWVxPzv.d.mts +325 -0
- package/dist/{types-CW6lghof.d.mts → types-CfCoIsWI.d.mts} +27 -1
- package/dist/{types-CW6lghof.d.ts → types-CfCoIsWI.d.ts} +27 -1
- package/package.json +3 -2
- package/src/adapters/agui-adapter.ts +79 -0
- package/src/adapters/ai-adapter.ts +75 -0
- package/src/adapters/langchain-adapter.ts +74 -0
- package/src/client/react/index.ts +16 -0
- package/src/client/react/oauth-popup.tsx +446 -0
- package/src/client/react/use-mcp-apps.tsx +50 -32
- package/src/client/react/use-mcp.ts +36 -3
- package/src/client/vue/use-mcp.ts +38 -3
- package/src/server/handlers/sse-handler.ts +39 -0
- package/src/server/index.ts +2 -0
- package/src/server/mcp/oauth-client.ts +35 -15
- package/src/shared/index.ts +36 -0
- package/src/shared/meta-tools.ts +387 -0
- package/src/shared/schema-compressor.ts +124 -0
- package/src/shared/tool-index.ts +499 -0
- package/src/shared/tool-router.ts +469 -0
- package/src/shared/types.ts +30 -0
- package/supabase/migrations/20260421010000_add_session_cleanup_cron.sql +32 -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
|
|
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
|
|
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.
|
|
3
|
+
"version": "1.5.1",
|
|
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
|
*/
|