@mcp-ts/sdk 1.5.1 → 1.5.3

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 (61) hide show
  1. package/README.md +89 -27
  2. package/dist/adapters/agui-adapter.d.mts +1 -1
  3. package/dist/adapters/agui-adapter.d.ts +1 -1
  4. package/dist/adapters/agui-adapter.js +50 -10
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +50 -10
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +5 -1
  9. package/dist/adapters/agui-middleware.d.ts +5 -1
  10. package/dist/adapters/agui-middleware.js +116 -49
  11. package/dist/adapters/agui-middleware.js.map +1 -1
  12. package/dist/adapters/agui-middleware.mjs +117 -50
  13. package/dist/adapters/agui-middleware.mjs.map +1 -1
  14. package/dist/adapters/ai-adapter.d.mts +1 -1
  15. package/dist/adapters/ai-adapter.d.ts +1 -1
  16. package/dist/adapters/ai-adapter.js +49 -9
  17. package/dist/adapters/ai-adapter.js.map +1 -1
  18. package/dist/adapters/ai-adapter.mjs +49 -9
  19. package/dist/adapters/ai-adapter.mjs.map +1 -1
  20. package/dist/adapters/langchain-adapter.d.mts +1 -1
  21. package/dist/adapters/langchain-adapter.d.ts +1 -1
  22. package/dist/adapters/langchain-adapter.js +49 -9
  23. package/dist/adapters/langchain-adapter.js.map +1 -1
  24. package/dist/adapters/langchain-adapter.mjs +49 -9
  25. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  26. package/dist/client/react.d.mts +10 -0
  27. package/dist/client/react.d.ts +10 -0
  28. package/dist/client/react.js +23 -0
  29. package/dist/client/react.js.map +1 -1
  30. package/dist/client/react.mjs +23 -0
  31. package/dist/client/react.mjs.map +1 -1
  32. package/dist/client/vue.d.mts +10 -0
  33. package/dist/client/vue.d.ts +10 -0
  34. package/dist/client/vue.js +17 -0
  35. package/dist/client/vue.js.map +1 -1
  36. package/dist/client/vue.mjs +17 -0
  37. package/dist/client/vue.mjs.map +1 -1
  38. package/dist/index.d.mts +1 -1
  39. package/dist/index.d.ts +1 -1
  40. package/dist/index.js +123 -28
  41. package/dist/index.js.map +1 -1
  42. package/dist/index.mjs +123 -28
  43. package/dist/index.mjs.map +1 -1
  44. package/dist/shared/index.d.mts +2 -2
  45. package/dist/shared/index.d.ts +2 -2
  46. package/dist/shared/index.js +123 -28
  47. package/dist/shared/index.js.map +1 -1
  48. package/dist/shared/index.mjs +123 -28
  49. package/dist/shared/index.mjs.map +1 -1
  50. package/dist/{tool-router-XnWVxPzv.d.mts → tool-router-DK0RJblO.d.mts} +3 -0
  51. package/dist/{tool-router-Bo8qZbsD.d.ts → tool-router-DsKhRmJm.d.ts} +3 -0
  52. package/package.json +3 -3
  53. package/src/adapters/agui-adapter.ts +7 -7
  54. package/src/adapters/agui-middleware.ts +163 -59
  55. package/src/adapters/ai-adapter.ts +5 -5
  56. package/src/adapters/langchain-adapter.ts +5 -5
  57. package/src/client/react/use-mcp.ts +48 -0
  58. package/src/client/vue/use-mcp.ts +42 -0
  59. package/src/shared/meta-tools.ts +73 -15
  60. package/src/shared/tool-index.ts +85 -12
  61. package/src/shared/tool-router.ts +8 -7
package/dist/index.mjs CHANGED
@@ -3884,6 +3884,7 @@ var ToolIndex = class _ToolIndex {
3884
3884
  name: tool.name,
3885
3885
  description: tool.description ?? "",
3886
3886
  serverName: tool.serverName,
3887
+ serverId: tool.serverId,
3887
3888
  sessionId: tool.sessionId,
3888
3889
  estimatedTokens
3889
3890
  });
@@ -3946,12 +3947,50 @@ var ToolIndex = class _ToolIndex {
3946
3947
  */
3947
3948
  async search(query, topK = 5) {
3948
3949
  if (this.tools.size === 0) return [];
3949
- const queryLower = query.toLowerCase();
3950
- 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
+ }
3951
3987
  const keywordScores = /* @__PURE__ */ new Map();
3952
3988
  const k1 = 1.2;
3953
3989
  const b = 0.75;
3954
- 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);
3955
3994
  let score = 0;
