@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.js CHANGED
@@ -3981,6 +3981,7 @@ var ToolIndex = class _ToolIndex {
3981
3981
  name: tool.name,
3982
3982
  description: tool.description ?? "",
3983
3983
  serverName: tool.serverName,
3984
+ serverId: tool.serverId,
3984
3985
  sessionId: tool.sessionId,
3985
3986
  estimatedTokens
3986
3987
  });
@@ -4043,12 +4044,50 @@ var ToolIndex = class _ToolIndex {
4043
4044
  */
4044
4045
  async search(query, topK = 5) {
4045
4046
  if (this.tools.size === 0) return [];
4046
- const queryLower = query.toLowerCase();
4047
- const queryTokens = this.tokenize(queryLower);
4047
+ const queryLower = query.toLowerCase().trim();
4048
+ const exactMatches = [...this.toolSummaries.values()].filter(
4049
+ (summary) => summary.name.toLowerCase() === queryLower
4050
+ );
4051
+ if (exactMatches.length > 0) {
4052
+ return exactMatches.slice(0, topK);
4053
+ }
4054
+ if (queryLower.startsWith("mcp__") && queryLower.length > 5) {
4055
+ const prefixMatches = [...this.toolSummaries.values()].filter((t) => t.name.toLowerCase().startsWith(queryLower)).slice(0, topK);
4056
+ if (prefixMatches.length > 0) return prefixMatches;
4057
+ }
4058
+ const queryTermsRaw = queryLower.split(/\s+/).filter((t) => t.length > 0);
4059
+ const requiredTerms = [];
4060
+ const optionalTerms = [];
4061
+ for (const term of queryTermsRaw) {
4062
+ if (term.startsWith("+") && term.length > 1) {
4063
+ requiredTerms.push(term.slice(1));
4064
+ } else {
4065
+ optionalTerms.push(term);
4066
+ }
4067
+ }
4068
+ const allScoringTerms = requiredTerms.length > 0 ? [...requiredTerms, ...optionalTerms] : queryTermsRaw;
4069
+ const normalizedQueryText = allScoringTerms.join(" ").trim();
4070
+ const queryTokens = this.tokenize(allScoringTerms.join(" "));
4071
+ const candidateKeys = /* @__PURE__ */ new Set();
4072
+ for (const docKey of this.toolSummaries.keys()) {
4073
+ if (requiredTerms.length > 0) {
4074
+ const text = this.searchTexts.get(docKey) || "";
4075
+ const summary = this.toolSummaries.get(docKey);
4076
+ const nameLower = summary.name.toLowerCase();
4077
+ const matchesAll = requiredTerms.every(
4078
+ (term) => text.includes(term) || nameLower.includes(term)
4079
+ );
4080
+ if (!matchesAll) continue;
4081
+ }
4082
+ candidateKeys.add(docKey);
4083
+ }
4048
4084
  const keywordScores = /* @__PURE__ */ new Map();
4049
4085
  const k1 = 1.2;
4050
4086
  const b = 0.75;
4051
- for (const [docKey, docTf] of this.tfVectors) {
4087
+ for (const docKey of candidateKeys) {
4088
+ const docTf = this.tfVectors.get(docKey);
4089
+ if (!docTf) continue;
4090
+ const summary = this.toolSummaries.get(docKey);
4052
4091
  let score = 0;
4053
4092
  const docLen = this.docLengths.get(docKey) ?? 0;
4054
4093
  for (const tok of queryTokens) {
@@ -4059,16 +4098,31 @@ var ToolIndex = class _ToolIndex {
4059
4098
  const denominator = tfVal + k1 * (1 - b + b * (docLen / this.avgDocLength));
4060
4099
  score += idf * (numerator / denominator);
4061
4100
  }
4062
- keywordScores.set(docKey, score);
4101
+ const serverLower = (summary.serverName || summary.serverId || "").toLowerCase();
4102
+ const toolLower = summary.name.toLowerCase();
4103
+ for (const term of allScoringTerms) {
4104
+ if (serverLower.includes(term)) {
4105
+ score += 10;
4106
+ }
4107
+ if (toolLower.includes(term)) {
4108
+ score += 5;
4109
+ }
4110
+ }
4111
+ if (score > 0) {
4112
+ keywordScores.set(docKey, score);
4113
+ }
4063
4114
  }
4064
4115
  let embeddingScores = null;
4065
4116
  if (this.options.embedFn && this.embeddings.size > 0) {
4066
4117
  try {
4067
- const [queryEmbedding] = await this.options.embedFn([queryLower]);
4118
+ const [queryEmbedding] = await this.options.embedFn([normalizedQueryText]);
4068
4119
  if (queryEmbedding) {
4069
4120
  embeddingScores = /* @__PURE__ */ new Map();
4070
- for (const [docKey, vec] of this.embeddings) {
4071
- embeddingScores.set(docKey, this.cosineSimilarity(queryEmbedding, vec));
4121
+ for (const docKey of candidateKeys) {
4122
+ const vec = this.embeddings.get(docKey);
4123
+ if (vec) {
4124
+ embeddingScores.set(docKey, this.cosineSimilarity(queryEmbedding, vec));
4125
+ }
4072
4126
  }
4073
4127
  }
4074
4128
  } catch {
@@ -4076,7 +4130,7 @@ var ToolIndex = class _ToolIndex {
4076
4130
  }
4077
4131
  const kw = this.options.keywordWeight;
4078
4132
  const finalScores = [];
4079
- for (const docKey of this.toolSummaries.keys()) {
4133
+ for (const docKey of candidateKeys) {
4080
4134
  const kwScore = keywordScores.get(docKey) ?? 0;
4081
4135
  const embScore = embeddingScores?.get(docKey) ?? 0;
4082
4136
  const score = embeddingScores ? kw * kwScore + (1 - kw) * embScore : kwScore;
@@ -4134,7 +4188,7 @@ var ToolIndex = class _ToolIndex {
4134
4188
  getTool(name, namespace) {
4135
4189
  const list = this.tools.get(name) ?? [];
4136
4190
  if (!namespace) return list;
4137
- return list.filter((t) => t.sessionId === namespace || t.serverName === namespace);
4191
+ return list.filter((t) => t.sessionId === namespace || t.serverId === namespace);
4138
4192
  }
4139
4193
  /** All indexed tool names. */
4140
4194
  getToolNames() {
@@ -4194,7 +4248,7 @@ var ToolIndex = class _ToolIndex {
4194
4248
  return parts.join(" ");
4195
4249
  }
4196
4250
  getDocumentKey(tool) {
4197
- return `${tool.sessionId}::${tool.serverName}::${tool.name}`;
4251
+ return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
4198
4252
  }
4199
4253
  /** Simple whitespace + camelCase + snake_case tokenizer. */
4200
4254
  tokenize(text) {
@@ -4282,13 +4336,13 @@ init_cjs_shims();
4282
4336
  function createSearchToolDefinition() {
4283
4337
  return {
4284
4338
  name: "mcp_search_tool_bm25",
4285
- 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".',
4339
+ 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',
4286
4340
  inputSchema: {
4287
4341
  type: "object",
4288
4342
  properties: {
4289
4343
  query: {
4290
4344
  type: "string",
4291
- description: "Natural language description of the capability you need."
4345
+ description: 'Query to find tools. Use "select:<tool_name>" for direct selection, or keywords to search. Prefix keywords with + to require them.'
4292
4346
  },
4293
4347
  limit: {
4294
4348
  type: "number",
@@ -4322,7 +4376,7 @@ function createRegexSearchToolDefinition() {
4322
4376
  function createGetSchemaToolDefinition() {
4323
4377
  return {
4324
4378
  name: "mcp_get_tool_schema",
4325
- 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.",
4379
+ 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.",
4326
4380
  inputSchema: {
4327
4381
  type: "object",
4328
4382
  properties: {
@@ -4330,9 +4384,9 @@ function createGetSchemaToolDefinition() {
4330
4384
  type: "string",
4331
4385
  description: "The exact tool name returned by mcp_search_tool_bm25."
4332
4386
  },
4333
- serverName: {
4387
+ serverId: {
4334
4388
  type: "string",
4335
- description: "Optional: The server name provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4389
+ description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4336
4390
  }
4337
4391
  },
4338
4392
  required: ["toolName"]
@@ -4350,9 +4404,9 @@ function createExecuteToolDefinition() {
4350
4404
  type: "string",
4351
4405
  description: "The exact tool name from mcp_search_tool_bm25 results."
4352
4406
  },
4353
- serverName: {
4407
+ serverId: {
4354
4408
  type: "string",
4355
- description: "Optional: The server name provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4409
+ description: "Optional: The server ID provided in mcp_search_tool_bm25. Required if multiple tools have the same name."
4356
4410
  },
4357
4411
  args: {
4358
4412
  type: "object",
@@ -4382,9 +4436,43 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4382
4436
  case "mcp_search_tool_bm25": {
4383
4437
  const query = String(args.query ?? "");
4384
4438
  const limit = Math.min(Number(args.limit) || 5, 20);
4439
+ const selectMatch = query.match(/^select:(.+)$/i);
4440
+ if (selectMatch) {
4441
+ const requested = selectMatch[1].split(",").map((s) => s.trim()).filter(Boolean);
4442
+ const found = [];
4443
+ const errors = [];
4444
+ for (const requestedToolName of requested) {
4445
+ const { tool, error } = resolveToolSchema(requestedToolName);
4446
+ if (error) {
4447
+ const errorMsg = error.content[0]?.type === "text" ? error.content[0].text : "Unknown error";
4448
+ errors.push(`- **${requestedToolName}**: ${errorMsg}`);
4449
+ } else if (tool) {
4450
+ found.push(tool);
4451
+ } else {
4452
+ errors.push(`- **${requestedToolName}**: Tool not found. Try searching with mcp_search_tool_bm25.`);
4453
+ }
4454
+ }
4455
+ const lines = [];
4456
+ if (found.length > 0) {
4457
+ lines.push(...found.map(
4458
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4459
+ ${t.description}`
4460
+ ));
4461
+ }
4462
+ if (errors.length > 0) {
4463
+ if (lines.length > 0) lines.push("");
4464
+ lines.push("Errors resolving some tools:");
4465
+ lines.push(...errors);
4466
+ }
4467
+ const text2 = lines.length > 0 ? lines.join("\n") : `No tools found matching select query: ${requested.join(", ")}`;
4468
+ return {
4469
+ content: [{ type: "text", text: text2 }],
4470
+ isError: found.length === 0
4471
+ };
4472
+ }
4385
4473
  const results = await router.searchTools(query, limit);
4386
4474
  const text = results.length === 0 ? "No tools found matching your query. Try different keywords." : results.map(
4387
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName})
4475
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4388
4476
  ${t.description}
4389
4477
  Estimated tokens: ${t.estimatedTokens}`
4390
4478
  ).join("\n");
@@ -4398,7 +4486,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4398
4486
  const limit = Math.min(Number(args.limit) || 5, 20);
4399
4487
  const results = await router.searchToolsRegex(pattern, limit);
4400
4488
  const text = results.length === 0 ? "No tools matched your regex pattern. Try a broader pattern." : results.map(
4401
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName})
4489
+ (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
4402
4490
  ${t.description}
4403
4491
  Estimated tokens: ${t.estimatedTokens}`
4404
4492
  ).join("\n");
@@ -4409,7 +4497,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4409
4497
  }
4410
4498
  case "mcp_get_tool_schema": {
4411
4499
  const name = String(args.toolName ?? "");
4412
- const namespace = String(args.serverName ?? "") || void 0;
4500
+ const namespace = String(args.serverId ?? "") || void 0;
4413
4501
  const { tool, error } = resolveToolSchema(name, namespace);
4414
4502
  if (error) {
4415
4503
  return error;
@@ -4428,7 +4516,13 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4428
4516
  const schema = {
4429
4517
  name: tool.name,
4430
4518
  description: tool.description,
4431
- inputSchema: tool.inputSchema
4519
+ inputSchema: tool.inputSchema,
4520
+ executionInstructions: {
4521
+ nextTool: "mcp_execute_tool",
4522
+ toolName: tool.name,
4523
+ serverId: tool.serverId,
4524
+ 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."
4525
+ }
4432
4526
  };
4433
4527
  return {
4434
4528
  content: [{ type: "text", text: JSON.stringify(schema, null, 2) }],
@@ -4437,7 +4531,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
4437
4531
  }
4438
4532
  case "mcp_execute_tool": {
4439
4533
  const targetToolName = String(args.toolName ?? "");
4440
- const namespace = String(args.serverName ?? "") || void 0;
4534
+ const namespace = String(args.serverId ?? "") || void 0;
4441
4535
  const toolArgs = args.args ?? {};
4442
4536
  if (!targetToolName) {
4443
4537
  return {
@@ -4586,9 +4680,9 @@ var ToolRouter = class {
4586
4680
  const matches = this.index.getTool(toolName, namespace);
4587
4681
  if (matches.length === 0) return void 0;
4588
4682
  if (matches.length > 1) {
4589
- const servers = matches.map((m) => m.serverName).join(", ");
4683
+ const servers = matches.map((m) => m.serverId).join(", ");
4590
4684
  throw new Error(
4591
- `Tool "${toolName}" is provided by multiple servers: [${servers}]. Please specify the desired "serverName" as a namespace.`
4685
+ `Tool "${toolName}" is provided by multiple servers: [${servers}]. Please specify the desired "serverId" as a namespace.`
4592
4686
  );
4593
4687
  }
4594
4688
  return matches[0];
@@ -4699,6 +4793,7 @@ var ToolRouter = class {
4699
4793
  for (const tool of tools) {
4700
4794
  result.push({
4701
4795
  ...tool,
4796
+ serverId,
4702
4797
  serverName,
4703
4798
  sessionId
4704
4799
  });
@@ -4732,16 +4827,16 @@ var ToolRouter = class {
4732
4827
  } else {
4733
4828
  const serverTools = /* @__PURE__ */ new Map();
4734
4829
  for (const tool of this.allTools) {
4735
- const group = tool.serverName;
4830
+ const group = tool.serverId;
4736
4831
  if (!serverTools.has(group)) {
4737
4832
  serverTools.set(group, []);
4738
4833
  }
4739
4834
  serverTools.get(group).push(tool.name);
4740
4835
  }
4741
- for (const [serverName, tools] of serverTools) {
4742
- this.groupsMap.set(serverName, {
4836
+ for (const [serverId, tools] of serverTools) {
4837
+ this.groupsMap.set(serverId, {
4743
4838
  tools,
4744
- active: this.activeGroups.size === 0 || this.activeGroups.has(serverName)
4839
+ active: this.activeGroups.size === 0 || this.activeGroups.has(serverId)
4745
4840
  });
4746
4841
  }
4747
4842
  }