@mcp-ts/sdk 1.5.3 → 1.6.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.
Files changed (60) hide show
  1. package/dist/adapters/agui-adapter.d.mts +2 -2
  2. package/dist/adapters/agui-adapter.d.ts +2 -2
  3. package/dist/adapters/agui-adapter.js +69 -18
  4. package/dist/adapters/agui-adapter.js.map +1 -1
  5. package/dist/adapters/agui-adapter.mjs +69 -18
  6. package/dist/adapters/agui-adapter.mjs.map +1 -1
  7. package/dist/adapters/agui-middleware.d.mts +2 -2
  8. package/dist/adapters/agui-middleware.d.ts +2 -2
  9. package/dist/adapters/ai-adapter.d.mts +2 -2
  10. package/dist/adapters/ai-adapter.d.ts +2 -2
  11. package/dist/adapters/ai-adapter.js +69 -18
  12. package/dist/adapters/ai-adapter.js.map +1 -1
  13. package/dist/adapters/ai-adapter.mjs +69 -18
  14. package/dist/adapters/ai-adapter.mjs.map +1 -1
  15. package/dist/adapters/langchain-adapter.d.mts +2 -2
  16. package/dist/adapters/langchain-adapter.d.ts +2 -2
  17. package/dist/adapters/langchain-adapter.js +69 -18
  18. package/dist/adapters/langchain-adapter.js.map +1 -1
  19. package/dist/adapters/langchain-adapter.mjs +69 -18
  20. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  21. package/dist/client/index.d.mts +2 -2
  22. package/dist/client/index.d.ts +2 -2
  23. package/dist/client/react.d.mts +4 -4
  24. package/dist/client/react.d.ts +4 -4
  25. package/dist/client/react.js.map +1 -1
  26. package/dist/client/react.mjs.map +1 -1
  27. package/dist/client/vue.d.mts +4 -4
  28. package/dist/client/vue.d.ts +4 -4
  29. package/dist/{index-GfC_eNEv.d.ts → index-DhA-OEAe.d.ts} +1 -1
  30. package/dist/{index-DcYfpY3H.d.mts → index-bFL4ZF2N.d.mts} +1 -1
  31. package/dist/index.d.mts +4 -4
  32. package/dist/index.d.ts +4 -4
  33. package/dist/index.js +212 -44
  34. package/dist/index.js.map +1 -1
  35. package/dist/index.mjs +212 -45
  36. package/dist/index.mjs.map +1 -1
  37. package/dist/server/index.d.mts +2 -2
  38. package/dist/server/index.d.ts +2 -2
  39. package/dist/server/index.js +13 -5
  40. package/dist/server/index.js.map +1 -1
  41. package/dist/server/index.mjs +13 -5
  42. package/dist/server/index.mjs.map +1 -1
  43. package/dist/shared/index.d.mts +17 -10
  44. package/dist/shared/index.d.ts +17 -10
  45. package/dist/shared/index.js +199 -39
  46. package/dist/shared/index.js.map +1 -1
  47. package/dist/shared/index.mjs +199 -40
  48. package/dist/shared/index.mjs.map +1 -1
  49. package/dist/{tool-router-DsKhRmJm.d.ts → tool-router-BVaV1udm.d.mts} +57 -8
  50. package/dist/{tool-router-DK0RJblO.d.mts → tool-router-Dh2804tM.d.ts} +57 -8
  51. package/dist/{types-CfCoIsWI.d.mts → types-rIuN1CQi.d.mts} +1 -0
  52. package/dist/{types-CfCoIsWI.d.ts → types-rIuN1CQi.d.ts} +1 -0
  53. package/package.json +3 -1
  54. package/src/server/handlers/sse-handler.ts +12 -0
  55. package/src/server/mcp/oauth-client.ts +10 -6
  56. package/src/shared/index.ts +4 -0
  57. package/src/shared/meta-tools.ts +163 -37
  58. package/src/shared/tool-index.ts +123 -7
  59. package/src/shared/tool-router.ts +40 -7
  60. package/src/shared/types.ts +1 -0
