@mcp-ts/sdk 1.5.2 → 1.6.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.
- package/README.md +89 -27
- package/dist/adapters/agui-adapter.d.mts +1 -1
- package/dist/adapters/agui-adapter.d.ts +1 -1
- package/dist/adapters/agui-adapter.js +76 -19
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +76 -19
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +5 -1
- package/dist/adapters/agui-middleware.d.ts +5 -1
- package/dist/adapters/agui-middleware.js +116 -49
- package/dist/adapters/agui-middleware.js.map +1 -1
- package/dist/adapters/agui-middleware.mjs +117 -50
- package/dist/adapters/agui-middleware.mjs.map +1 -1
- package/dist/adapters/ai-adapter.d.mts +1 -1
- package/dist/adapters/ai-adapter.d.ts +1 -1
- package/dist/adapters/ai-adapter.js +76 -19
- package/dist/adapters/ai-adapter.js.map +1 -1
- package/dist/adapters/ai-adapter.mjs +76 -19
- package/dist/adapters/ai-adapter.mjs.map +1 -1
- package/dist/adapters/langchain-adapter.d.mts +1 -1
- package/dist/adapters/langchain-adapter.d.ts +1 -1
- package/dist/adapters/langchain-adapter.js +76 -19
- package/dist/adapters/langchain-adapter.js.map +1 -1
- package/dist/adapters/langchain-adapter.mjs +76 -19
- package/dist/adapters/langchain-adapter.mjs.map +1 -1
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +207 -43
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +207 -44
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.js +1 -3
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +1 -3
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +15 -8
- package/dist/shared/index.d.ts +15 -8
- package/dist/shared/index.js +206 -40
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +206 -41
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{tool-router-DsKhRmJm.d.ts → tool-router-Bn9R0KWr.d.ts} +56 -7
- package/dist/{tool-router-DK0RJblO.d.mts → tool-router-_O2tIwf7.d.mts} +56 -7
- package/package.json +5 -3
- package/src/adapters/agui-middleware.ts +163 -59
- package/src/server/mcp/oauth-client.ts +4 -4
- package/src/shared/index.ts +4 -0
- package/src/shared/meta-tools.ts +172 -37
- package/src/shared/tool-index.ts +123 -7
- package/src/shared/tool-router.ts +40 -7
package/dist/shared/index.d.mts
CHANGED
|
@@ -2,8 +2,8 @@ export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, M as M
|
|
|
2
2
|
export { A as AuthenticationError, C as ConfigurationError, a as ConnectionError, I as InvalidStateError, M as McpError, N as NotConnectedError, R as RpcErrorCode, b as RpcErrorCodes, S as SessionNotFoundError, c as SessionValidationError, T as ToolExecutionError, U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-0qmYrqoa.mjs';
|
|
3
3
|
import { v as ToolInfo } from '../types-CfCoIsWI.mjs';
|
|
4
4
|
export { C as CallToolParams, a as CallToolRequest, b as CallToolResponse, c as ConnectAuthRequiredResponse, d as ConnectErrorResponse, e as ConnectParams, f as ConnectRequest, g as ConnectResponse, h as ConnectResult, i as ConnectSuccessResponse, D as DisconnectParams, j as DisconnectResult, F as FinishAuthParams, k as FinishAuthResult, G as GetPromptParams, L as ListPromptsResult, l as ListResourcesResult, m as ListToolsResponse, n as ListToolsRpcResult, M as McpRpcMethod, o as McpRpcParams, p as McpRpcRequest, q as McpRpcResponse, R as ReadResourceParams, r as RestoreSessionResult, S as SessionInfo, s as SessionListResult, t as SessionParams, T as ToolClient, u as ToolClientProvider, w as TransportType, x as isCallToolSuccess, y as isConnectAuthRequired, z as isConnectError, A as isConnectSuccess, B as isListToolsSuccess } from '../types-CfCoIsWI.mjs';
|
|
5
|
-
import {
|
|
6
|
-
export { C as CompactTool, a as CompressionStats, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, b as ToolIndex, c as ToolIndexOptions,
|
|
5
|
+
import { e as ToolRouter } from '../tool-router-_O2tIwf7.mjs';
|
|
6
|
+
export { C as CompactTool, a as CompressionStats, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, b as ToolIndex, c as ToolIndexOptions, d as ToolListResult, f as ToolRouterClientInput, g as ToolRouterOptions, h as ToolRouterStrategy, i as ToolSearchOptions, j as ToolServerSummary, k as ToolSummary } from '../tool-router-_O2tIwf7.mjs';
|
|
7
7
|
import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -68,7 +68,7 @@ declare function findToolByName(connections: Array<{
|
|
|
68
68
|
* only the tools it actually needs.
|
|
69
69
|
*
|
|
70
70
|
* Meta-tools:
|
|
71
|
-
* • `
|
|
71
|
+
* • `mcp_search_tools` — Search/list available tools
|
|
72
72
|
* • `mcp_search_tool_regex` — Regex pattern search
|
|
73
73
|
* • `mcp_get_tool_schema` — Get full inputSchema for a discovered tool
|
|
74
74
|
* • `mcp_execute_tool` — Execute a discovered tool
|
|
@@ -77,13 +77,20 @@ declare function findToolByName(connections: Array<{
|
|
|
77
77
|
*/
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
* Creates the `
|
|
80
|
+
* Creates the `mcp_search_tools` tool definition.
|
|
81
81
|
*
|
|
82
82
|
* This tool lets the LLM search the full catalog of available MCP tools
|
|
83
83
|
* using a BM25 natural-language query. Returns tool names and descriptions
|
|
84
84
|
* without the full inputSchema to save context space.
|
|
85
85
|
*/
|
|
86
86
|
declare function createSearchToolDefinition(): Tool;
|
|
87
|
+
/**
|
|
88
|
+
* Creates the `mcp_list_servers` tool definition.
|
|
89
|
+
*
|
|
90
|
+
* This tool lets the LLM inspect connected MCP servers before doing
|
|
91
|
+
* server-scoped tool discovery.
|
|
92
|
+
*/
|
|
93
|
+
declare function createListServersToolDefinition(): Tool;
|
|
87
94
|
/**
|
|
88
95
|
* Creates the `mcp_search_tool_regex` tool definition.
|
|
89
96
|
*
|
|
@@ -93,7 +100,7 @@ declare function createRegexSearchToolDefinition(): Tool;
|
|
|
93
100
|
/**
|
|
94
101
|
* Creates the `mcp_get_tool_schema` tool definition.
|
|
95
102
|
*
|
|
96
|
-
* After discovering tools via `
|
|
103
|
+
* After discovering tools via `mcp_search_tools` or
|
|
97
104
|
* `mcp_search_tool_regex`, the LLM calls this to load the full
|
|
98
105
|
* inputSchema for a specific tool so it can construct the correct
|
|
99
106
|
* arguments.
|
|
@@ -103,7 +110,7 @@ declare function createGetSchemaToolDefinition(): Tool;
|
|
|
103
110
|
* Creates the `mcp_execute_tool` tool definition.
|
|
104
111
|
*
|
|
105
112
|
* This is the execution meta-tool — the LLM calls this to execute any
|
|
106
|
-
* tool discovered via `
|
|
113
|
+
* tool discovered via `mcp_search_tools` or `mcp_search_tool_regex`.
|
|
107
114
|
* The LLM should first call `mcp_get_tool_schema` to know the correct
|
|
108
115
|
* arguments.
|
|
109
116
|
*
|
|
@@ -119,7 +126,7 @@ type CallToolFn = (toolName: string, args: Record<string, unknown>, namespace?:
|
|
|
119
126
|
/**
|
|
120
127
|
* Execute a meta-tool call and return the result in MCP CallToolResult format.
|
|
121
128
|
*
|
|
122
|
-
* @param toolName - One of the meta-tool names (
|
|
129
|
+
* @param toolName - One of the meta-tool names (mcp_search_tools, mcp_list_servers, mcp_search_tool_regex, etc.)
|
|
123
130
|
* @param args - The arguments from the LLM's tool call
|
|
124
131
|
* @param router - The ToolRouter to query
|
|
125
132
|
* @param callToolFn - Optional callback for executing real tools (required for mcp_execute_tool)
|
|
@@ -139,4 +146,4 @@ declare function resolveMetaToolProxy(toolName: string, args: Record<string, unk
|
|
|
139
146
|
args: Record<string, unknown>;
|
|
140
147
|
};
|
|
141
148
|
|
|
142
|
-
export { type CallToolFn, DEFAULT_CLIENT_NAME, DEFAULT_CLIENT_URI, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_LOGO_URI, DEFAULT_POLICY_URI, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, REDIS_KEY_PREFIX, SESSION_TTL_SECONDS, SOFTWARE_ID, SOFTWARE_VERSION, STATE_EXPIRATION_MS, TOKEN_EXPIRY_BUFFER_MS, ToolInfo, ToolRouter, type ToolUiConfig, createExecuteToolDefinition, createGetSchemaToolDefinition, createRegexSearchToolDefinition, createSearchToolDefinition, executeMetaTool, findToolByName, getToolUiResourceUri, isMetaTool, resolveMetaToolProxy };
|
|
149
|
+
export { type CallToolFn, DEFAULT_CLIENT_NAME, DEFAULT_CLIENT_URI, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_LOGO_URI, DEFAULT_POLICY_URI, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, REDIS_KEY_PREFIX, SESSION_TTL_SECONDS, SOFTWARE_ID, SOFTWARE_VERSION, STATE_EXPIRATION_MS, TOKEN_EXPIRY_BUFFER_MS, ToolInfo, ToolRouter, type ToolUiConfig, createExecuteToolDefinition, createGetSchemaToolDefinition, createListServersToolDefinition, createRegexSearchToolDefinition, createSearchToolDefinition, executeMetaTool, findToolByName, getToolUiResourceUri, isMetaTool, resolveMetaToolProxy };
|
package/dist/shared/index.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, M as M
|
|
|
2
2
|
export { A as AuthenticationError, C as ConfigurationError, a as ConnectionError, I as InvalidStateError, M as McpError, N as NotConnectedError, R as RpcErrorCode, b as RpcErrorCodes, S as SessionNotFoundError, c as SessionValidationError, T as ToolExecutionError, U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-0qmYrqoa.js';
|
|
3
3
|
import { v as ToolInfo } from '../types-CfCoIsWI.js';
|
|
4
4
|
export { C as CallToolParams, a as CallToolRequest, b as CallToolResponse, c as ConnectAuthRequiredResponse, d as ConnectErrorResponse, e as ConnectParams, f as ConnectRequest, g as ConnectResponse, h as ConnectResult, i as ConnectSuccessResponse, D as DisconnectParams, j as DisconnectResult, F as FinishAuthParams, k as FinishAuthResult, G as GetPromptParams, L as ListPromptsResult, l as ListResourcesResult, m as ListToolsResponse, n as ListToolsRpcResult, M as McpRpcMethod, o as McpRpcParams, p as McpRpcRequest, q as McpRpcResponse, R as ReadResourceParams, r as RestoreSessionResult, S as SessionInfo, s as SessionListResult, t as SessionParams, T as ToolClient, u as ToolClientProvider, w as TransportType, x as isCallToolSuccess, y as isConnectAuthRequired, z as isConnectError, A as isConnectSuccess, B as isListToolsSuccess } from '../types-CfCoIsWI.js';
|
|
5
|
-
import {
|
|
6
|
-
export { C as CompactTool, a as CompressionStats, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, b as ToolIndex, c as ToolIndexOptions,
|
|
5
|
+
import { e as ToolRouter } from '../tool-router-Bn9R0KWr.js';
|
|
6
|
+
export { C as CompactTool, a as CompressionStats, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, b as ToolIndex, c as ToolIndexOptions, d as ToolListResult, f as ToolRouterClientInput, g as ToolRouterOptions, h as ToolRouterStrategy, i as ToolSearchOptions, j as ToolServerSummary, k as ToolSummary } from '../tool-router-Bn9R0KWr.js';
|
|
7
7
|
import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -68,7 +68,7 @@ declare function findToolByName(connections: Array<{
|
|
|
68
68
|
* only the tools it actually needs.
|
|
69
69
|
*
|
|
70
70
|
* Meta-tools:
|
|
71
|
-
* • `
|
|
71
|
+
* • `mcp_search_tools` — Search/list available tools
|
|
72
72
|
* • `mcp_search_tool_regex` — Regex pattern search
|
|
73
73
|
* • `mcp_get_tool_schema` — Get full inputSchema for a discovered tool
|
|
74
74
|
* • `mcp_execute_tool` — Execute a discovered tool
|
|
@@ -77,13 +77,20 @@ declare function findToolByName(connections: Array<{
|
|
|
77
77
|
*/
|
|
78
78
|
|
|
79
79
|
/**
|
|
80
|
-
* Creates the `
|
|
80
|
+
* Creates the `mcp_search_tools` tool definition.
|
|
81
81
|
*
|
|
82
82
|
* This tool lets the LLM search the full catalog of available MCP tools
|
|
83
83
|
* using a BM25 natural-language query. Returns tool names and descriptions
|
|
84
84
|
* without the full inputSchema to save context space.
|
|
85
85
|
*/
|
|
86
86
|
declare function createSearchToolDefinition(): Tool;
|
|
87
|
+
/**
|
|
88
|
+
* Creates the `mcp_list_servers` tool definition.
|
|
89
|
+
*
|
|
90
|
+
* This tool lets the LLM inspect connected MCP servers before doing
|
|
91
|
+
* server-scoped tool discovery.
|
|
92
|
+
*/
|
|
93
|
+
declare function createListServersToolDefinition(): Tool;
|
|
87
94
|
/**
|
|
88
95
|
* Creates the `mcp_search_tool_regex` tool definition.
|
|
89
96
|
*
|
|
@@ -93,7 +100,7 @@ declare function createRegexSearchToolDefinition(): Tool;
|
|
|
93
100
|
/**
|
|
94
101
|
* Creates the `mcp_get_tool_schema` tool definition.
|
|
95
102
|
*
|
|
96
|
-
* After discovering tools via `
|
|
103
|
+
* After discovering tools via `mcp_search_tools` or
|
|
97
104
|
* `mcp_search_tool_regex`, the LLM calls this to load the full
|
|
98
105
|
* inputSchema for a specific tool so it can construct the correct
|
|
99
106
|
* arguments.
|
|
@@ -103,7 +110,7 @@ declare function createGetSchemaToolDefinition(): Tool;
|
|
|
103
110
|
* Creates the `mcp_execute_tool` tool definition.
|
|
104
111
|
*
|
|
105
112
|
* This is the execution meta-tool — the LLM calls this to execute any
|
|
106
|
-
* tool discovered via `
|
|
113
|
+
* tool discovered via `mcp_search_tools` or `mcp_search_tool_regex`.
|
|
107
114
|
* The LLM should first call `mcp_get_tool_schema` to know the correct
|
|
108
115
|
* arguments.
|
|
109
116
|
*
|
|
@@ -119,7 +126,7 @@ type CallToolFn = (toolName: string, args: Record<string, unknown>, namespace?:
|
|
|
119
126
|
/**
|
|
120
127
|
* Execute a meta-tool call and return the result in MCP CallToolResult format.
|
|
121
128
|
*
|
|
122
|
-
* @param toolName - One of the meta-tool names (
|
|
129
|
+
* @param toolName - One of the meta-tool names (mcp_search_tools, mcp_list_servers, mcp_search_tool_regex, etc.)
|
|
123
130
|
* @param args - The arguments from the LLM's tool call
|
|
124
131
|
* @param router - The ToolRouter to query
|
|
125
132
|
* @param callToolFn - Optional callback for executing real tools (required for mcp_execute_tool)
|
|
@@ -139,4 +146,4 @@ declare function resolveMetaToolProxy(toolName: string, args: Record<string, unk
|
|
|
139
146
|
args: Record<string, unknown>;
|
|
140
147
|
};
|
|
141
148
|
|
|
142
|
-
export { type CallToolFn, DEFAULT_CLIENT_NAME, DEFAULT_CLIENT_URI, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_LOGO_URI, DEFAULT_POLICY_URI, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, REDIS_KEY_PREFIX, SESSION_TTL_SECONDS, SOFTWARE_ID, SOFTWARE_VERSION, STATE_EXPIRATION_MS, TOKEN_EXPIRY_BUFFER_MS, ToolInfo, ToolRouter, type ToolUiConfig, createExecuteToolDefinition, createGetSchemaToolDefinition, createRegexSearchToolDefinition, createSearchToolDefinition, executeMetaTool, findToolByName, getToolUiResourceUri, isMetaTool, resolveMetaToolProxy };
|
|
149
|
+
export { type CallToolFn, DEFAULT_CLIENT_NAME, DEFAULT_CLIENT_URI, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_LOGO_URI, DEFAULT_POLICY_URI, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, REDIS_KEY_PREFIX, SESSION_TTL_SECONDS, SOFTWARE_ID, SOFTWARE_VERSION, STATE_EXPIRATION_MS, TOKEN_EXPIRY_BUFFER_MS, ToolInfo, ToolRouter, type ToolUiConfig, createExecuteToolDefinition, createGetSchemaToolDefinition, createListServersToolDefinition, createRegexSearchToolDefinition, createSearchToolDefinition, executeMetaTool, findToolByName, getToolUiResourceUri, isMetaTool, resolveMetaToolProxy };
|
package/dist/shared/index.js
CHANGED
|
@@ -340,17 +340,17 @@ var ToolIndex = class _ToolIndex {
|
|
|
340
340
|
*
|
|
341
341
|
* `score = keywordWeight × keyword_score + (1 - keywordWeight) × cosine_score`
|
|
342
342
|
*/
|
|
343
|
-
async search(query, topK = 5) {
|
|
343
|
+
async search(query, topK = 5, options = {}) {
|
|
344
344
|
if (this.tools.size === 0) return [];
|
|
345
345
|
const queryLower = query.toLowerCase().trim();
|
|
346
346
|
const exactMatches = [...this.toolSummaries.values()].filter(
|
|
347
|
-
(summary) => summary.name.toLowerCase() === queryLower
|
|
347
|
+
(summary) => summary.name.toLowerCase() === queryLower && this.matchesServer(summary, options)
|
|
348
348
|
);
|
|
349
349
|
if (exactMatches.length > 0) {
|
|
350
350
|
return exactMatches.slice(0, topK);
|
|
351
351
|
}
|
|
352
352
|
if (queryLower.startsWith("mcp__") && queryLower.length > 5) {
|
|
353
|
-
const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower)).slice(0, topK);
|
|
353
|
+
const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower) && this.matchesServer(t, options)).slice(0, topK);
|
|
354
354
|
if (prefixMatches.length > 0) return prefixMatches;
|
|
355
355
|
}
|
|
356
356
|
const queryTermsRaw = queryLower.split(/\s+/).filter((t) => t.length > 0);
|
|
@@ -368,9 +368,10 @@ var ToolIndex = class _ToolIndex {
|
|
|
368
368
|
const queryTokens = this.tokenize(allScoringTerms.join(" "));
|
|
369
369
|
const candidateKeys = /* @__PURE__ */ new Set();
|
|
370
370
|
for (const docKey of this.toolSummaries.keys()) {
|
|
371
|
+
const summary = this.toolSummaries.get(docKey);
|
|
372
|
+
if (!this.matchesServer(summary, options)) continue;
|
|
371
373
|
if (requiredTerms.length > 0) {
|
|
372
374
|
const text = this.searchTexts.get(docKey) || "";
|
|
373
|
-
const summary = this.toolSummaries.get(docKey);
|
|
374
375
|
const nameLower = summary.name.toLowerCase();
|
|
375
376
|
const matchesAll = requiredTerms.every(
|
|
376
377
|
(term) => text.includes(term) || nameLower.includes(term)
|
|
@@ -481,17 +482,66 @@ var ToolIndex = class _ToolIndex {
|
|
|
481
482
|
// -----------------------------------------------------------------------
|
|
482
483
|
/**
|
|
483
484
|
* Get tool definition(s) by name.
|
|
484
|
-
* If namespace is provided,
|
|
485
|
+
* If namespace is provided, exact sessionId/serverId matches take precedence.
|
|
486
|
+
* Falls back to serverName fragment matching only when explicitly allowed.
|
|
485
487
|
*/
|
|
486
|
-
getTool(name, namespace) {
|
|
488
|
+
getTool(name, namespace, options = {}) {
|
|
487
489
|
const list = this.tools.get(name) ?? [];
|
|
488
490
|
if (!namespace) return list;
|
|
489
|
-
|
|
491
|
+
const exactMatches = list.filter(
|
|
492
|
+
(t) => t.sessionId === namespace || t.serverId === namespace
|
|
493
|
+
);
|
|
494
|
+
if (exactMatches.length > 0) return exactMatches;
|
|
495
|
+
if (!options.allowServerNameFragment) return [];
|
|
496
|
+
const namespaceLower = namespace.toLowerCase();
|
|
497
|
+
return list.filter((t) => t.serverName.toLowerCase().includes(namespaceLower));
|
|
490
498
|
}
|
|
491
499
|
/** All indexed tool names. */
|
|
492
500
|
getToolNames() {
|
|
493
501
|
return [...this.tools.keys()];
|
|
494
502
|
}
|
|
503
|
+
/** List indexed servers with tool counts. */
|
|
504
|
+
listServers(options = {}) {
|
|
505
|
+
const servers = /* @__PURE__ */ new Map();
|
|
506
|
+
for (const summary of this.toolSummaries.values()) {
|
|
507
|
+
if (!this.matchesServer(summary, options)) continue;
|
|
508
|
+
const key = `${summary.sessionId}::${summary.serverId}`;
|
|
509
|
+
const existing = servers.get(key);
|
|
510
|
+
if (existing) {
|
|
511
|
+
existing.toolCount += 1;
|
|
512
|
+
} else {
|
|
513
|
+
servers.set(key, {
|
|
514
|
+
serverName: summary.serverName,
|
|
515
|
+
serverId: summary.serverId,
|
|
516
|
+
sessionId: summary.sessionId,
|
|
517
|
+
toolCount: 1
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return [...servers.values()].sort((a, b) => {
|
|
522
|
+
const byName = a.serverName.localeCompare(b.serverName);
|
|
523
|
+
return byName !== 0 ? byName : a.serverId.localeCompare(b.serverId);
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
/** List tools deterministically, optionally scoped to a server. */
|
|
527
|
+
listTools(options = {}) {
|
|
528
|
+
const offset = Math.max(Number(options.cursor) || 0, 0);
|
|
529
|
+
const limit = Math.max(Number(options.limit) || 20, 1);
|
|
530
|
+
const tools = [...this.toolSummaries.values()].filter((summary) => this.matchesServer(summary, options)).sort((a, b) => {
|
|
531
|
+
const byServer = a.serverName.localeCompare(b.serverName);
|
|
532
|
+
if (byServer !== 0) return byServer;
|
|
533
|
+
return a.name.localeCompare(b.name);
|
|
534
|
+
});
|
|
535
|
+
const page = tools.slice(offset, offset + limit);
|
|
536
|
+
const nextOffset = offset + page.length;
|
|
537
|
+
return {
|
|
538
|
+
tools: page,
|
|
539
|
+
totalCount: tools.length,
|
|
540
|
+
returnedCount: page.length,
|
|
541
|
+
nextCursor: nextOffset < tools.length ? String(nextOffset) : void 0,
|
|
542
|
+
servers: this.listServers(options)
|
|
543
|
+
};
|
|
544
|
+
}
|
|
495
545
|
/** Number of indexed tools (including duplicates). */
|
|
496
546
|
get size() {
|
|
497
547
|
let count = 0;
|
|
@@ -548,6 +598,20 @@ var ToolIndex = class _ToolIndex {
|
|
|
548
598
|
getDocumentKey(tool) {
|
|
549
599
|
return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
|
|
550
600
|
}
|
|
601
|
+
matchesServer(summary, options) {
|
|
602
|
+
if (options.serverId && summary.serverId !== options.serverId) {
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
if (options.serverName) {
|
|
606
|
+
const serverNameQuery = options.serverName.toLowerCase();
|
|
607
|
+
const serverName = summary.serverName.toLowerCase();
|
|
608
|
+
const serverId = summary.serverId.toLowerCase();
|
|
609
|
+
if (!serverName.includes(serverNameQuery) && !serverId.includes(serverNameQuery)) {
|
|
610
|
+
return false;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
return true;
|
|
614
|
+
}
|
|
551
615
|
/** Simple whitespace + camelCase + snake_case tokenizer. */
|
|
552
616
|
tokenize(text) {
|
|
553
617
|
return text.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((t) => t.length > 1);
|
|
@@ -631,7 +695,7 @@ var SchemaCompressor = class _SchemaCompressor {
|
|
|
631
695
|
// src/shared/meta-tools.ts
|
|
632
696
|
function createSearchToolDefinition() {
|
|
633
697
|
return {
|
|
634
|
-
name: "
|
|
698
|
+
name: "mcp_search_tools",
|
|
635
699
|
description: 'Search the catalog of available tools. Returns tool names, descriptions, and server info. Use this FIRST to find relevant tools before calling them.\n\nQuery forms:\n- "select:Read,Edit,Grep" \u2014 fetch these exact tools by name\n- "notebook jupyter" \u2014 keyword search, up to limit best matches\n- "+slack send" \u2014 require "slack" in the name, rank by remaining terms',
|
|
636
700
|
inputSchema: {
|
|
637
701
|
type: "object",
|
|
@@ -640,15 +704,47 @@ function createSearchToolDefinition() {
|
|
|
640
704
|
type: "string",
|
|
641
705
|
description: 'Query to find tools. Use "select:<tool_name>" for direct selection, or keywords to search. Prefix keywords with + to require them.'
|
|
642
706
|
},
|
|
707
|
+
operation: {
|
|
708
|
+
type: "string",
|
|
709
|
+
enum: ["search", "list"],
|
|
710
|
+
description: 'Operation to perform. Use "search" to find relevant tools by capability. Use "list" with serverId or serverName when the user asks for every tool from a connected MCP server.'
|
|
711
|
+
},
|
|
712
|
+
serverId: {
|
|
713
|
+
type: "string",
|
|
714
|
+
description: "Optional server ID to restrict search/list results to one MCP server."
|
|
715
|
+
},
|
|
716
|
+
serverName: {
|
|
717
|
+
type: "string",
|
|
718
|
+
description: 'Optional server name fragment to restrict search/list results to matching MCP servers, e.g. "supabase".'
|
|
719
|
+
},
|
|
643
720
|
limit: {
|
|
644
721
|
type: "number",
|
|
645
|
-
description: "Maximum number of results to return (default: 5, max: 20)."
|
|
722
|
+
description: "Maximum number of results to return (default: 5 for search, 20 for list; max: 20 for search, 100 for list)."
|
|
723
|
+
},
|
|
724
|
+
cursor: {
|
|
725
|
+
type: "string",
|
|
726
|
+
description: 'Optional pagination cursor returned by operation "list".'
|
|
646
727
|
}
|
|
647
728
|
},
|
|
648
729
|
required: ["query"]
|
|
649
730
|
}
|
|
650
731
|
};
|
|
651
732
|
}
|
|
733
|
+
function createListServersToolDefinition() {
|
|
734
|
+
return {
|
|
735
|
+
name: "mcp_list_servers",
|
|
736
|
+
description: "List connected MCP servers and their tool counts. Use this when mcp_search_tools returns no matches, then retry mcp_search_tools with serverId or serverName.",
|
|
737
|
+
inputSchema: {
|
|
738
|
+
type: "object",
|
|
739
|
+
properties: {
|
|
740
|
+
query: {
|
|
741
|
+
type: "string",
|
|
742
|
+
description: 'Optional server filter text. Matches server name or serverId, e.g. "web" or "supabase".'
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
};
|
|
747
|
+
}
|
|
652
748
|
function createRegexSearchToolDefinition() {
|
|
653
749
|
return {
|
|
654
750
|
name: "mcp_search_tool_regex",
|
|
@@ -672,17 +768,17 @@ function createRegexSearchToolDefinition() {
|
|
|
672
768
|
function createGetSchemaToolDefinition() {
|
|
673
769
|
return {
|
|
674
770
|
name: "mcp_get_tool_schema",
|
|
675
|
-
description: "Get the full input schema (parameters) for a specific tool. Call this after
|
|
771
|
+
description: "Get the full input schema (parameters) for a specific tool. Call this after mcp_search_tools to get the parameter details needed to call a tool correctly. Do NOT call the discovered tool directly; after reading the schema, call mcp_execute_tool.",
|
|
676
772
|
inputSchema: {
|
|
677
773
|
type: "object",
|
|
678
774
|
properties: {
|
|
679
775
|
toolName: {
|
|
680
776
|
type: "string",
|
|
681
|
-
description: "The exact tool name returned by
|
|
777
|
+
description: "The exact tool name returned by mcp_search_tools."
|
|
682
778
|
},
|
|
683
779
|
serverId: {
|
|
684
780
|
type: "string",
|
|
685
|
-
description: "Optional: The server ID provided in
|
|
781
|
+
description: "Optional: The server ID provided in mcp_search_tools. Required if multiple tools have the same name."
|
|
686
782
|
}
|
|
687
783
|
},
|
|
688
784
|
required: ["toolName"]
|
|
@@ -692,17 +788,17 @@ function createGetSchemaToolDefinition() {
|
|
|
692
788
|
function createExecuteToolDefinition() {
|
|
693
789
|
return {
|
|
694
790
|
name: "mcp_execute_tool",
|
|
695
|
-
description: "Execute a tool that was discovered via
|
|
791
|
+
description: "Execute a tool that was discovered via mcp_search_tools. You MUST call mcp_get_tool_schema first to know the correct parameters. Pass the exact tool name and its arguments.",
|
|
696
792
|
inputSchema: {
|
|
697
793
|
type: "object",
|
|
698
794
|
properties: {
|
|
699
795
|
toolName: {
|
|
700
796
|
type: "string",
|
|
701
|
-
description: "The exact tool name from
|
|
797
|
+
description: "The exact tool name from mcp_search_tools results."
|
|
702
798
|
},
|
|
703
799
|
serverId: {
|
|
704
800
|
type: "string",
|
|
705
|
-
description: "Optional: The server ID provided in
|
|
801
|
+
description: "Optional: The server ID provided in mcp_search_tools. Required if multiple tools have the same name."
|
|
706
802
|
},
|
|
707
803
|
args: {
|
|
708
804
|
type: "object",
|
|
@@ -715,9 +811,9 @@ function createExecuteToolDefinition() {
|
|
|
715
811
|
};
|
|
716
812
|
}
|
|
717
813
|
async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
718
|
-
const resolveToolSchema = (name, namespace) => {
|
|
814
|
+
const resolveToolSchema = (name, namespace, options) => {
|
|
719
815
|
try {
|
|
720
|
-
return { tool: router.getToolSchema(name, namespace) };
|
|
816
|
+
return { tool: router.getToolSchema(name, namespace, options) };
|
|
721
817
|
} catch (err) {
|
|
722
818
|
const errorMessage = err instanceof Error ? err.message : String(err);
|
|
723
819
|
return {
|
|
@@ -729,23 +825,61 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
729
825
|
}
|
|
730
826
|
};
|
|
731
827
|
switch (toolName) {
|
|
732
|
-
case "
|
|
828
|
+
case "mcp_search_tools": {
|
|
733
829
|
const query = String(args.query ?? "");
|
|
830
|
+
const operation = String(args.operation ?? "search");
|
|
831
|
+
const serverId = String(args.serverId ?? "") || void 0;
|
|
832
|
+
const serverName = String(args.serverName ?? "") || void 0;
|
|
833
|
+
if (operation === "list") {
|
|
834
|
+
const limit2 = Math.min(Number(args.limit) || 20, 100);
|
|
835
|
+
const cursor = String(args.cursor ?? "") || void 0;
|
|
836
|
+
const result = await router.listTools({
|
|
837
|
+
serverId,
|
|
838
|
+
serverName: serverName ?? (!serverId && query ? query : void 0),
|
|
839
|
+
limit: limit2,
|
|
840
|
+
cursor
|
|
841
|
+
});
|
|
842
|
+
const serverText = result.servers.length > 0 ? result.servers.map((server) => `${server.serverName} (serverId: ${server.serverId}, tools: ${server.toolCount})`).join(", ") : "none";
|
|
843
|
+
const lines = [
|
|
844
|
+
"operation: list",
|
|
845
|
+
`servers: ${serverText}`,
|
|
846
|
+
`totalCount: ${result.totalCount}`,
|
|
847
|
+
`returnedCount: ${result.returnedCount}`,
|
|
848
|
+
`nextCursor: ${result.nextCursor ?? "null"}`,
|
|
849
|
+
""
|
|
850
|
+
];
|
|
851
|
+
if (result.tools.length > 0) {
|
|
852
|
+
lines.push(...formatToolSummaries(result.tools));
|
|
853
|
+
} else {
|
|
854
|
+
lines.push(
|
|
855
|
+
serverId || serverName ? "No tools found for the requested server scope." : 'No tools found. Try operation "search" or provide serverId/serverName.'
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
return {
|
|
859
|
+
content: [{ type: "text", text: lines.join("\n") }],
|
|
860
|
+
isError: false
|
|
861
|
+
};
|
|
862
|
+
}
|
|
734
863
|
const limit = Math.min(Number(args.limit) || 5, 20);
|
|
864
|
+
const searchOptions = { serverId, serverName };
|
|
735
865
|
const selectMatch = query.match(/^select:(.+)$/i);
|
|
736
866
|
if (selectMatch) {
|
|
867
|
+
await router.listTools({ serverId, serverName, limit: 1 });
|
|
737
868
|
const requested = selectMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
|
|
738
869
|
const found = [];
|
|
739
870
|
const errors = [];
|
|
871
|
+
const namespace = serverId ?? serverName;
|
|
740
872
|
for (const requestedToolName of requested) {
|
|
741
|
-
const { tool, error } = resolveToolSchema(requestedToolName
|
|
873
|
+
const { tool, error } = resolveToolSchema(requestedToolName, namespace, {
|
|
874
|
+
allowServerNameFragment: Boolean(serverName && !serverId)
|
|
875
|
+
});
|
|
742
876
|
if (error) {
|
|
743
877
|
const errorMsg = error.content[0]?.type === "text" ? error.content[0].text : "Unknown error";
|
|
744
878
|
errors.push(`- **${requestedToolName}**: ${errorMsg}`);
|
|
745
879
|
} else if (tool) {
|
|
746
880
|
found.push(tool);
|
|
747
881
|
} else {
|
|
748
|
-
errors.push(`- **${requestedToolName}**: Tool not found. Try searching with
|
|
882
|
+
errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tools.`);
|
|
749
883
|
}
|
|
750
884
|
}
|
|
751
885
|
const lines = [];
|
|
@@ -766,11 +900,21 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
766
900
|
isError: found.length === 0
|
|
767
901
|
};
|
|
768
902
|
}
|
|
769
|
-
const results = await router.searchTools(query, limit);
|
|
770
|
-
const text = results.length === 0 ? "No tools found matching your query.
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
903
|
+
const results = await router.searchTools(query, limit, searchOptions);
|
|
904
|
+
const text = results.length === 0 ? "No tools found matching your query. Call mcp_list_servers to inspect connected servers, then retry mcp_search_tools with serverId or serverName." : formatToolSummaries(results).join("\n");
|
|
905
|
+
return {
|
|
906
|
+
content: [{ type: "text", text }],
|
|
907
|
+
isError: false
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
case "mcp_list_servers": {
|
|
911
|
+
const query = String(args.query ?? "").trim();
|
|
912
|
+
const servers = await router.listServers({
|
|
913
|
+
serverName: query || void 0
|
|
914
|
+
});
|
|
915
|
+
const text = servers.length === 0 ? "No connected servers found." : servers.map(
|
|
916
|
+
(server, i) => `${i + 1}. **${server.serverName}** (serverId: ${server.serverId}, sessionId: ${server.sessionId})
|
|
917
|
+
Tool count: ${server.toolCount}`
|
|
774
918
|
).join("\n");
|
|
775
919
|
return {
|
|
776
920
|
content: [{ type: "text", text }],
|
|
@@ -781,11 +925,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
781
925
|
const pattern = String(args.query ?? "");
|
|
782
926
|
const limit = Math.min(Number(args.limit) || 5, 20);
|
|
783
927
|
const results = await router.searchToolsRegex(pattern, limit);
|
|
784
|
-
const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : results.
|
|
785
|
-
(t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
|
|
786
|
-
${t.description}
|
|
787
|
-
Estimated tokens: ${t.estimatedTokens}`
|
|
788
|
-
).join("\n");
|
|
928
|
+
const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : formatToolSummaries(results).join("\n");
|
|
789
929
|
return {
|
|
790
930
|
content: [{ type: "text", text }],
|
|
791
931
|
isError: false
|
|
@@ -803,7 +943,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
803
943
|
content: [
|
|
804
944
|
{
|
|
805
945
|
type: "text",
|
|
806
|
-
text: `Tool "${name}" not found. Use
|
|
946
|
+
text: `Tool "${name}" not found. Use mcp_search_tools to find available tools first.`
|
|
807
947
|
}
|
|
808
948
|
],
|
|
809
949
|
isError: true
|
|
@@ -812,7 +952,13 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
812
952
|
const schema = {
|
|
813
953
|
name: tool.name,
|
|
814
954
|
description: tool.description,
|
|
815
|
-
inputSchema: tool.inputSchema
|
|
955
|
+
inputSchema: tool.inputSchema,
|
|
956
|
+
executionInstructions: {
|
|
957
|
+
nextTool: "mcp_execute_tool",
|
|
958
|
+
toolName: tool.name,
|
|
959
|
+
serverId: tool.serverId,
|
|
960
|
+
note: "Do not call this discovered tool directly unless it was explicitly registered as a runtime tool. Execute it via mcp_execute_tool and pass these parameters inside args."
|
|
961
|
+
}
|
|
816
962
|
};
|
|
817
963
|
return {
|
|
818
964
|
content: [{ type: "text", text: JSON.stringify(schema, null, 2) }],
|
|
@@ -838,7 +984,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
838
984
|
content: [
|
|
839
985
|
{
|
|
840
986
|
type: "text",
|
|
841
|
-
text: `Tool "${targetToolName}" not found. Use
|
|
987
|
+
text: `Tool "${targetToolName}" not found. Use mcp_search_tools to discover available tools first.`
|
|
842
988
|
}
|
|
843
989
|
],
|
|
844
990
|
isError: true
|
|
@@ -872,8 +1018,15 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
|
|
|
872
1018
|
return null;
|
|
873
1019
|
}
|
|
874
1020
|
}
|
|
1021
|
+
function formatToolSummaries(tools) {
|
|
1022
|
+
return tools.map(
|
|
1023
|
+
(t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
|
|
1024
|
+
${t.description}
|
|
1025
|
+
Estimated tokens: ${t.estimatedTokens}`
|
|
1026
|
+
);
|
|
1027
|
+
}
|
|
875
1028
|
function isMetaTool(toolName) {
|
|
876
|
-
return toolName === "
|
|
1029
|
+
return toolName === "mcp_search_tools" || toolName === "mcp_list_servers" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
|
|
877
1030
|
}
|
|
878
1031
|
function resolveMetaToolProxy(toolName, args) {
|
|
879
1032
|
if (toolName === "mcp_execute_tool") {
|
|
@@ -921,7 +1074,7 @@ var ToolRouter = class {
|
|
|
921
1074
|
* This is the main method adapters should call.
|
|
922
1075
|
*
|
|
923
1076
|
* - `all` → returns all tools (unchanged behavior)
|
|
924
|
-
* - `search` → returns only meta-tools (
|
|
1077
|
+
* - `search` → returns only meta-tools (mcp_search_tools, mcp_get_tool_schema, mcp_execute_tool)
|
|
925
1078
|
* - `groups` → returns tools from active groups only
|
|
926
1079
|
*/
|
|
927
1080
|
async getFilteredTools() {
|
|
@@ -950,9 +1103,10 @@ var ToolRouter = class {
|
|
|
950
1103
|
* Search tools by natural-language query.
|
|
951
1104
|
* Works regardless of strategy.
|
|
952
1105
|
*/
|
|
953
|
-
async searchTools(query, topK) {
|
|
1106
|
+
async searchTools(query, topK, options = {}) {
|
|
954
1107
|
await this.ensureInitialized();
|
|
955
|
-
|
|
1108
|
+
const limit = topK ?? this.maxTools;
|
|
1109
|
+
return this.index.search(query, limit, options);
|
|
956
1110
|
}
|
|
957
1111
|
/**
|
|
958
1112
|
* Search tools by regex pattern.
|
|
@@ -962,12 +1116,22 @@ var ToolRouter = class {
|
|
|
962
1116
|
await this.ensureInitialized();
|
|
963
1117
|
return this.index.searchRegex(pattern, topK ?? this.maxTools);
|
|
964
1118
|
}
|
|
1119
|
+
/** List connected MCP servers with indexed tool counts. */
|
|
1120
|
+
async listServers(options = {}) {
|
|
1121
|
+
await this.ensureInitialized();
|
|
1122
|
+
return this.index.listServers(options);
|
|
1123
|
+
}
|
|
1124
|
+
/** List tools deterministically, optionally scoped to a server. */
|
|
1125
|
+
async listTools(options = {}) {
|
|
1126
|
+
await this.ensureInitialized();
|
|
1127
|
+
return this.index.listTools(options);
|
|
1128
|
+
}
|
|
965
1129
|
/**
|
|
966
1130
|
* Get the full tool definition by name.
|
|
967
1131
|
* If tool name is ambiguous, use namespace to specify the server.
|
|
968
1132
|
*/
|
|
969
|
-
getToolSchema(toolName, namespace) {
|
|
970
|
-
const matches = this.index.getTool(toolName, namespace);
|
|
1133
|
+
getToolSchema(toolName, namespace, options = {}) {
|
|
1134
|
+
const matches = this.index.getTool(toolName, namespace, options);
|
|
971
1135
|
if (matches.length === 0) return void 0;
|
|
972
1136
|
if (matches.length > 1) {
|
|
973
1137
|
const servers = matches.map((m) => m.serverId).join(", ");
|
|
@@ -1046,7 +1210,7 @@ var ToolRouter = class {
|
|
|
1046
1210
|
const indexedTool = this.getToolSchema(toolName, namespace);
|
|
1047
1211
|
if (!indexedTool) {
|
|
1048
1212
|
throw new Error(
|
|
1049
|
-
`Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use
|
|
1213
|
+
`Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use mcp_search_tools or mcp_search_tool_regex to discover available tools.`
|
|
1050
1214
|
);
|
|
1051
1215
|
}
|
|
1052
1216
|
const clients = this.getClients();
|
|
@@ -1158,6 +1322,7 @@ var ToolRouter = class {
|
|
|
1158
1322
|
getMetaToolDefinitions() {
|
|
1159
1323
|
return [
|
|
1160
1324
|
createSearchToolDefinition(),
|
|
1325
|
+
createListServersToolDefinition(),
|
|
1161
1326
|
createRegexSearchToolDefinition(),
|
|
1162
1327
|
createGetSchemaToolDefinition(),
|
|
1163
1328
|
createExecuteToolDefinition()
|
|
@@ -1196,6 +1361,7 @@ exports.ToolRouter = ToolRouter;
|
|
|
1196
1361
|
exports.UnauthorizedError = UnauthorizedError;
|
|
1197
1362
|
exports.createExecuteToolDefinition = createExecuteToolDefinition;
|
|
1198
1363
|
exports.createGetSchemaToolDefinition = createGetSchemaToolDefinition;
|
|
1364
|
+
exports.createListServersToolDefinition = createListServersToolDefinition;
|
|
1199
1365
|
exports.createRegexSearchToolDefinition = createRegexSearchToolDefinition;
|
|
1200
1366
|
exports.createSearchToolDefinition = createSearchToolDefinition;
|
|
1201
1367
|
exports.executeMetaTool = executeMetaTool;
|