@mcp-ts/sdk 1.5.3 → 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.
Files changed (46) hide show
  1. package/dist/adapters/agui-adapter.d.mts +1 -1
  2. package/dist/adapters/agui-adapter.d.ts +1 -1
  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 +1 -1
  8. package/dist/adapters/agui-middleware.d.ts +1 -1
  9. package/dist/adapters/ai-adapter.d.mts +1 -1
  10. package/dist/adapters/ai-adapter.d.ts +1 -1
  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 +1 -1
  16. package/dist/adapters/langchain-adapter.d.ts +1 -1
  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/react.js.map +1 -1
  22. package/dist/client/react.mjs.map +1 -1
  23. package/dist/index.d.mts +2 -2
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.js +200 -42
  26. package/dist/index.js.map +1 -1
  27. package/dist/index.mjs +200 -43
  28. package/dist/index.mjs.map +1 -1
  29. package/dist/server/index.js +1 -3
  30. package/dist/server/index.js.map +1 -1
  31. package/dist/server/index.mjs +1 -3
  32. package/dist/server/index.mjs.map +1 -1
  33. package/dist/shared/index.d.mts +15 -8
  34. package/dist/shared/index.d.ts +15 -8
  35. package/dist/shared/index.js +199 -39
  36. package/dist/shared/index.js.map +1 -1
  37. package/dist/shared/index.mjs +199 -40
  38. package/dist/shared/index.mjs.map +1 -1
  39. package/dist/{tool-router-DsKhRmJm.d.ts → tool-router-Bn9R0KWr.d.ts} +56 -7
  40. package/dist/{tool-router-DK0RJblO.d.mts → tool-router-_O2tIwf7.d.mts} +56 -7
  41. package/package.json +3 -1
  42. package/src/server/mcp/oauth-client.ts +4 -4
  43. package/src/shared/index.ts +4 -0
  44. package/src/shared/meta-tools.ts +163 -37
  45. package/src/shared/tool-index.ts +123 -7
  46. package/src/shared/tool-router.ts +40 -7
package/dist/index.mjs CHANGED
@@ -2201,9 +2201,7 @@ var MCPClient = class _MCPClient {
2201
2201
  * @returns Server name or undefined
2202
2202
  */
2203
2203
  getServerName() {
2204
- const info = this.client?.getServerVersion();
2205
- console.log("server info ->", info);
2206
- return info?.title ?? info?.name ?? this.serverName;
2204
+ return this.serverName;
2207
2205
  }
2208
2206
  /**
2209
2207
  * Gets the server ID
@@ -3945,17 +3943,17 @@ var ToolIndex = class _ToolIndex {
3945
3943
  *
3946
3944
  * `score = keywordWeight × keyword_score + (1 - keywordWeight) × cosine_score`
3947
3945
  */
3948
- async search(query, topK = 5) {
3946
+ async search(query, topK = 5, options = {}) {
3949
3947
  if (this.tools.size === 0) return [];
3950
3948
  const queryLower = query.toLowerCase().trim();
3951
3949
  const exactMatches = [...this.toolSummaries.values()].filter(
3952
- (summary) => summary.name.toLowerCase() === queryLower
3950
+ (summary) => summary.name.toLowerCase() === queryLower && this.matchesServer(summary, options)
3953
3951
  );
3954
3952
  if (exactMatches.length > 0) {
3955
3953
  return exactMatches.slice(0, topK);
3956
3954
  }
3957
3955
  if (queryLower.startsWith("mcp__") && queryLower.length > 5) {
3958
- const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower)).slice(0, topK);
3956
+ const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower) && this.matchesServer(t, options)).slice(0, topK);
3959
3957
  if (prefixMatches.length > 0) return prefixMatches;
3960
3958
  }
3961
3959
  const queryTermsRaw = queryLower.split(/\s+/).filter((t) => t.length > 0);