@@ -1,9 +1,9 @@
1
1
  export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, M as McpConnectionEvent, c as McpConnectionState, d as McpObservabilityEvent } from '../events-CK3N--3g.mjs';
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
- import { v as ToolInfo } from '../types-CfCoIsWI.mjs';
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 { d as ToolRouter } from '../tool-router-DK0RJblO.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, e as ToolRouterClientInput, f as ToolRouterOptions, g as ToolRouterStrategy, h as ToolSummary } from '../tool-router-DK0RJblO.mjs';
3
+ import { v as ToolInfo } from '../types-rIuN1CQi.mjs';
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-rIuN1CQi.mjs';
5
+ import { e as ToolRouter } from '../tool-router-BVaV1udm.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-BVaV1udm.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
- * • `mcp_search_tool_bm25` BM25 natural language search
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 `mcp_search_tool_bm25` tool definition.
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 `mcp_search_tool_bm25` or
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 `mcp_search_tool_bm25` or `mcp_search_tool_regex`.
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 (mcp_search_tool_bm25, mcp_search_tool_regex, etc.)
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 };
@@ -1,9 +1,9 @@
1
1
  export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, M as McpConnectionEvent, c as McpConnectionState, d as McpObservabilityEvent } from '../events-CK3N--3g.js';
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
- import { v as ToolInfo } from '../types-CfCoIsWI.js';
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 { d as ToolRouter } from '../tool-router-DsKhRmJm.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, e as ToolRouterClientInput, f as ToolRouterOptions, g as ToolRouterStrategy, h as ToolSummary } from '../tool-router-DsKhRmJm.js';
3
+ import { v as ToolInfo } from '../types-rIuN1CQi.js';
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-rIuN1CQi.js';
5
+ import { e as ToolRouter } from '../tool-router-Dh2804tM.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-Dh2804tM.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
- * • `mcp_search_tool_bm25` BM25 natural language search
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 `mcp_search_tool_bm25` tool definition.
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 `mcp_search_tool_bm25` or
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 `mcp_search_tool_bm25` or `mcp_search_tool_regex`.
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 (mcp_search_tool_bm25, mcp_search_tool_regex, etc.)
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 };
@@ -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, it tries to match sessionId or serverName.
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
- return list.filter((t) => t.sessionId === namespace || t.serverId === namespace);
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: "mcp_search_tool_bm25",
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 mcp_search_tool_bm25 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.",
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 mcp_search_tool_bm25."
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 mcp_search_tool_bm25. Required if multiple tools have the same name."
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 mcp_search_tool_bm25. You MUST call mcp_get_tool_schema first to know the correct parameters. Pass the exact tool name and its arguments.",
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 mcp_search_tool_bm25 results."
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 mcp_search_tool_bm25. Required if multiple tools have the same name."
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 "mcp_search_tool_bm25": {
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 mcp_search_tool_bm25.`);
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. Try different keywords." : results.map(
771
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
772
- ${t.description}
773
- Estimated tokens: ${t.estimatedTokens}`
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.map(
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 mcp_search_tool_bm25 to find available tools first.`
946
+ text: `Tool "${name}" not found. Use mcp_search_tools to find available tools first.`
807
947
  }
808
948
  ],
809
949
  isError: true
@@ -844,7 +984,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
844
984
  content: [
845
985
  {
846
986
  type: "text",
847
- text: `Tool "${targetToolName}" not found. Use mcp_search_tool_bm25 to discover available tools first.`
987
+ text: `Tool "${targetToolName}" not found. Use mcp_search_tools to discover available tools first.`
848
988
  }
849
989
  ],
850
990
  isError: true
@@ -878,8 +1018,15 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
878
1018
  return null;
879
1019
  }
880
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
+ }
881
1028
  function isMetaTool(toolName) {
882
- return toolName === "mcp_search_tool_bm25" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
1029
+ return toolName === "mcp_search_tools" || toolName === "mcp_list_servers" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
883
1030
  }
884
1031
  function resolveMetaToolProxy(toolName, args) {
885
1032
  if (toolName === "mcp_execute_tool") {
@@ -927,7 +1074,7 @@ var ToolRouter = class {
927
1074
  * This is the main method adapters should call.
928
1075
  *
929
1076
  * - `all` → returns all tools (unchanged behavior)
930
- * - `search` → returns only meta-tools (mcp_search_tool_bm25, mcp_get_tool_schema, mcp_execute_tool)
1077
+ * - `search` → returns only meta-tools (mcp_search_tools, mcp_get_tool_schema, mcp_execute_tool)
931
1078
  * - `groups` → returns tools from active groups only
932
1079
  */
933
1080
  async getFilteredTools() {
@@ -956,9 +1103,10 @@ var ToolRouter = class {
956
1103
  * Search tools by natural-language query.
957
1104
  * Works regardless of strategy.
958
1105
  */
959
- async searchTools(query, topK) {
1106
+ async searchTools(query, topK, options = {}) {
960
1107
  await this.ensureInitialized();
961
- return this.index.search(query, topK ?? this.maxTools);
1108
+ const limit = topK ?? this.maxTools;
1109
+ return this.index.search(query, limit, options);
962
1110
  }
963
1111
  /**
964
1112
  * Search tools by regex pattern.
@@ -968,12 +1116,22 @@ var ToolRouter = class {
968
1116
  await this.ensureInitialized();
969
1117
  return this.index.searchRegex(pattern, topK ?? this.maxTools);
970
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
+ }
971
1129
  /**
972
1130
  * Get the full tool definition by name.
973
1131
  * If tool name is ambiguous, use namespace to specify the server.
974
1132
  */
975
- getToolSchema(toolName, namespace) {
976
- const matches = this.index.getTool(toolName, namespace);
1133
+ getToolSchema(toolName, namespace, options = {}) {
1134
+ const matches = this.index.getTool(toolName, namespace, options);
977
1135
  if (matches.length === 0) return void 0;
978
1136
  if (matches.length > 1) {
979
1137
  const servers = matches.map((m) => m.serverId).join(", ");
@@ -1052,7 +1210,7 @@ var ToolRouter = class {
1052
1210
  const indexedTool = this.getToolSchema(toolName, namespace);
1053
1211
  if (!indexedTool) {
1054
1212
  throw new Error(
1055
- `Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use mcp_search_tool_bm25 or mcp_search_tool_regex to discover available tools.`
1213
+ `Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use mcp_search_tools or mcp_search_tool_regex to discover available tools.`
1056
1214
  );
1057
1215
  }
1058
1216
  const clients = this.getClients();
@@ -1164,6 +1322,7 @@ var ToolRouter = class {
1164
1322
  getMetaToolDefinitions() {
1165
1323
  return [
1166
1324
  createSearchToolDefinition(),
1325
+ createListServersToolDefinition(),
1167
1326
  createRegexSearchToolDefinition(),
1168
1327
  createGetSchemaToolDefinition(),
1169
1328
  createExecuteToolDefinition()
@@ -1202,6 +1361,7 @@ exports.ToolRouter = ToolRouter;
1202
1361
  exports.UnauthorizedError = UnauthorizedError;
1203
1362
  exports.createExecuteToolDefinition = createExecuteToolDefinition;
1204
1363
  exports.createGetSchemaToolDefinition = createGetSchemaToolDefinition;
1364
+ exports.createListServersToolDefinition = createListServersToolDefinition;
1205
1365
  exports.createRegexSearchToolDefinition = createRegexSearchToolDefinition;
1206
1366
  exports.createSearchToolDefinition = createSearchToolDefinition;
1207
1367
  exports.executeMetaTool = executeMetaTool;