@mcp-ts/sdk 1.5.0 → 1.5.2

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 (66) 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 +43 -9
  4. package/dist/adapters/agui-adapter.js.map +1 -1
  5. package/dist/adapters/agui-adapter.mjs +43 -9
  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/agui-middleware.js.map +1 -1
  10. package/dist/adapters/agui-middleware.mjs.map +1 -1
  11. package/dist/adapters/ai-adapter.d.mts +1 -1
  12. package/dist/adapters/ai-adapter.d.ts +1 -1
  13. package/dist/adapters/ai-adapter.js +42 -8
  14. package/dist/adapters/ai-adapter.js.map +1 -1
  15. package/dist/adapters/ai-adapter.mjs +42 -8
  16. package/dist/adapters/ai-adapter.mjs.map +1 -1
  17. package/dist/adapters/langchain-adapter.d.mts +1 -1
  18. package/dist/adapters/langchain-adapter.d.ts +1 -1
  19. package/dist/adapters/langchain-adapter.js +42 -8
  20. package/dist/adapters/langchain-adapter.js.map +1 -1
  21. package/dist/adapters/langchain-adapter.mjs +42 -8
  22. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  23. package/dist/client/react.d.mts +91 -2
  24. package/dist/client/react.d.ts +91 -2
  25. package/dist/client/react.js +339 -3
  26. package/dist/client/react.js.map +1 -1
  27. package/dist/client/react.mjs +335 -4
  28. package/dist/client/react.mjs.map +1 -1
  29. package/dist/client/vue.d.mts +10 -0
  30. package/dist/client/vue.d.ts +10 -0
  31. package/dist/client/vue.js +28 -2
  32. package/dist/client/vue.js.map +1 -1
  33. package/dist/client/vue.mjs +28 -2
  34. package/dist/client/vue.mjs.map +1 -1
  35. package/dist/index.d.mts +1 -1
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.js +170 -37
  38. package/dist/index.js.map +1 -1
  39. package/dist/index.mjs +170 -37
  40. package/dist/index.mjs.map +1 -1
  41. package/dist/server/index.js +55 -11
  42. package/dist/server/index.js.map +1 -1
  43. package/dist/server/index.mjs +55 -11
  44. package/dist/server/index.mjs.map +1 -1
  45. package/dist/shared/index.d.mts +2 -2
  46. package/dist/shared/index.d.ts +2 -2
  47. package/dist/shared/index.js +115 -26
  48. package/dist/shared/index.js.map +1 -1
  49. package/dist/shared/index.mjs +115 -26
  50. package/dist/shared/index.mjs.map +1 -1
  51. package/dist/{tool-router-XnWVxPzv.d.mts → tool-router-DK0RJblO.d.mts} +3 -0
  52. package/dist/{tool-router-Bo8qZbsD.d.ts → tool-router-DsKhRmJm.d.ts} +3 -0
  53. package/package.json +1 -1
  54. package/src/adapters/agui-adapter.ts +7 -7
  55. package/src/adapters/ai-adapter.ts +5 -5
  56. package/src/adapters/langchain-adapter.ts +5 -5
  57. package/src/client/react/index.ts +14 -0
  58. package/src/client/react/oauth-popup.tsx +446 -0
  59. package/src/client/react/use-mcp.ts +84 -3
  60. package/src/client/vue/use-mcp.ts +80 -3
  61. package/src/server/handlers/sse-handler.ts +39 -0
  62. package/src/server/mcp/oauth-client.ts +32 -14
  63. package/src/shared/meta-tools.ts +62 -13
  64. package/src/shared/tool-index.ts +85 -12
  65. package/src/shared/tool-router.ts +8 -7
  66. package/supabase/migrations/20260421010000_add_session_cleanup_cron.sql +32 -0