@@ -3973,9 +3971,10 @@ var ToolIndex = class _ToolIndex {
3973
3971
  const queryTokens = this.tokenize(allScoringTerms.join(" "));
3974
3972
  const candidateKeys = /* @__PURE__ */ new Set();
3975
3973
  for (const docKey of this.toolSummaries.keys()) {
3974
+ const summary = this.toolSummaries.get(docKey);
3975
+ if (!this.matchesServer(summary, options)) continue;
3976
3976
  if (requiredTerms.length > 0) {
3977
3977
  const text = this.searchTexts.get(docKey) || "";
3978
- const summary = this.toolSummaries.get(docKey);
3979
3978
  const nameLower = summary.name.toLowerCase();
3980
3979
  const matchesAll = requiredTerms.every(
3981
3980
  (term) => text.includes(term) || nameLower.includes(term)
@@ -4086,17 +4085,66 @@ var ToolIndex = class _ToolIndex {
4086
4085
  // -----------------------------------------------------------------------
4087
4086
  /**
4088
4087
  * Get tool definition(s) by name.
4089
- * If namespace is provided, it tries to match sessionId or serverName.
4088
+ * If namespace is provided, exact sessionId/serverId matches take precedence.
4089
+ * Falls back to serverName fragment matching only when explicitly allowed.
4090
4090
  */
4091
- getTool(name, namespace) {
4091
+ getTool(name, namespace, options = {}) {
4092
4092
  const list = this.tools.get(name) ?? [];
4093
4093
  if (!namespace) return list;
4094
- return list.filter((t) => t.sessionId === namespace || t.serverId === namespace);
4094
+ const exactMatches = list.filter(
4095
+ (t) => t.sessionId === namespace || t.serverId === namespace
4096
+ );
4097
+ if (exactMatches.length > 0) return exactMatches;
4098
+ if (!options.allowServerNameFragment) return [];
4099
+ const namespaceLower = namespace.toLowerCase();
4100
+ return list.filter((t) => t.serverName.toLowerCase().includes(namespaceLower));
4095
4101
  }
4096
4102
  /** All indexed tool names. */
4097
4103
  getToolNames() {
4098
4104
  return [...this.tools.keys()];
4099
4105
  }
4106
+ /** List indexed servers with tool counts. */
4107
+ listServers(options = {}) {
4108
+ const servers = /* @__PURE__ */ new Map();
4109
+ for (const summary of this.toolSummaries.values()) {
4110
+ if (!this.matchesServer(summary, options)) continue;
4111
+ const key = `${summary.sessionId}::${summary.serverId}`;
4112
+ const existing = servers.get(key);
4113
+ if (existing) {
4114
+ existing.toolCount += 1;
4115
+ } else {
4116
+ servers.set(key, {
4117
+ serverName: summary.serverName,
4118
+ serverId: summary.serverId,
4119
+ sessionId: summary.sessionId,
4120
+ toolCount: 1
4121
+ });
4122
+ }
4123
+ }
4124
+ return [...servers.values()].sort((a, b) => {
4125
+ const byName = a.serverName.localeCompare(b.serverName);
4126
+ return byName !== 0 ? byName : a.serverId.localeCompare(b.serverId);
4127
+ });
4128
+ }
4129
+ /** List tools deterministically, optionally scoped to a server. */
4130
+ listTools(options = {}) {
4131
+ const offset = Math.max(Number(options.cursor) || 0, 0);
4132
+ const limit = Math.max(Number(options.limit) || 20, 1);
4133
+ const tools = [...this.toolSummaries.values()].filter((summary) => this.matchesServer(summary, options)).sort((a, b) => {
4134
+ const byServer = a.serverName.localeCompare(b.serverName);
4135
+ if (byServer !== 0) return byServer;
4136
+ return a.name.localeCompare(b.name);
4137
+ });
4138
+ const page = tools.slice(offset, offset + limit);
4139
+ const nextOffset = offset + page.length;
4140
+ return {
4141
+ tools: page,
4142
+ totalCount: tools.length,
4143
+ returnedCount: page.length,
4144
+ nextCursor: nextOffset < tools.length ? String(nextOffset) : void 0,
4145
+ servers: this.listServers(options)
4146
+ };
4147
+ }
4100
4148
  /** Number of indexed tools (including duplicates). */
4101
4149
  get size() {
4102
4150
  let count = 0;
@@ -4153,6 +4201,20 @@ var ToolIndex = class _ToolIndex {
4153
4201
  getDocumentKey(tool) {
4154
4202
  return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
4155
4203
  }
4204
+ matchesServer(summary, options) {
4205
+ if (options.serverId && summary.serverId !== options.serverId) {
4206
+ return false;
4207
+ }
4208
+ if (options.serverName) {
4209
+ const serverNameQuery = options.serverName.toLowerCase();
4210
+ const serverName = summary.serverName.toLowerCase();
4211
+ const serverId = summary.serverId.toLowerCase();
4212
+ if (!serverName.includes(serverNameQuery) && !serverId.includes(serverNameQuery)) {
4213
+ return false;
4214
+ }
4215
+ }
4216
+ return true;
4217
+ }
4156
4218
  /** Simple whitespace + camelCase + snake_case tokenizer. */
4157
4219
  tokenize(text) {
4158
4220
  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);
@@ -4236,7 +4298,7 @@ var SchemaCompressor = class _SchemaCompressor {
4236
4298
  // src/shared/meta-tools.ts
4237
4299
  function createSearchToolDefinition() {
4238
4300
  return {
4239
- name: "mcp_search_tool_bm25",
4301
+ name: "mcp_search_tools",
4240
4302
  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',
4241
4303
  inputSchema: {
4242
4304
  type: "object",
@@ -4245,15 +4307,47 @@ function createSearchToolDefinition() {
4245
4307
  type: "string",
4246
4308
  description: 'Query to find tools. Use "select:<tool_name>" for direct selection, or keywords to search. Prefix keywords with + to require them.'
4247
4309
  },
4310
+ operation: {
4311
+ type: "string",
4312
+ enum: ["search", "list"],
4313
+ 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.'
4314
+ },
4315
+ serverId: {
4316
+ type: "string",
4317
+ description: "Optional server ID to restrict search/list results to one MCP server."
4318
+ },
4319
+ serverName: {
4320
+ type: "string",
4321
+ description: 'Optional server name fragment to restrict search/list results to matching MCP servers, e.g. "supabase".'
4322
+ },
4248
4323
  limit: {
4249
4324
  type: "number",
4250
- description: "Maximum number of results to return (default: 5, max: 20)."
4325
+ description: "Maximum number of results to return (default: 5 for search, 20 for list; max: 20 for search, 100 for list)."
4326
+ },
4327
+ cursor: {
4328
+ type: "string",
4329
+ description: 'Optional pagination cursor returned by operation "list".'
4251
4330
  }
4252
4331
  },
4253
4332
  required: ["query"]
4254
4333
  }
4255
4334
  };
4256
4335
  }
4336
+ function createListServersToolDefinition() {
4337
+ return {
4338
+ name: "mcp_list_servers",
4339
+ 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.",
4340
+ inputSchema: {
4341
+ type: "object",
4342
+ properties: {
4343
+ query: {
4344
+ type: "string",
4345
+ description: 'Optional server filter text. Matches server name or serverId, e.g. "web" or "supabase".'
4346
+ }
4347
+ }
4348
+ }
4349
+ };
4350
+ }
4257
4351
  function createRegexSearchToolDefinition() {
4258
4352
  return {
4259
4353
  name: "mcp_search_tool_regex",
@@ -4277,17 +4371,17 @@ function createRegexSearchToolDefinition() {
4277
4371
  function createGetSchemaToolDefinition() {
4278
4372
  return {
4279
4373
  name: "mcp_get_tool_schema",
4280
- 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.",
4374
+ 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.",
4281
4375
  inputSchema: {
4282
4376
  type: "object",
4283
4377
  properties: {
4284
4378
  toolName: {
4285
4379
  type: "string",
4286
- description: "The exact tool name returned by mcp_search_tool_bm25."
4380
+ description: "The exact tool name returned by mcp_search_tools."
4287
4381
  },
4288
4382
  serverId: {
4289
4383
  type: "string",
4290
- description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4384
+ description: "Optional: The server ID provided in mcp_search_tools. Required if multiple tools have the same name."
4291
4385
  }
4292
4386
  },
4293
4387
  required: ["toolName"]
@@ -4297,17 +4391,17 @@ function createGetSchemaToolDefinition() {
4297
4391
  function createExecuteToolDefinition() {
4298
4392
  return {
4299
4393
  name: "mcp_execute_tool",
4300
- 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.",
4394
+ 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.",
4301
4395
  inputSchema: {
4302
4396
  type: "object",
4303
4397
  properties: {
4304
4398
  toolName: {
4305
4399
  type: "string",
4306
- description: "The exact tool name from mcp_search_tool_bm25 results."
4400
+ description: "The exact tool name from mcp_search_tools results."
4307
4401
  },
4308
4402
  serverId: {
4309
4403
  type: "string",
4310
- description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4404
+ description: "Optional: The server ID provided in mcp_search_tools. Required if multiple tools have the same name."
4311
4405
  },
4312
4406
  args: {
4313
4407
  type: "object",
@@ -4320,9 +4414,9 @@ function createExecuteToolDefinition() {
4320
4414
  };
4321
4415
  }
4322
4416
  async function executeMetaTool(toolName, args, router, callToolFn) {
4323
- const resolveToolSchema = (name, namespace) => {
4417
+ const resolveToolSchema = (name, namespace, options) => {
4324
4418
  try {
4325
- return { tool: router.getToolSchema(name, namespace) };
4419
+ return { tool: router.getToolSchema(name, namespace, options) };
4326
4420
  } catch (err) {
4327
4421
  const errorMessage = err instanceof Error ? err.message : String(err);
4328
4422
  return {
@@ -4334,23 +4428,61 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4334
4428
  }
4335
4429
  };
4336
4430
  switch (toolName) {
4337
- case "mcp_search_tool_bm25": {
4431
+ case "mcp_search_tools": {
4338
4432
  const query = String(args.query ?? "");
4433
+ const operation = String(args.operation ?? "search");
4434
+ const serverId = String(args.serverId ?? "") || void 0;
4435
+ const serverName = String(args.serverName ?? "") || void 0;
4436
+ if (operation === "list") {
4437
+ const limit2 = Math.min(Number(args.limit) || 20, 100);
4438
+ const cursor = String(args.cursor ?? "") || void 0;
4439
+ const result = await router.listTools({
4440
+ serverId,
4441
+ serverName: serverName ?? (!serverId && query ? query : void 0),
4442
+ limit: limit2,
4443
+ cursor
4444
+ });
4445
+ const serverText = result.servers.length > 0 ? result.servers.map((server) => `${server.serverName} (serverId: ${server.serverId}, tools: ${server.toolCount})`).join(", ") : "none";
4446
+ const lines = [
4447
+ "operation: list",
4448
+ `servers: ${serverText}`,
4449
+ `totalCount: ${result.totalCount}`,
4450
+ `returnedCount: ${result.returnedCount}`,
4451
+ `nextCursor: ${result.nextCursor ?? "null"}`,
4452
+ ""
4453
+ ];
4454
+ if (result.tools.length > 0) {
4455
+ lines.push(...formatToolSummaries(result.tools));
4456
+ } else {
4457
+ lines.push(
4458
+ serverId || serverName ? "No tools found for the requested server scope." : 'No tools found. Try operation "search" or provide serverId/serverName.'
4459
+ );
4460
+ }
4461
+ return {
4462
+ content: [{ type: "text", text: lines.join("\n") }],
4463
+ isError: false
4464
+ };
4465
+ }
4339
4466
  const limit = Math.min(Number(args.limit) || 5, 20);
4467
+ const searchOptions = { serverId, serverName };
4340
4468
  const selectMatch = query.match(/^select:(.+)$/i);
4341
4469
  if (selectMatch) {
4470
+ await router.listTools({ serverId, serverName, limit: 1 });
4342
4471
  const requested = selectMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
4343
4472
  const found = [];
4344
4473
  const errors = [];
4474
+ const namespace = serverId ?? serverName;
4345
4475
  for (const requestedToolName of requested) {
4346
- const { tool, error } = resolveToolSchema(requestedToolName);
4476
+ const { tool, error } = resolveToolSchema(requestedToolName, namespace, {
4477
+ allowServerNameFragment: Boolean(serverName && !serverId)
4478
+ });
4347
4479
  if (error) {
4348
4480
  const errorMsg = error.content[0]?.type === "text" ? error.content[0].text : "Unknown error";
4349
4481
  errors.push(`- **${requestedToolName}**: ${errorMsg}`);
4350
4482
  } else if (tool) {
4351
4483
  found.push(tool);
4352
4484
  } else {
4353
- errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tool_bm25.`);
4485
+ errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tools.`);
4354
4486
  }
4355
4487
  }
4356
4488
  const lines = [];
@@ -4371,11 +4503,21 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4371
4503
  isError: found.length === 0
4372
4504
  };
4373
4505
  }
4374
- const results = await router.searchTools(query, limit);
4375
- const text = results.length === 0 ? "No tools found matching your query. Try different keywords." : results.map(
4376
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4377
- ${t.description}
4378
- Estimated tokens: ${t.estimatedTokens}`
4506
+ const results = await router.searchTools(query, limit, searchOptions);
4507
+ 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");
4508
+ return {
4509
+ content: [{ type: "text", text }],
4510
+ isError: false
4511
+ };
4512
+ }
4513
+ case "mcp_list_servers": {
4514
+ const query = String(args.query ?? "").trim();
4515
+ const servers = await router.listServers({
4516
+ serverName: query || void 0
4517
+ });
4518
+ const text = servers.length === 0 ? "No connected servers found." : servers.map(
4519
+ (server, i) => `${i + 1}. **${server.serverName}** (serverId: ${server.serverId}, sessionId: ${server.sessionId})
4520
+ Tool count: ${server.toolCount}`
4379
4521
  ).join("\n");
4380
4522
  return {
4381
4523
  content: [{ type: "text", text }],
@@ -4386,11 +4528,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4386
4528
  const pattern = String(args.query ?? "");
4387
4529
  const limit = Math.min(Number(args.limit) || 5, 20);
4388
4530
  const results = await router.searchToolsRegex(pattern, limit);
4389
- const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : results.map(
4390
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4391
- ${t.description}
4392
- Estimated tokens: ${t.estimatedTokens}`
4393
- ).join("\n");
4531
+ const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : formatToolSummaries(results).join("\n");
4394
4532
  return {
4395
4533
  content: [{ type: "text", text }],
4396
4534
  isError: false
@@ -4408,7 +4546,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4408
4546
  content: [
4409
4547
  {
4410
4548
  type: "text",
4411
- text: `Tool "${name}" not found. Use mcp_search_tool_bm25 to find available tools first.`
4549
+ text: `Tool "${name}" not found. Use mcp_search_tools to find available tools first.`
4412
4550
  }
4413
4551
  ],
4414
4552
  isError: true
@@ -4449,7 +4587,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4449
4587
  content: [
4450
4588
  {
4451
4589
  type: "text",
4452
- text: `Tool "${targetToolName}" not found. Use mcp_search_tool_bm25 to discover available tools first.`
4590
+ text: `Tool "${targetToolName}" not found. Use mcp_search_tools to discover available tools first.`
4453
4591
  }
4454
4592
  ],
4455
4593
  isError: true
@@ -4483,8 +4621,15 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4483
4621
  return null;
4484
4622
  }
4485
4623
  }
4624
+ function formatToolSummaries(tools) {
4625
+ return tools.map(
4626
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4627
+ ${t.description}
4628
+ Estimated tokens: ${t.estimatedTokens}`
4629
+ );
4630
+ }
4486
4631
  function isMetaTool(toolName) {
4487
- return toolName === "mcp_search_tool_bm25" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
4632
+ return toolName === "mcp_search_tools" || toolName === "mcp_list_servers" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
4488
4633
  }
4489
4634
  function resolveMetaToolProxy(toolName, args) {
4490
4635
  if (toolName === "mcp_execute_tool") {
@@ -4532,7 +4677,7 @@ var ToolRouter = class {
4532
4677
  * This is the main method adapters should call.
4533
4678
  *
4534
4679
  * - `all` → returns all tools (unchanged behavior)
4535
- * - `search` → returns only meta-tools (mcp_search_tool_bm25, mcp_get_tool_schema, mcp_execute_tool)
4680
+ * - `search` → returns only meta-tools (mcp_search_tools, mcp_get_tool_schema, mcp_execute_tool)
4536
4681
  * - `groups` → returns tools from active groups only
4537
4682
  */
4538
4683
  async getFilteredTools() {
@@ -4561,9 +4706,10 @@ var ToolRouter = class {
4561
4706
  * Search tools by natural-language query.
4562
4707
  * Works regardless of strategy.
4563
4708
  */
4564
- async searchTools(query, topK) {
4709
+ async searchTools(query, topK, options = {}) {
4565
4710
  await this.ensureInitialized();
4566
- return this.index.search(query, topK ?? this.maxTools);
4711
+ const limit = topK ?? this.maxTools;
4712
+ return this.index.search(query, limit, options);
4567
4713
  }
4568
4714
  /**
4569
4715
  * Search tools by regex pattern.
@@ -4573,12 +4719,22 @@ var ToolRouter = class {
4573
4719
  await this.ensureInitialized();
4574
4720
  return this.index.searchRegex(pattern, topK ?? this.maxTools);
4575
4721
  }
4722
+ /** List connected MCP servers with indexed tool counts. */
4723
+ async listServers(options = {}) {
4724
+ await this.ensureInitialized();
4725
+ return this.index.listServers(options);
4726
+ }
4727
+ /** List tools deterministically, optionally scoped to a server. */
4728
+ async listTools(options = {}) {
4729
+ await this.ensureInitialized();
4730
+ return this.index.listTools(options);
4731
+ }
4576
4732
  /**
4577
4733
  * Get the full tool definition by name.
4578
4734
  * If tool name is ambiguous, use namespace to specify the server.
4579
4735
  */
4580
- getToolSchema(toolName, namespace) {
4581
- const matches = this.index.getTool(toolName, namespace);
4736
+ getToolSchema(toolName, namespace, options = {}) {
4737
+ const matches = this.index.getTool(toolName, namespace, options);
4582
4738
  if (matches.length === 0) return void 0;
4583
4739
  if (matches.length > 1) {
4584
4740
  const servers = matches.map((m) => m.serverId).join(", ");
@@ -4657,7 +4813,7 @@ var ToolRouter = class {
4657
4813
  const indexedTool = this.getToolSchema(toolName, namespace);
4658
4814
  if (!indexedTool) {
4659
4815
  throw new Error(
4660
- `Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use mcp_search_tool_bm25 or mcp_search_tool_regex to discover available tools.`
4816
+ `Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use mcp_search_tools or mcp_search_tool_regex to discover available tools.`
4661
4817
  );
4662
4818
  }
4663
4819
  const clients = this.getClients();
@@ -4769,6 +4925,7 @@ var ToolRouter = class {
4769
4925
  getMetaToolDefinitions() {
4770
4926
  return [
4771
4927
  createSearchToolDefinition(),
4928
+ createListServersToolDefinition(),
4772
4929
  createRegexSearchToolDefinition(),
4773
4930
  createGetSchemaToolDefinition(),
4774
4931
  createExecuteToolDefinition()
@@ -4776,6 +4933,6 @@ var ToolRouter = class {
4776
4933
  }
4777
4934
  };
4778
4935
 
4779
- export { APP_HOST_DEFAULTS, AppHost, AuthenticationError, ConfigurationError, ConnectionError, DEFAULT_CLIENT_NAME, DEFAULT_CLIENT_URI, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_LOGO_URI, DEFAULT_MCP_APP_CSP, DEFAULT_POLICY_URI, DisposableStore, Emitter, InvalidStateError, MCPClient, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, McpError, MultiSessionClient, NotConnectedError, REDIS_KEY_PREFIX, RpcErrorCodes, SANDBOX_PROXY_READY_METHOD, SANDBOX_RESOURCE_READY_METHOD, SESSION_TTL_SECONDS, SOFTWARE_ID, SOFTWARE_VERSION, SSEClient, SSEConnectionManager, STATE_EXPIRATION_MS, SchemaCompressor, SessionNotFoundError, SessionValidationError, StorageOAuthClientProvider, TOKEN_EXPIRY_BUFFER_MS, ToolExecutionError, ToolIndex, ToolRouter, UnauthorizedError, createExecuteToolDefinition, createGetSchemaToolDefinition, createNextMcpHandler, createRegexSearchToolDefinition, createSSEHandler, createSearchToolDefinition, executeMetaTool, findToolByName, getToolUiResourceUri, isCallToolSuccess, isConnectAuthRequired, isConnectError, isConnectSuccess, isListToolsSuccess, isMetaTool, resolveMetaToolProxy, sanitizeServerLabel, storage };
4936
+ export { APP_HOST_DEFAULTS, AppHost, AuthenticationError, ConfigurationError, ConnectionError, DEFAULT_CLIENT_NAME, DEFAULT_CLIENT_URI, DEFAULT_HEARTBEAT_INTERVAL_MS, DEFAULT_LOGO_URI, DEFAULT_MCP_APP_CSP, DEFAULT_POLICY_URI, DisposableStore, Emitter, InvalidStateError, MCPClient, MCP_CLIENT_NAME, MCP_CLIENT_VERSION, McpError, MultiSessionClient, NotConnectedError, REDIS_KEY_PREFIX, RpcErrorCodes, SANDBOX_PROXY_READY_METHOD, SANDBOX_RESOURCE_READY_METHOD, SESSION_TTL_SECONDS, SOFTWARE_ID, SOFTWARE_VERSION, SSEClient, SSEConnectionManager, STATE_EXPIRATION_MS, SchemaCompressor, SessionNotFoundError, SessionValidationError, StorageOAuthClientProvider, TOKEN_EXPIRY_BUFFER_MS, ToolExecutionError, ToolIndex, ToolRouter, UnauthorizedError, createExecuteToolDefinition, createGetSchemaToolDefinition, createListServersToolDefinition, createNextMcpHandler, createRegexSearchToolDefinition, createSSEHandler, createSearchToolDefinition, executeMetaTool, findToolByName, getToolUiResourceUri, isCallToolSuccess, isConnectAuthRequired, isConnectError, isConnectSuccess, isListToolsSuccess, isMetaTool, resolveMetaToolProxy, sanitizeServerLabel, storage };
4780
4937
  //# sourceMappingURL=index.mjs.map
4781
4938
  //# sourceMappingURL=index.mjs.map