3956
3995
  const docLen = this.docLengths.get(docKey) ?? 0;
3957
3996
  for (const tok of queryTokens) {
@@ -3962,16 +4001,31 @@ var ToolIndex = class _ToolIndex {
3962
4001
  const denominator = tfVal + k1 * (1 - b + b * (docLen / this.avgDocLength));
3963
4002
  score += idf * (numerator / denominator);
3964
4003
  }
3965
- 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
+ }
3966
4017
  }
3967
4018
  let embeddingScores = null;
3968
4019
  if (this.options.embedFn && this.embeddings.size > 0) {
3969
4020
  try {
3970
- const [queryEmbedding] = await this.options.embedFn([queryLower]);
4021
+ const [queryEmbedding] = await this.options.embedFn([normalizedQueryText]);
3971
4022
  if (queryEmbedding) {
3972
4023
  embeddingScores = /* @__PURE__ */ new Map();
3973
- for (const [docKey, vec] of this.embeddings) {
3974
- 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
+ }
3975
4029
  }
3976
4030
  }
3977
4031
  } catch {
@@ -3979,7 +4033,7 @@ var ToolIndex = class _ToolIndex {
3979
4033
  }
3980
4034
  const kw = this.options.keywordWeight;
3981
4035
  const finalScores = [];
3982
- for (const docKey of this.toolSummaries.keys()) {
4036
+ for (const docKey of candidateKeys) {
3983
4037
  const kwScore = keywordScores.get(docKey) ?? 0;
3984
4038
  const embScore = embeddingScores?.get(docKey) ?? 0;
3985
4039
  const score = embeddingScores ? kw * kwScore + (1 - kw) * embScore : kwScore;
@@ -4037,7 +4091,7 @@ var ToolIndex = class _ToolIndex {
4037
4091
  getTool(name, namespace) {
4038
4092
  const list = this.tools.get(name) ?? [];
4039
4093
  if (!namespace) return list;
4040
- return list.filter((t) => t.sessionId === namespace || t.serverName === namespace);
4094
+ return list.filter((t) => t.sessionId === namespace || t.serverId === namespace);
4041
4095
  }
4042
4096
  /** All indexed tool names. */
4043
4097
  getToolNames() {
@@ -4097,7 +4151,7 @@ var ToolIndex = class _ToolIndex {
4097
4151
  return parts.join(" ");
4098
4152
  }
4099
4153
  getDocumentKey(tool) {
4100
- return `${tool.sessionId}::${tool.serverName}::${tool.name}`;
4154
+ return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
4101
4155
  }
4102
4156
  /** Simple whitespace + camelCase + snake_case tokenizer. */
4103
4157
  tokenize(text) {
@@ -4183,13 +4237,13 @@ var SchemaCompressor = class _SchemaCompressor {
4183
4237
  function createSearchToolDefinition() {
4184
4238
  return {
4185
4239
  name: "mcp_search_tool_bm25",
4186
- 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',
4187
4241
  inputSchema: {
4188
4242
  type: "object",
4189
4243
  properties: {
4190
4244
  query: {
4191
4245
  type: "string",
4192
- 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.'
4193
4247
  },
4194
4248
  limit: {
4195
4249
  type: "number",
@@ -4223,7 +4277,7 @@ function createRegexSearchToolDefinition() {
4223
4277
  function createGetSchemaToolDefinition() {
4224
4278
  return {
4225
4279
  name: "mcp_get_tool_schema",
4226
- 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.",
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.",
4227
4281
  inputSchema: {
4228
4282
  type: "object",
4229
4283
  properties: {
@@ -4231,9 +4285,9 @@ function createGetSchemaToolDefinition() {
4231
4285
  type: "string",
4232
4286
  description: "The exact tool name returned by mcp_search_tool_bm25."
4233
4287
  },
4234
- serverName: {
4288
+ serverId: {
4235
4289
  type: "string",
4236
- 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."
4237
4291
  }
4238
4292
  },
4239
4293
  required: ["toolName"]
@@ -4251,9 +4305,9 @@ function createExecuteToolDefinition() {
4251
4305
  type: "string",
4252
4306
  description: "The exact tool name from mcp_search_tool_bm25 results."
4253
4307
  },
4254
- serverName: {
4308
+ serverId: {
4255
4309
  type: "string",
4256
- 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."
4257
4311
  },
4258
4312
  args: {
4259
4313
  type: "object",
@@ -4283,9 +4337,43 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4283
4337
  case "mcp_search_tool_bm25": {
4284
4338
  const query = String(args.query ?? "");
4285
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
+ }
4286
4374
  const results = await router.searchTools(query, limit);
4287
4375
  const text = results.length === 0 ? "No tools found matching your query. Try different keywords." : results.map(
4288
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName})
4376
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4289
4377
  ${t.description}
4290
4378
  Estimated tokens: ${t.estimatedTokens}`
4291
4379
  ).join("\n");
@@ -4299,7 +4387,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4299
4387
  const limit = Math.min(Number(args.limit) || 5, 20);
4300
4388
  const results = await router.searchToolsRegex(pattern, limit);
4301
4389
  const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : results.map(
4302
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName})
4390
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4303
4391
  ${t.description}
4304
4392
  Estimated tokens: ${t.estimatedTokens}`
4305
4393
  ).join("\n");
@@ -4310,7 +4398,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4310
4398
  }
4311
4399
  case "mcp_get_tool_schema": {
4312
4400
  const name = String(args.toolName ?? "");
4313
- const namespace = String(args.serverName ?? "") || void 0;
4401
+ const namespace = String(args.serverId ?? "") || void 0;
4314
4402
  const { tool, error } = resolveToolSchema(name, namespace);
4315
4403
  if (error) {
4316
4404
  return error;
@@ -4329,7 +4417,13 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4329
4417
  const schema = {
4330
4418
  name: tool.name,
4331
4419
  description: tool.description,
4332
- inputSchema: tool.inputSchema
4420
+ inputSchema: tool.inputSchema,
4421
+ executionInstructions: {
4422
+ nextTool: "mcp_execute_tool",
4423
+ toolName: tool.name,
4424
+ serverId: tool.serverId,
4425
+ note: "Do not call this discovered tool directly unless it was explicitly registered as a runtime tool. Execute it via mcp_execute_tool and pass these parameters inside args."
4426
+ }
4333
4427
  };
4334
4428
  return {
4335
4429
  content: [{ type: "text", text: JSON.stringify(schema, null, 2) }],
@@ -4338,7 +4432,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4338
4432
  }
4339
4433
  case "mcp_execute_tool": {
4340
4434
  const targetToolName = String(args.toolName ?? "");
4341
- const namespace = String(args.serverName ?? "") || void 0;
4435
+ const namespace = String(args.serverId ?? "") || void 0;
4342
4436
  const toolArgs = args.args ?? {};
4343
4437
  if (!targetToolName) {
4344
4438
  return {
@@ -4487,9 +4581,9 @@ var ToolRouter = class {
4487
4581
  const matches = this.index.getTool(toolName, namespace);
4488
4582
  if (matches.length === 0) return void 0;
4489
4583
  if (matches.length > 1) {
4490
- const servers = matches.map((m) => m.serverName).join(", ");
4584
+ const servers = matches.map((m) => m.serverId).join(", ");
4491
4585
  throw new Error(
4492
- `Tool "${toolName}" is provided by multiple servers: [${servers}]. Please specify the desired "serverName" as a namespace.`
4586
+ `Tool "${toolName}" is provided by multiple servers: [${servers}]. Please specify the desired "serverId" as a namespace.`
4493
4587
  );
4494
4588
  }
4495
4589
  return matches[0];
@@ -4600,6 +4694,7 @@ var ToolRouter = class {
4600
4694
  for (const tool of tools) {
4601
4695
  result.push({
4602
4696
  ...tool,
4697
+ serverId,
4603
4698
  serverName,
4604
4699
  sessionId
4605
4700
  });
@@ -4633,16 +4728,16 @@ var ToolRouter = class {
4633
4728
  } else {
4634
4729
  const serverTools = /* @__PURE__ */ new Map();
4635
4730
  for (const tool of this.allTools) {
4636
- const group = tool.serverName;
4731
+ const group = tool.serverId;
4637
4732
  if (!serverTools.has(group)) {
4638
4733
  serverTools.set(group, []);
4639
4734
  }
4640
4735
  serverTools.get(group).push(tool.name);
4641
4736
  }
4642
- for (const [serverName, tools] of serverTools) {
4643
- this.groupsMap.set(serverName, {
4737
+ for (const [serverId, tools] of serverTools) {
4738
+ this.groupsMap.set(serverId, {
4644
4739
  tools,
4645
- active: this.activeGroups.size === 0 || this.activeGroups.has(serverName)
4740
+ active: this.activeGroups.size === 0 || this.activeGroups.has(serverId)
4646
4741
  });
4647
4742
  }
4648
4743
  }