package/dist/index.mjs CHANGED
@@ -1716,13 +1716,8 @@ var MCPClient = class _MCPClient {
1716
1716
  this.transportType = transportType;
1717
1717
  this.emitStateChange("CONNECTED");
1718
1718
  this.emitProgress("Connected successfully");
1719
- const existingSession = await storage.getSession(this.identity, this.sessionId);
1720
- const needsTransportUpdate = !existingSession || existingSession.transportType !== this.transportType;
1721
- const needsTtlPromotion = !existingSession || existingSession.active !== true;
1722
- if (needsTransportUpdate || needsTtlPromotion) {
1723
- console.log(`[MCPClient] Saving session ${this.sessionId} with 12hr TTL (connect success)`);
1724
- await this.saveSession(SESSION_TTL_SECONDS, true);
1725
- }
1719
+ console.log(`[MCPClient] Saving session ${this.sessionId} with 12hr TTL (connect success)`);
1720
+ await this.saveSession(SESSION_TTL_SECONDS, true);
1726
1721
  } catch (error) {
1727
1722
  if (error instanceof UnauthorizedError$1 || error instanceof Error && error.message.toLowerCase().includes("unauthorized")) {
1728
1723
  let authUrl = "";
@@ -1760,6 +1755,13 @@ var MCPClient = class _MCPClient {
1760
1755
  const errorMessage = error instanceof Error ? error.message : "Connection failed";
1761
1756
  this.emitError(errorMessage, "connection");
1762
1757
  this.emitStateChange("FAILED");
1758
+ try {
1759
+ const existingSession = await storage.getSession(this.identity, this.sessionId);
1760
+ if (!existingSession || existingSession.active !== true) {
1761
+ await storage.removeSession(this.identity, this.sessionId);
1762
+ }
1763
+ } catch {
1764
+ }
1763
1765
  throw error;
1764
1766
  }
1765
1767
  }
@@ -1783,6 +1785,7 @@ var MCPClient = class _MCPClient {
1783
1785
  const transportsToTry = this.transportType ? [this.transportType] : ["streamable_http", "sse"];
1784
1786
  let lastError;
1785
1787
  let tokensExchanged = false;
1788
+ let authenticatedStateEmitted = false;
1786
1789
  for (const currentType of transportsToTry) {
1787
1790
  const isLastAttempt = currentType === transportsToTry[transportsToTry.length - 1];
1788
1791
  try {
@@ -1794,8 +1797,10 @@ var MCPClient = class _MCPClient {
1794
1797
  } else {
1795
1798
  this.emitProgress(`Tokens already exchanged, skipping auth step for ${currentType}...`);
1796
1799
  }
1797
- this.transportType = currentType;
1798
- this.emitStateChange("AUTHENTICATED");
1800
+ if (!authenticatedStateEmitted) {
1801
+ this.emitStateChange("AUTHENTICATED");
1802
+ authenticatedStateEmitted = true;
1803
+ }
1799
1804
  this.emitProgress("Creating authenticated client...");
1800
1805
  this.client = new Client(
1801
1806
  {
@@ -1814,6 +1819,7 @@ var MCPClient = class _MCPClient {
1814
1819
  );
1815
1820
  this.emitStateChange("CONNECTING");
1816
1821
  await this.client.connect(this.transport);
1822
+ this.transportType = currentType;
1817
1823
  this.emitStateChange("CONNECTED");
1818
1824
  console.log(`[MCPClient] Updating session ${this.sessionId} to 12hr TTL (OAuth complete)`);
1819
1825
  await this.saveSession(SESSION_TTL_SECONDS, true);
@@ -2680,9 +2686,23 @@ var SSEConnectionManager = class {
2680
2686
  if (existing) {
2681
2687
  return existing;
2682
2688
  }
2689
+ const session = await storage.getSession(this.identity, sessionId);
2690
+ if (!session) {
2691
+ throw new Error("Session not found");
2692
+ }
2683
2693
  const client = new MCPClient({
2684
2694
  identity: this.identity,
2685
- sessionId
2695
+ sessionId,
2696
+ // These fields are optional in MCPClient, but when rehydrating a known
2697
+ // stored session on the server we pass them explicitly to preserve the
2698
+ // original transport/connection metadata instead of relying on lazy
2699
+ // reloading during initialize().
2700
+ serverId: session.serverId,
2701
+ serverName: session.serverName,
2702
+ serverUrl: session.serverUrl,
2703
+ callbackUrl: session.callbackUrl,
2704
+ transportType: session.transportType,
2705
+ headers: session.headers
2686
2706
  });
2687
2707
  client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2688
2708
  client.onObservabilityEvent((event) => this.sendEvent(event));
@@ -2739,6 +2759,16 @@ var SSEConnectionManager = class {
2739
2759
  const client = new MCPClient({
2740
2760
  identity: this.identity,
2741
2761
  sessionId,
2762
+ // These fields are optional in MCPClient, but when rehydrating a known
2763
+ // stored session on the server we pass them explicitly to preserve the
2764
+ // original transport/connection metadata instead of relying on lazy
2765
+ // reloading during initialize().
2766
+ serverId: session.serverId,
2767
+ serverName: session.serverName,
2768
+ serverUrl: session.serverUrl,
2769
+ callbackUrl: session.callbackUrl,
2770
+ transportType: session.transportType,
2771
+ headers: session.headers,
2742
2772
  ...clientMetadata
2743
2773
  });
2744
2774
  client.onConnectionEvent((event) => this.emitConnectionEvent(event));
@@ -2771,7 +2801,21 @@ var SSEConnectionManager = class {
2771
2801
  try {
2772
2802
  const client = new MCPClient({
2773
2803
  identity: this.identity,
2774
- sessionId
2804
+ sessionId,
2805
+ // These fields are optional in MCPClient, but when rehydrating a known
2806
+ // stored session on the server we pass them explicitly to preserve the
2807
+ // original connection metadata instead of relying on lazy
2808
+ // reloading during initialize().
2809
+ serverId: session.serverId,
2810
+ serverName: session.serverName,
2811
+ serverUrl: session.serverUrl,
2812
+ callbackUrl: session.callbackUrl,
2813
+ // NOTE: transportType is intentionally omitted here.
2814
+ // The session's stored transportType is a placeholder ('streamable_http')
2815
+ // set before transport negotiation. Omitting it lets MCPClient auto-negotiate
2816
+ // (try streamable_http → SSE fallback), which is critical for servers like
2817
+ // Neon that only support SSE transport.
2818
+ headers: session.headers
2775
2819
  });
2776
2820
  client.onConnectionEvent((event) => this.emitConnectionEvent(event));
2777
2821
  await client.finishAuth(code);
@@ -3840,6 +3884,7 @@ var ToolIndex = class _ToolIndex {
3840
3884
  name: tool.name,
3841
3885
  description: tool.description ?? "",
3842
3886
  serverName: tool.serverName,
3887
+ serverId: tool.serverId,
3843
3888
  sessionId: tool.sessionId,
3844
3889
  estimatedTokens
3845
3890
  });
@@ -3902,12 +3947,50 @@ var ToolIndex = class _ToolIndex {
3902
3947
  */
3903
3948
  async search(query, topK = 5) {
3904
3949
  if (this.tools.size === 0) return [];
3905
- const queryLower = query.toLowerCase();
3906
- const queryTokens = this.tokenize(queryLower);
3950
+ const queryLower = query.toLowerCase().trim();
3951
+ const exactMatches = [...this.toolSummaries.values()].filter(
3952
+ (summary) => summary.name.toLowerCase() === queryLower
3953
+ );
3954
+ if (exactMatches.length > 0) {
3955
+ return exactMatches.slice(0, topK);
3956
+ }
3957
+ if (queryLower.startsWith("mcp__") && queryLower.length > 5) {
3958
+ const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower)).slice(0, topK);
3959
+ if (prefixMatches.length > 0) return prefixMatches;
3960
+ }
3961
+ const queryTermsRaw = queryLower.split(/\s+/).filter((t) => t.length > 0);
3962
+ const requiredTerms = [];
3963
+ const optionalTerms = [];
3964
+ for (const term of queryTermsRaw) {
3965
+ if (term.startsWith("+") && term.length > 1) {
3966
+ requiredTerms.push(term.slice(1));
3967
+ } else {
3968
+ optionalTerms.push(term);
3969
+ }
3970
+ }
3971
+ const allScoringTerms = requiredTerms.length > 0 ? [...requiredTerms, ...optionalTerms] : queryTermsRaw;
3972
+ const normalizedQueryText = allScoringTerms.join(" ").trim();
3973
+ const queryTokens = this.tokenize(allScoringTerms.join(" "));
3974
+ const candidateKeys = /* @__PURE__ */ new Set();
3975
+ for (const docKey of this.toolSummaries.keys()) {
3976
+ if (requiredTerms.length > 0) {
3977
+ const text = this.searchTexts.get(docKey) || "";
3978
+ const summary = this.toolSummaries.get(docKey);
3979
+ const nameLower = summary.name.toLowerCase();
3980
+ const matchesAll = requiredTerms.every(
3981
+ (term) => text.includes(term) || nameLower.includes(term)
3982
+ );
3983
+ if (!matchesAll) continue;
3984
+ }
3985
+ candidateKeys.add(docKey);
3986
+ }
3907
3987
  const keywordScores = /* @__PURE__ */ new Map();
3908
3988
  const k1 = 1.2;
3909
3989
  const b = 0.75;
3910
- for (const [docKey, docTf] of this.tfVectors) {
3990
+ for (const docKey of candidateKeys) {
3991
+ const docTf = this.tfVectors.get(docKey);
3992
+ if (!docTf) continue;
3993
+ const summary = this.toolSummaries.get(docKey);
3911
3994
  let score = 0;
3912
3995
  const docLen = this.docLengths.get(docKey) ?? 0;
3913
3996
  for (const tok of queryTokens) {
@@ -3918,16 +4001,31 @@ var ToolIndex = class _ToolIndex {
3918
4001
  const denominator = tfVal + k1 * (1 - b + b * (docLen / this.avgDocLength));
3919
4002
  score += idf * (numerator / denominator);
3920
4003
  }
3921
- keywordScores.set(docKey, score);
4004
+ const serverLower = (summary.serverName || summary.serverId || "").toLowerCase();
4005
+ const toolLower = summary.name.toLowerCase();
4006
+ for (const term of allScoringTerms) {
4007
+ if (serverLower.includes(term)) {
4008
+ score += 10;
4009
+ }
4010
+ if (toolLower.includes(term)) {
4011
+ score += 5;
4012
+ }
4013
+ }
4014
+ if (score > 0) {
4015
+ keywordScores.set(docKey, score);
4016
+ }
3922
4017
  }
3923
4018
  let embeddingScores = null;
3924
4019
  if (this.options.embedFn && this.embeddings.size > 0) {
3925
4020
  try {
3926
- const [queryEmbedding] = await this.options.embedFn([queryLower]);
4021
+ const [queryEmbedding] = await this.options.embedFn([normalizedQueryText]);
3927
4022
  if (queryEmbedding) {
3928
4023
  embeddingScores = /* @__PURE__ */ new Map();
3929
- for (const [docKey, vec] of this.embeddings) {
3930
- embeddingScores.set(docKey, this.cosineSimilarity(queryEmbedding, vec));
4024
+ for (const docKey of candidateKeys) {
4025
+ const vec = this.embeddings.get(docKey);
4026
+ if (vec) {
4027
+ embeddingScores.set(docKey, this.cosineSimilarity(queryEmbedding, vec));
4028
+ }
3931
4029
  }
3932
4030
  }
3933
4031
  } catch {
@@ -3935,7 +4033,7 @@ var ToolIndex = class _ToolIndex {
3935
4033
  }
3936
4034
  const kw = this.options.keywordWeight;
3937
4035
  const finalScores = [];
3938
- for (const docKey of this.toolSummaries.keys()) {
4036
+ for (const docKey of candidateKeys) {
3939
4037
  const kwScore = keywordScores.get(docKey) ?? 0;
3940
4038
  const embScore = embeddingScores?.get(docKey) ?? 0;
3941
4039
  const score = embeddingScores ? kw * kwScore + (1 - kw) * embScore : kwScore;
@@ -3993,7 +4091,7 @@ var ToolIndex = class _ToolIndex {
3993
4091
  getTool(name, namespace) {
3994
4092
  const list = this.tools.get(name) ?? [];
3995
4093
  if (!namespace) return list;
3996
- return list.filter((t) => t.sessionId === namespace || t.serverName === namespace);
4094
+ return list.filter((t) => t.sessionId === namespace || t.serverId === namespace);
3997
4095
  }
3998
4096
  /** All indexed tool names. */
3999
4097
  getToolNames() {
@@ -4053,7 +4151,7 @@ var ToolIndex = class _ToolIndex {
4053
4151
  return parts.join(" ");
4054
4152
  }
4055
4153
  getDocumentKey(tool) {
4056
- return `${tool.sessionId}::${tool.serverName}::${tool.name}`;
4154
+ return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
4057
4155
  }
4058
4156
  /** Simple whitespace + camelCase + snake_case tokenizer. */
4059
4157
  tokenize(text) {
@@ -4139,13 +4237,13 @@ var SchemaCompressor = class _SchemaCompressor {
4139
4237
  function createSearchToolDefinition() {
4140
4238
  return {
4141
4239
  name: "mcp_search_tool_bm25",
4142
- description: 'Search the catalog of available tools using BM25 natural language ranking. Returns tool names, descriptions, and server info. Use this FIRST to find relevant tools before calling them. Example queries: "database query", "send email", "github pull request".',
4240
+ 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',
4143
4241
  inputSchema: {
4144
4242
  type: "object",
4145
4243
  properties: {
4146
4244
  query: {
4147
4245
  type: "string",
4148
- description: "Natural language description of the capability you need."
4246
+ description: 'Query to find tools. Use "select:<tool_name>" for direct selection, or keywords to search. Prefix keywords with + to require them.'
4149
4247
  },
4150
4248
  limit: {
4151
4249
  type: "number",
@@ -4187,9 +4285,9 @@ function createGetSchemaToolDefinition() {
4187
4285
  type: "string",
4188
4286
  description: "The exact tool name returned by mcp_search_tool_bm25."
4189
4287
  },
4190
- serverName: {
4288
+ serverId: {
4191
4289
  type: "string",
4192
- description: "Optional: The server name provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4290
+ description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4193
4291
  }
4194
4292
  },
4195
4293
  required: ["toolName"]
@@ -4207,9 +4305,9 @@ function createExecuteToolDefinition() {
4207
4305
  type: "string",
4208
4306
  description: "The exact tool name from mcp_search_tool_bm25 results."
4209
4307
  },
4210
- serverName: {
4308
+ serverId: {
4211
4309
  type: "string",
4212
- description: "Optional: The server name provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4310
+ description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4213
4311
  },
4214
4312
  args: {
4215
4313
  type: "object",
@@ -4239,9 +4337,43 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4239
4337
  case "mcp_search_tool_bm25": {
4240
4338
  const query = String(args.query ?? "");
4241
4339
  const limit = Math.min(Number(args.limit) || 5, 20);
4340
+ const selectMatch = query.match(/^select:(.+)$/i);
4341
+ if (selectMatch) {
4342
+ const requested = selectMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
4343
+ const found = [];
4344
+ const errors = [];
4345
+ for (const requestedToolName of requested) {
4346
+ const { tool, error } = resolveToolSchema(requestedToolName);
4347
+ if (error) {
4348
+ const errorMsg = error.content[0]?.type === "text" ? error.content[0].text : "Unknown error";
4349
+ errors.push(`- **${requestedToolName}**: ${errorMsg}`);
4350
+ } else if (tool) {
4351
+ found.push(tool);
4352
+ } else {
4353
+ errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tool_bm25.`);
4354
+ }
4355
+ }
4356
+ const lines = [];
4357
+ if (found.length > 0) {
4358
+ lines.push(...found.map(
4359
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4360
+ ${t.description}`
4361
+ ));
4362
+ }
4363
+ if (errors.length > 0) {
4364
+ if (lines.length > 0) lines.push("");
4365
+ lines.push("Errors resolving some tools:");
4366
+ lines.push(...errors);
4367
+ }
4368
+ const text2 = lines.length > 0 ? lines.join("\n") : `No tools found matching select query: ${requested.join(", ")}`;
4369
+ return {
4370
+ content: [{ type: "text", text: text2 }],
4371
+ isError: found.length === 0
4372
+ };
4373
+ }
4242
4374
  const results = await router.searchTools(query, limit);
4243
4375
  const text = results.length === 0 ? "No tools found matching your query. Try different keywords." : results.map(
4244
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName})
4376
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4245
4377
  ${t.description}
4246
4378
  Estimated tokens: ${t.estimatedTokens}`
4247
4379
  ).join("\n");
@@ -4255,7 +4387,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4255
4387
  const limit = Math.min(Number(args.limit) || 5, 20);
4256
4388
  const results = await router.searchToolsRegex(pattern, limit);
4257
4389
  const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : results.map(
4258
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName})
4390
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4259
4391
  ${t.description}
4260
4392
  Estimated tokens: ${t.estimatedTokens}`
4261
4393
  ).join("\n");
@@ -4266,7 +4398,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4266
4398
  }
4267
4399
  case "mcp_get_tool_schema": {
4268
4400
  const name = String(args.toolName ?? "");
4269
- const namespace = String(args.serverName ?? "") || void 0;
4401
+ const namespace = String(args.serverId ?? "") || void 0;
4270
4402
  const { tool, error } = resolveToolSchema(name, namespace);
4271
4403
  if (error) {
4272
4404
  return error;
@@ -4294,7 +4426,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4294
4426
  }
4295
4427
  case "mcp_execute_tool": {
4296
4428
  const targetToolName = String(args.toolName ?? "");
4297
- const namespace = String(args.serverName ?? "") || void 0;
4429
+ const namespace = String(args.serverId ?? "") || void 0;
4298
4430
  const toolArgs = args.args ?? {};
4299
4431
  if (!targetToolName) {
4300
4432
  return {
@@ -4443,9 +4575,9 @@ var ToolRouter = class {
4443
4575
  const matches = this.index.getTool(toolName, namespace);
4444
4576
  if (matches.length === 0) return void 0;
4445
4577
  if (matches.length > 1) {
4446
- const servers = matches.map((m) => m.serverName).join(", ");
4578
+ const servers = matches.map((m) => m.serverId).join(", ");
4447
4579
  throw new Error(
4448
- `Tool "${toolName}" is provided by multiple servers: [${servers}]. Please specify the desired "serverName" as a namespace.`
4580
+ `Tool "${toolName}" is provided by multiple servers: [${servers}]. Please specify the desired "serverId" as a namespace.`
4449
4581
  );
4450
4582
  }
4451
4583
  return matches[0];
@@ -4556,6 +4688,7 @@ var ToolRouter = class {
4556
4688
  for (const tool of tools) {
4557
4689
  result.push({
4558
4690
  ...tool,
4691
+ serverId,
4559
4692
  serverName,
4560
4693
  sessionId
4561
4694
  });
@@ -4589,16 +4722,16 @@ var ToolRouter = class {
4589
4722
  } else {
4590
4723
  const serverTools = /* @__PURE__ */ new Map();
4591
4724
  for (const tool of this.allTools) {
4592
- const group = tool.serverName;
4725
+ const group = tool.serverId;
4593
4726
  if (!serverTools.has(group)) {
4594
4727
  serverTools.set(group, []);
4595
4728
  }
4596
4729
  serverTools.get(group).push(tool.name);
4597
4730
  }
4598
- for (const [serverName, tools] of serverTools) {
4599
- this.groupsMap.set(serverName, {
4731
+ for (const [serverId, tools] of serverTools) {
4732
+ this.groupsMap.set(serverId, {
4600
4733
  tools,
4601
- active: this.activeGroups.size === 0 || this.activeGroups.has(serverName)
4734
+ active: this.activeGroups.size === 0 || this.activeGroups.has(serverId)
4602
4735
  });
4603
4736
  }
4604
4737
  }