@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
package/dist/index.mjs CHANGED
@@ -1515,9 +1515,10 @@ var MCPClient = class _MCPClient {
1515
1515
  throw new Error("Server URL is required to create transport");
1516
1516
  }
1517
1517
  const baseUrl = new URL(this.serverUrl);
1518
+ const hasAuthorizationHeader = Object.keys(this.headers || {}).some((key) => key.toLowerCase() === "authorization");
1518
1519
  const transportOptions = {
1519
- authProvider: this.oauthProvider,
1520
- ...this.headers && { headers: this.headers },
1520
+ ...!hasAuthorizationHeader && { authProvider: this.oauthProvider },
1521
+ ...this.headers && { requestInit: { headers: this.headers } },
1521
1522
  /**
1522
1523
  * Custom fetch implementation to handle connection timeouts.
1523
1524
  * Observation: SDK 1.24.0+ connections may hang indefinitely in some environments.
@@ -1618,6 +1619,7 @@ var MCPClient = class _MCPClient {
1618
1619
  serverUrl: this.serverUrl,
1619
1620
  callbackUrl: this.callbackUrl,
1620
1621
  transportType: this.transportType || "streamable_http",
1622
+ headers: this.headers,
1621
1623
  createdAt: this.createdAt,
1622
1624
  active: false
1623
1625
  }, Math.floor(STATE_EXPIRATION_MS / 1e3));
@@ -1642,6 +1644,7 @@ var MCPClient = class _MCPClient {
1642
1644
  serverUrl: this.serverUrl,
1643
1645
  callbackUrl: this.callbackUrl,
1644
1646
  transportType: this.transportType || "streamable_http",
1647
+ headers: this.headers,
1645
1648
  createdAt: this.createdAt || Date.now(),
1646
1649
  active
1647
1650
  };
@@ -2201,9 +2204,7 @@ var MCPClient = class _MCPClient {
2201
2204
  * @returns Server name or undefined
2202
2205
  */
2203
2206
  getServerName() {
2204
- const info = this.client?.getServerVersion();
2205
- console.log("server info ->", info);
2206
- return info?.title ?? info?.name ?? this.serverName;
2207
+ return this.serverName;
2207
2208
  }
2208
2209
  /**
2209
2210
  * Gets the server ID
@@ -2477,6 +2478,11 @@ function isConnectionEvent(event) {
2477
2478
 
2478
2479
  // src/server/handlers/sse-handler.ts
2479
2480
  var DEFAULT_HEARTBEAT_INTERVAL = 3e4;
2481
+ function normalizeHeaders(headers) {
2482
+ if (!headers || typeof headers !== "object") return void 0;
2483
+ const entries = Object.entries(headers).map(([key, value]) => [key.trim(), String(value).trim()]).filter(([key, value]) => key.length > 0 && value.length > 0);
2484
+ return entries.length > 0 ? Object.fromEntries(entries) : void 0;
2485
+ }
2480
2486
  var SSEConnectionManager = class {
2481
2487
  constructor(options, sendEvent) {
2482
2488
  this.options = options;
@@ -2601,6 +2607,7 @@ var SSEConnectionManager = class {
2601
2607
  */
2602
2608
  async connect(params) {
2603
2609
  const { serverName, serverUrl, callbackUrl, transportType } = params;
2610
+ const headers = normalizeHeaders(params.headers);
2604
2611
  const serverId = params.serverId && params.serverId.length <= 12 ? params.serverId : await storage.generateSessionId();
2605
2612
  const existingSessions = await storage.getIdentitySessionsData(this.identity);
2606
2613
  const duplicate = existingSessions.find(
@@ -2627,6 +2634,7 @@ var SSEConnectionManager = class {
2627
2634
  serverUrl,
2628
2635
  callbackUrl,
2629
2636
  transportType,
2637
+ headers,
2630
2638
  ...clientMetadata
2631
2639
  // Spread client metadata (clientName, clientUri, logoUri, policyUri)
2632
2640
  });
@@ -3945,17 +3953,17 @@ var ToolIndex = class _ToolIndex {
3945
3953
  *
3946
3954
  * `score = keywordWeight × keyword_score + (1 - keywordWeight) × cosine_score`
3947
3955
  */
3948
- async search(query, topK = 5) {
3956
+ async search(query, topK = 5, options = {}) {
3949
3957
  if (this.tools.size === 0) return [];
3950
3958
  const queryLower = query.toLowerCase().trim();
3951
3959
  const exactMatches = [...this.toolSummaries.values()].filter(
3952
- (summary) => summary.name.toLowerCase() === queryLower
3960
+ (summary) => summary.name.toLowerCase() === queryLower && this.matchesServer(summary, options)
3953
3961
  );
3954
3962
  if (exactMatches.length > 0) {
3955
3963
  return exactMatches.slice(0, topK);
3956
3964
  }
3957
3965
  if (queryLower.startsWith("mcp__") && queryLower.length > 5) {
3958
- const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower)).slice(0, topK);
3966
+ const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower) && this.matchesServer(t, options)).slice(0, topK);
3959
3967
  if (prefixMatches.length > 0) return prefixMatches;
3960
3968
  }
3961
3969
  const queryTermsRaw = queryLower.split(/\s+/).filter((t) => t.length > 0);
@@ -3973,9 +3981,10 @@ var ToolIndex = class _ToolIndex {
3973
3981
  const queryTokens = this.tokenize(allScoringTerms.join(" "));
3974
3982
  const candidateKeys = /* @__PURE__ */ new Set();
3975
3983
  for (const docKey of this.toolSummaries.keys()) {
3984
+ const summary = this.toolSummaries.get(docKey);
3985
+ if (!this.matchesServer(summary, options)) continue;
3976
3986
  if (requiredTerms.length > 0) {
3977
3987
  const text = this.searchTexts.get(docKey) || "";
3978
- const summary = this.toolSummaries.get(docKey);
3979
3988
  const nameLower = summary.name.toLowerCase();
3980
3989
  const matchesAll = requiredTerms.every(
3981
3990
  (term) => text.includes(term) || nameLower.includes(term)
@@ -4086,17 +4095,66 @@ var ToolIndex = class _ToolIndex {
4086
4095
  // -----------------------------------------------------------------------
4087
4096
  /**
4088
4097
  * Get tool definition(s) by name.
4089
- * If namespace is provided, it tries to match sessionId or serverName.
4098
+ * If namespace is provided, exact sessionId/serverId matches take precedence.
4099
+ * Falls back to serverName fragment matching only when explicitly allowed.
4090
4100
  */
4091
- getTool(name, namespace) {
4101
+ getTool(name, namespace, options = {}) {
4092
4102
  const list = this.tools.get(name) ?? [];
4093
4103
  if (!namespace) return list;
4094
- return list.filter((t) => t.sessionId === namespace || t.serverId === namespace);
4104
+ const exactMatches = list.filter(
4105
+ (t) => t.sessionId === namespace || t.serverId === namespace
4106
+ );
4107
+ if (exactMatches.length > 0) return exactMatches;
4108
+ if (!options.allowServerNameFragment) return [];
4109
+ const namespaceLower = namespace.toLowerCase();
4110
+ return list.filter((t) => t.serverName.toLowerCase().includes(namespaceLower));
4095
4111
  }
4096
4112
  /** All indexed tool names. */
4097
4113
  getToolNames() {
4098
4114
  return [...this.tools.keys()];
4099
4115
  }
4116
+ /** List indexed servers with tool counts. */
4117
+ listServers(options = {}) {
4118
+ const servers = /* @__PURE__ */ new Map();
4119
+ for (const summary of this.toolSummaries.values()) {
4120
+ if (!this.matchesServer(summary, options)) continue;
4121
+ const key = `${summary.sessionId}::${summary.serverId}`;
4122
+ const existing = servers.get(key);
4123
+ if (existing) {
4124
+ existing.toolCount += 1;
4125
+ } else {
4126
+ servers.set(key, {
4127
+ serverName: summary.serverName,
4128
+ serverId: summary.serverId,
4129
+ sessionId: summary.sessionId,
4130
+ toolCount: 1
4131
+ });
4132
+ }
4133
+ }
4134
+ return [...servers.values()].sort((a, b) => {
4135
+ const byName = a.serverName.localeCompare(b.serverName);
4136
+ return byName !== 0 ? byName : a.serverId.localeCompare(b.serverId);
4137
+ });
4138
+ }
4139
+ /** List tools deterministically, optionally scoped to a server. */
4140
+ listTools(options = {}) {
4141
+ const offset = Math.max(Number(options.cursor) || 0, 0);
4142
+ const limit = Math.max(Number(options.limit) || 20, 1);
4143
+ const tools = [...this.toolSummaries.values()].filter((summary) => this.matchesServer(summary, options)).sort((a, b) => {
4144
+ const byServer = a.serverName.localeCompare(b.serverName);
4145
+ if (byServer !== 0) return byServer;
4146
+ return a.name.localeCompare(b.name);
4147
+ });
4148
+ const page = tools.slice(offset, offset + limit);
4149
+ const nextOffset = offset + page.length;
4150
+ return {
4151
+ tools: page,
4152
+ totalCount: tools.length,
4153
+ returnedCount: page.length,
4154
+ nextCursor: nextOffset < tools.length ? String(nextOffset) : void 0,
4155
+ servers: this.listServers(options)
4156
+ };
4157
+ }
4100
4158
  /** Number of indexed tools (including duplicates). */
4101
4159
  get size() {
4102
4160
  let count = 0;
@@ -4153,6 +4211,20 @@ var ToolIndex = class _ToolIndex {
4153
4211
  getDocumentKey(tool) {
4154
4212
  return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
4155
4213
  }
4214
+ matchesServer(summary, options) {
4215
+ if (options.serverId && summary.serverId !== options.serverId) {
4216
+ return false;
4217
+ }
4218
+ if (options.serverName) {
4219
+ const serverNameQuery = options.serverName.toLowerCase();
4220
+ const serverName = summary.serverName.toLowerCase();
4221
+ const serverId = summary.serverId.toLowerCase();
4222
+ if (!serverName.includes(serverNameQuery) && !serverId.includes(serverNameQuery)) {
4223
+ return false;
4224
+ }
4225
+ }
4226
+ return true;
4227
+ }
4156
4228
  /** Simple whitespace + camelCase + snake_case tokenizer. */
4157
4229
  tokenize(text) {
4158
4230
  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 +4308,7 @@ var SchemaCompressor = class _SchemaCompressor {
4236
4308
  // src/shared/meta-tools.ts
4237
4309
  function createSearchToolDefinition() {
4238
4310
  return {
4239
- name: "mcp_search_tool_bm25",
4311
+ name: "mcp_search_tools",
4240
4312
  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
4313
  inputSchema: {
4242
4314
  type: "object",
@@ -4245,15 +4317,47 @@ function createSearchToolDefinition() {
4245
4317
  type: "string",
4246
4318
  description: 'Query to find tools. Use "select:<tool_name>" for direct selection, or keywords to search. Prefix keywords with + to require them.'
4247
4319
  },
4320
+ operation: {
4321
+ type: "string",
4322
+ enum: ["search", "list"],
4323
+ 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.'
4324
+ },
4325
+ serverId: {
4326
+ type: "string",
4327
+ description: "Optional server ID to restrict search/list results to one MCP server."
4328
+ },
4329
+ serverName: {
4330
+ type: "string",
4331
+ description: 'Optional server name fragment to restrict search/list results to matching MCP servers, e.g. "supabase".'
4332
+ },
4248
4333
  limit: {
4249
4334
  type: "number",
4250
- description: "Maximum number of results to return (default: 5, max: 20)."
4335
+ description: "Maximum number of results to return (default: 5 for search, 20 for list; max: 20 for search, 100 for list)."
4336
+ },
4337
+ cursor: {
4338
+ type: "string",
4339
+ description: 'Optional pagination cursor returned by operation "list".'
4251
4340
  }
4252
4341
  },
4253
4342
  required: ["query"]
4254
4343
  }
4255
4344
  };
4256
4345
  }
4346
+ function createListServersToolDefinition() {
4347
+ return {
4348
+ name: "mcp_list_servers",
4349
+ 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.",
4350
+ inputSchema: {
4351
+ type: "object",
4352
+ properties: {
4353
+ query: {
4354
+ type: "string",
4355
+ description: 'Optional server filter text. Matches server name or serverId, e.g. "web" or "supabase".'
4356
+ }
4357
+ }
4358
+ }
4359
+ };
4360
+ }
4257
4361
  function createRegexSearchToolDefinition() {
4258
4362
  return {
4259
4363
  name: "mcp_search_tool_regex",
@@ -4277,17 +4381,17 @@ function createRegexSearchToolDefinition() {
4277
4381
  function createGetSchemaToolDefinition() {
4278
4382
  return {
4279
4383
  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.",
4384
+ 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
4385
  inputSchema: {
4282
4386
  type: "object",
4283
4387
  properties: {
4284
4388
  toolName: {
4285
4389
  type: "string",
4286
- description: "The exact tool name returned by mcp_search_tool_bm25."
4390
+ description: "The exact tool name returned by mcp_search_tools."
4287
4391
  },
4288
4392
  serverId: {
4289
4393
  type: "string",
4290
- description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4394
+ description: "Optional: The server ID provided in mcp_search_tools. Required if multiple tools have the same name."
4291
4395
  }
4292
4396
  },
4293
4397
  required: ["toolName"]
@@ -4297,17 +4401,17 @@ function createGetSchemaToolDefinition() {
4297
4401
  function createExecuteToolDefinition() {
4298
4402
  return {
4299
4403
  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.",
4404
+ 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
4405
  inputSchema: {
4302
4406
  type: "object",
4303
4407
  properties: {
4304
4408
  toolName: {
4305
4409
  type: "string",
4306
- description: "The exact tool name from mcp_search_tool_bm25 results."
4410
+ description: "The exact tool name from mcp_search_tools results."
4307
4411
  },
4308
4412
  serverId: {
4309
4413
  type: "string",
4310
- description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4414
+ description: "Optional: The server ID provided in mcp_search_tools. Required if multiple tools have the same name."
4311
4415
  },
4312
4416
  args: {
4313
4417
  type: "object",
@@ -4320,9 +4424,9 @@ function createExecuteToolDefinition() {
4320
4424
  };
4321
4425
  }
4322
4426
  async function executeMetaTool(toolName, args, router, callToolFn) {
4323
- const resolveToolSchema = (name, namespace) => {
4427
+ const resolveToolSchema = (name, namespace, options) => {
4324
4428
  try {
4325
- return { tool: router.getToolSchema(name, namespace) };
4429
+ return { tool: router.getToolSchema(name, namespace, options) };
4326
4430
  } catch (err) {
4327
4431
  const errorMessage = err instanceof Error ? err.message : String(err);
4328
4432
  return {
@@ -4334,23 +4438,61 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4334
4438
  }
4335
4439
  };
4336
4440
  switch (toolName) {
4337
- case "mcp_search_tool_bm25": {
4441
+ case "mcp_search_tools": {
4338
4442
  const query = String(args.query ?? "");
4443
+ const operation = String(args.operation ?? "search");
4444
+ const serverId = String(args.serverId ?? "") || void 0;
4445
+ const serverName = String(args.serverName ?? "") || void 0;
4446
+ if (operation === "list") {
4447
+ const limit2 = Math.min(Number(args.limit) || 20, 100);
4448
+ const cursor = String(args.cursor ?? "") || void 0;
4449
+ const result = await router.listTools({
4450
+ serverId,
4451
+ serverName: serverName ?? (!serverId && query ? query : void 0),
4452
+ limit: limit2,
4453
+ cursor
4454
+ });
4455
+ const serverText = result.servers.length > 0 ? result.servers.map((server) => `${server.serverName} (serverId: ${server.serverId}, tools: ${server.toolCount})`).join(", ") : "none";
4456
+ const lines = [
4457
+ "operation: list",
4458
+ `servers: ${serverText}`,
4459
+ `totalCount: ${result.totalCount}`,
4460
+ `returnedCount: ${result.returnedCount}`,
4461
+ `nextCursor: ${result.nextCursor ?? "null"}`,
4462
+ ""
4463
+ ];
4464
+ if (result.tools.length > 0) {
4465
+ lines.push(...formatToolSummaries(result.tools));
4466
+ } else {
4467
+ lines.push(
4468
+ serverId || serverName ? "No tools found for the requested server scope." : 'No tools found. Try operation "search" or provide serverId/serverName.'
4469
+ );
4470
+ }
4471
+ return {
4472
+ content: [{ type: "text", text: lines.join("\n") }],
4473
+ isError: false
4474
+ };
4475
+ }
4339
4476
  const limit = Math.min(Number(args.limit) || 5, 20);
4477
+ const searchOptions = { serverId, serverName };
4340
4478
  const selectMatch = query.match(/^select:(.+)$/i);
4341
4479
  if (selectMatch) {
4480
+ await router.listTools({ serverId, serverName, limit: 1 });
4342
4481
  const requested = selectMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
4343
4482
  const found = [];
4344
4483
  const errors = [];
4484
+ const namespace = serverId ?? serverName;
4345
4485
  for (const requestedToolName of requested) {
4346
- const { tool, error } = resolveToolSchema(requestedToolName);
4486
+ const { tool, error } = resolveToolSchema(requestedToolName, namespace, {
4487
+ allowServerNameFragment: Boolean(serverName && !serverId)
4488
+ });
4347
4489
  if (error) {
4348
4490
  const errorMsg = error.content[0]?.type === "text" ? error.content[0].text : "Unknown error";
4349
4491
  errors.push(`- **${requestedToolName}**: ${errorMsg}`);
4350
4492
  } else if (tool) {
4351
4493
  found.push(tool);
4352
4494
  } else {
4353
- errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tool_bm25.`);
4495
+ errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tools.`);
4354
4496
  }
4355
4497
  }
4356
4498
  const lines = [];
@@ -4371,11 +4513,21 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4371
4513
  isError: found.length === 0
4372
4514
  };
4373
4515
  }
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}`
4516
+ const results = await router.searchTools(query, limit, searchOptions);
4517
+ 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");
4518
+ return {
4519
+ content: [{ type: "text", text }],
4520
+ isError: false
4521
+ };
4522
+ }
4523
+ case "mcp_list_servers": {
4524
+ const query = String(args.query ?? "").trim();
4525
+ const servers = await router.listServers({
4526
+ serverName: query || void 0
4527
+ });
4528
+ const text = servers.length === 0 ? "No connected servers found." : servers.map(
4529
+ (server, i) => `${i + 1}. **${server.serverName}** (serverId: ${server.serverId}, sessionId: ${server.sessionId})
4530
+ Tool count: ${server.toolCount}`
4379
4531
  ).join("\n");
4380
4532
  return {
4381
4533
  content: [{ type: "text", text }],
@@ -4386,11 +4538,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4386
4538
  const pattern = String(args.query ?? "");
4387
4539
  const limit = Math.min(Number(args.limit) || 5, 20);
4388
4540
  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");
4541
+ const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : formatToolSummaries(results).join("\n");
4394
4542
  return {
4395
4543
  content: [{ type: "text", text }],
4396
4544
  isError: false
@@ -4408,7 +4556,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4408
4556
  content: [
4409
4557
  {
4410
4558
  type: "text",
4411
- text: `Tool "${name}" not found. Use mcp_search_tool_bm25 to find available tools first.`
4559
+ text: `Tool "${name}" not found. Use mcp_search_tools to find available tools first.`
4412
4560
  }
4413
4561
  ],
4414
4562
  isError: true
@@ -4449,7 +4597,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4449
4597
  content: [
4450
4598
  {
4451
4599
  type: "text",
4452
- text: `Tool "${targetToolName}" not found. Use mcp_search_tool_bm25 to discover available tools first.`
4600
+ text: `Tool "${targetToolName}" not found. Use mcp_search_tools to discover available tools first.`
4453
4601
  }
4454
4602
  ],
4455
4603
  isError: true
@@ -4483,8 +4631,15 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4483
4631
  return null;
4484
4632
  }
4485
4633
  }
4634
+ function formatToolSummaries(tools) {
4635
+ return tools.map(
4636
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4637
+ ${t.description}
4638
+ Estimated tokens: ${t.estimatedTokens}`
4639
+ );
4640
+ }
4486
4641
  function isMetaTool(toolName) {
4487
- return toolName === "mcp_search_tool_bm25" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
4642
+ return toolName === "mcp_search_tools" || toolName === "mcp_list_servers" || toolName === "mcp_search_tool_regex" || toolName === "mcp_get_tool_schema" || toolName === "mcp_execute_tool";
4488
4643
  }
4489
4644
  function resolveMetaToolProxy(toolName, args) {
4490
4645
  if (toolName === "mcp_execute_tool") {
@@ -4532,7 +4687,7 @@ var ToolRouter = class {
4532
4687
  * This is the main method adapters should call.
4533
4688
  *
4534
4689
  * - `all` → returns all tools (unchanged behavior)
4535
- * - `search` → returns only meta-tools (mcp_search_tool_bm25, mcp_get_tool_schema, mcp_execute_tool)
4690
+ * - `search` → returns only meta-tools (mcp_search_tools, mcp_get_tool_schema, mcp_execute_tool)
4536
4691
  * - `groups` → returns tools from active groups only
4537
4692
  */
4538
4693
  async getFilteredTools() {
@@ -4561,9 +4716,10 @@ var ToolRouter = class {
4561
4716
  * Search tools by natural-language query.
4562
4717
  * Works regardless of strategy.
4563
4718
  */
4564
- async searchTools(query, topK) {
4719
+ async searchTools(query, topK, options = {}) {
4565
4720
  await this.ensureInitialized();
4566
- return this.index.search(query, topK ?? this.maxTools);
4721
+ const limit = topK ?? this.maxTools;
4722
+ return this.index.search(query, limit, options);
4567
4723
  }
4568
4724
  /**
4569
4725
  * Search tools by regex pattern.
@@ -4573,12 +4729,22 @@ var ToolRouter = class {
4573
4729
  await this.ensureInitialized();
4574
4730
  return this.index.searchRegex(pattern, topK ?? this.maxTools);
4575
4731
  }
4732
+ /** List connected MCP servers with indexed tool counts. */
4733
+ async listServers(options = {}) {
4734
+ await this.ensureInitialized();
4735
+ return this.index.listServers(options);
4736
+ }
4737
+ /** List tools deterministically, optionally scoped to a server. */
4738
+ async listTools(options = {}) {
4739
+ await this.ensureInitialized();
4740
+ return this.index.listTools(options);
4741
+ }
4576
4742
  /**
4577
4743
  * Get the full tool definition by name.
4578
4744
  * If tool name is ambiguous, use namespace to specify the server.
4579
4745
  */
4580
- getToolSchema(toolName, namespace) {
4581
- const matches = this.index.getTool(toolName, namespace);
4746
+ getToolSchema(toolName, namespace, options = {}) {
4747
+ const matches = this.index.getTool(toolName, namespace, options);
4582
4748
  if (matches.length === 0) return void 0;
4583
4749
  if (matches.length > 1) {
4584
4750
  const servers = matches.map((m) => m.serverId).join(", ");
@@ -4657,7 +4823,7 @@ var ToolRouter = class {
4657
4823
  const indexedTool = this.getToolSchema(toolName, namespace);
4658
4824
  if (!indexedTool) {
4659
4825
  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.`
4826
+ `Tool "${toolName}" not found${namespace ? ` on server "${namespace}"` : ""}. Use mcp_search_tools or mcp_search_tool_regex to discover available tools.`
4661
4827
  );
4662
4828
  }
4663
4829
  const clients = this.getClients();
@@ -4769,6 +4935,7 @@ var ToolRouter = class {
4769
4935
  getMetaToolDefinitions() {
4770
4936
  return [
4771
4937
  createSearchToolDefinition(),
4938
+ createListServersToolDefinition(),
4772
4939
  createRegexSearchToolDefinition(),
4773
4940
  createGetSchemaToolDefinition(),
4774
4941
  createExecuteToolDefinition()
@@ -4776,6 +4943,6 @@ var ToolRouter = class {
4776
4943
  }
4777
4944
  };
4778
4945
 
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 };
4946
+ 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
4947
  //# sourceMappingURL=index.mjs.map
4781
4948
  //# sourceMappingURL=index.mjs.map