@mcp-ts/sdk 1.6.2 → 2.1.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 (113) hide show
  1. package/README.md +12 -6
  2. package/dist/adapters/agui-adapter.d.mts +3 -3
  3. package/dist/adapters/agui-adapter.d.ts +3 -3
  4. package/dist/adapters/agui-adapter.js +5 -5
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +5 -5
  7. package/dist/adapters/agui-adapter.mjs.map +1 -1
  8. package/dist/adapters/agui-middleware.d.mts +3 -3
  9. package/dist/adapters/agui-middleware.d.ts +3 -3
  10. package/dist/adapters/ai-adapter.d.mts +9 -3
  11. package/dist/adapters/ai-adapter.d.ts +9 -3
  12. package/dist/adapters/ai-adapter.js +21 -6
  13. package/dist/adapters/ai-adapter.js.map +1 -1
  14. package/dist/adapters/ai-adapter.mjs +21 -6
  15. package/dist/adapters/ai-adapter.mjs.map +1 -1
  16. package/dist/adapters/langchain-adapter.d.mts +3 -3
  17. package/dist/adapters/langchain-adapter.d.ts +3 -3
  18. package/dist/adapters/langchain-adapter.js +10 -6
  19. package/dist/adapters/langchain-adapter.js.map +1 -1
  20. package/dist/adapters/langchain-adapter.mjs +10 -6
  21. package/dist/adapters/langchain-adapter.mjs.map +1 -1
  22. package/dist/adapters/mastra-adapter.d.mts +1 -1
  23. package/dist/adapters/mastra-adapter.d.ts +1 -1
  24. package/dist/adapters/mastra-adapter.js +5 -1
  25. package/dist/adapters/mastra-adapter.js.map +1 -1
  26. package/dist/adapters/mastra-adapter.mjs +5 -1
  27. package/dist/adapters/mastra-adapter.mjs.map +1 -1
  28. package/dist/bin/mcp-ts.js +7 -1
  29. package/dist/bin/mcp-ts.js.map +1 -1
  30. package/dist/bin/mcp-ts.mjs +7 -1
  31. package/dist/bin/mcp-ts.mjs.map +1 -1
  32. package/dist/client/index.d.mts +2 -2
  33. package/dist/client/index.d.ts +2 -2
  34. package/dist/client/index.js +9 -13
  35. package/dist/client/index.js.map +1 -1
  36. package/dist/client/index.mjs +9 -13
  37. package/dist/client/index.mjs.map +1 -1
  38. package/dist/client/react.d.mts +7 -7
  39. package/dist/client/react.d.ts +7 -7
  40. package/dist/client/react.js +15 -19
  41. package/dist/client/react.js.map +1 -1
  42. package/dist/client/react.mjs +15 -19
  43. package/dist/client/react.mjs.map +1 -1
  44. package/dist/client/vue.d.mts +7 -7
  45. package/dist/client/vue.d.ts +7 -7
  46. package/dist/client/vue.js +14 -18
  47. package/dist/client/vue.js.map +1 -1
  48. package/dist/client/vue.mjs +14 -18
  49. package/dist/client/vue.mjs.map +1 -1
  50. package/dist/{index-bFL4ZF2N.d.mts → index-Cfjsme-a.d.mts} +5 -5
  51. package/dist/{index-DhA-OEAe.d.ts → index-CmjMd2ac.d.ts} +5 -5
  52. package/dist/index.d.mts +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +643 -374
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.mjs +642 -374
  57. package/dist/index.mjs.map +1 -1
  58. package/dist/{multi-session-client-CHE8QpVE.d.ts → multi-session-client-BYtguGJm.d.ts} +22 -22
  59. package/dist/{multi-session-client-CQsRbxYI.d.mts → multi-session-client-DYNe6az3.d.mts} +22 -22
  60. package/dist/server/index.d.mts +31 -34
  61. package/dist/server/index.d.ts +31 -34
  62. package/dist/server/index.js +531 -256
  63. package/dist/server/index.js.map +1 -1
  64. package/dist/server/index.mjs +530 -256
  65. package/dist/server/index.mjs.map +1 -1
  66. package/dist/shared/index.d.mts +7 -7
  67. package/dist/shared/index.d.ts +7 -7
  68. package/dist/shared/index.js +103 -105
  69. package/dist/shared/index.js.map +1 -1
  70. package/dist/shared/index.mjs +103 -105
  71. package/dist/shared/index.mjs.map +1 -1
  72. package/dist/{tool-router-BVaV1udm.d.mts → tool-router-BP8TT9mI.d.ts} +87 -73
  73. package/dist/{tool-router-Dh2804tM.d.ts → tool-router-BkQnso27.d.mts} +87 -73
  74. package/dist/{types-rIuN1CQi.d.mts → types-CxFaaZrM.d.mts} +6 -5
  75. package/dist/{types-rIuN1CQi.d.ts → types-CxFaaZrM.d.ts} +6 -5
  76. package/dist/{utils-0qmYrqoa.d.mts → utils-DELRKQPU.d.mts} +1 -1
  77. package/dist/{utils-0qmYrqoa.d.ts → utils-DELRKQPU.d.ts} +1 -1
  78. package/migrations/neon/20260513010000_install_mcp_sessions.sql +69 -0
  79. package/migrations/neon/20260513020000_add_session_cleanup_cron.sql +35 -0
  80. package/{supabase/migrations → migrations/supabase}/20260330195700_install_mcp_sessions.sql +7 -9
  81. package/package.json +14 -5
  82. package/src/adapters/ai-adapter.ts +30 -1
  83. package/src/adapters/langchain-adapter.ts +6 -2
  84. package/src/adapters/mastra-adapter.ts +6 -2
  85. package/src/bin/mcp-ts.ts +8 -1
  86. package/src/client/core/app-host.ts +1 -1
  87. package/src/client/core/sse-client.ts +12 -14
  88. package/src/client/core/types.ts +1 -1
  89. package/src/client/react/use-mcp-apps.tsx +1 -1
  90. package/src/client/react/use-mcp.ts +11 -11
  91. package/src/client/vue/use-mcp.ts +10 -10
  92. package/src/server/handlers/nextjs-handler.ts +18 -15
  93. package/src/server/handlers/sse-handler.ts +29 -29
  94. package/src/server/index.ts +1 -1
  95. package/src/server/mcp/multi-session-client.ts +17 -17
  96. package/src/server/mcp/oauth-client.ts +37 -37
  97. package/src/server/mcp/storage-oauth-provider.ts +17 -17
  98. package/src/server/storage/file-backend.ts +25 -25
  99. package/src/server/storage/index.ts +67 -10
  100. package/src/server/storage/memory-backend.ts +34 -34
  101. package/src/server/storage/neon-backend.ts +281 -0
  102. package/src/server/storage/redis-backend.ts +64 -64
  103. package/src/server/storage/sqlite-backend.ts +33 -33
  104. package/src/server/storage/supabase-backend.ts +23 -24
  105. package/src/server/storage/types.ts +18 -21
  106. package/src/shared/errors.ts +1 -1
  107. package/src/shared/index.ts +1 -2
  108. package/src/shared/meta-tools.ts +9 -10
  109. package/src/shared/schema-compressor.ts +2 -42
  110. package/src/shared/tool-index.ts +90 -84
  111. package/src/shared/tool-router.ts +38 -27
  112. package/src/shared/types.ts +6 -5
  113. /package/{supabase/migrations → migrations/supabase}/20260421010000_add_session_cleanup_cron.sql +0 -0
@@ -1,9 +1,9 @@
1
1
  export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, M as McpConnectionEvent, c as McpConnectionState, d as McpObservabilityEvent } from '../events-CK3N--3g.mjs';
2
- export { A as AuthenticationError, C as ConfigurationError, a as ConnectionError, I as InvalidStateError, M as McpError, N as NotConnectedError, R as RpcErrorCode, b as RpcErrorCodes, S as SessionNotFoundError, c as SessionValidationError, T as ToolExecutionError, U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-0qmYrqoa.mjs';
3
- import { v as ToolInfo } from '../types-rIuN1CQi.mjs';
4
- export { C as CallToolParams, a as CallToolRequest, b as CallToolResponse, c as ConnectAuthRequiredResponse, d as ConnectErrorResponse, e as ConnectParams, f as ConnectRequest, g as ConnectResponse, h as ConnectResult, i as ConnectSuccessResponse, D as DisconnectParams, j as DisconnectResult, F as FinishAuthParams, k as FinishAuthResult, G as GetPromptParams, L as ListPromptsResult, l as ListResourcesResult, m as ListToolsResponse, n as ListToolsRpcResult, M as McpRpcMethod, o as McpRpcParams, p as McpRpcRequest, q as McpRpcResponse, R as ReadResourceParams, r as RestoreSessionResult, S as SessionInfo, s as SessionListResult, t as SessionParams, T as ToolClient, u as ToolClientProvider, w as TransportType, x as isCallToolSuccess, y as isConnectAuthRequired, z as isConnectError, A as isConnectSuccess, B as isListToolsSuccess } from '../types-rIuN1CQi.mjs';
5
- import { e as ToolRouter } from '../tool-router-BVaV1udm.mjs';
6
- export { C as CompactTool, a as CompressionStats, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, b as ToolIndex, c as ToolIndexOptions, d as ToolListResult, f as ToolRouterClientInput, g as ToolRouterOptions, h as ToolRouterStrategy, i as ToolSearchOptions, j as ToolServerSummary, k as ToolSummary } from '../tool-router-BVaV1udm.mjs';
2
+ export { A as AuthenticationError, C as ConfigurationError, a as ConnectionError, I as InvalidStateError, M as McpError, N as NotConnectedError, R as RpcErrorCode, b as RpcErrorCodes, S as SessionNotFoundError, c as SessionValidationError, T as ToolExecutionError, U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.mjs';
3
+ import { v as ToolInfo } from '../types-CxFaaZrM.mjs';
4
+ export { C as CallToolParams, a as CallToolRequest, b as CallToolResponse, c as ConnectAuthRequiredResponse, d as ConnectErrorResponse, e as ConnectParams, f as ConnectRequest, g as ConnectResponse, h as ConnectResult, i as ConnectSuccessResponse, D as DisconnectParams, j as DisconnectResult, F as FinishAuthParams, k as FinishAuthResult, G as GetPromptParams, l as GetSessionResult, L as ListPromptsResult, m as ListResourcesResult, n as ListToolsResponse, o as ListToolsRpcResult, M as McpRpcMethod, p as McpRpcParams, q as McpRpcRequest, r as McpRpcResponse, R as ReadResourceParams, S as SessionInfo, s as SessionListResult, t as SessionParams, T as ToolClient, u as ToolClientProvider, w as TransportType, x as isCallToolSuccess, y as isConnectAuthRequired, z as isConnectError, A as isConnectSuccess, B as isListToolsSuccess } from '../types-CxFaaZrM.mjs';
5
+ import { d as ToolRouter } from '../tool-router-BkQnso27.mjs';
6
+ export { C as CompactTool, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, a as ToolIndex, b as ToolIndexOptions, c as ToolListResult, e as ToolRouterClientInput, f as ToolRouterOptions, g as ToolRouterStrategy, h as ToolSearchOptions, i as ToolServerSummary, j as ToolSummary } from '../tool-router-BkQnso27.mjs';
7
7
  import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
8
8
 
9
9
  /**
@@ -102,8 +102,8 @@ declare function createRegexSearchToolDefinition(): Tool;
102
102
  *
103
103
  * After discovering tools via `mcp_search_tools` or
104
104
  * `mcp_search_tool_regex`, the LLM calls this to load the full
105
- * inputSchema for a specific tool so it can construct the correct
106
- * arguments.
105
+ * input and output schemas for a specific tool so it can construct the
106
+ * correct arguments and plan around the result shape.
107
107
  */
108
108
  declare function createGetSchemaToolDefinition(): Tool;
109
109
  /**
@@ -1,9 +1,9 @@
1
1
  export { D as Disposable, a as DisposableStore, E as Emitter, b as Event, M as McpConnectionEvent, c as McpConnectionState, d as McpObservabilityEvent } from '../events-CK3N--3g.js';
2
- export { A as AuthenticationError, C as ConfigurationError, a as ConnectionError, I as InvalidStateError, M as McpError, N as NotConnectedError, R as RpcErrorCode, b as RpcErrorCodes, S as SessionNotFoundError, c as SessionValidationError, T as ToolExecutionError, U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-0qmYrqoa.js';
3
- import { v as ToolInfo } from '../types-rIuN1CQi.js';
4
- export { C as CallToolParams, a as CallToolRequest, b as CallToolResponse, c as ConnectAuthRequiredResponse, d as ConnectErrorResponse, e as ConnectParams, f as ConnectRequest, g as ConnectResponse, h as ConnectResult, i as ConnectSuccessResponse, D as DisconnectParams, j as DisconnectResult, F as FinishAuthParams, k as FinishAuthResult, G as GetPromptParams, L as ListPromptsResult, l as ListResourcesResult, m as ListToolsResponse, n as ListToolsRpcResult, M as McpRpcMethod, o as McpRpcParams, p as McpRpcRequest, q as McpRpcResponse, R as ReadResourceParams, r as RestoreSessionResult, S as SessionInfo, s as SessionListResult, t as SessionParams, T as ToolClient, u as ToolClientProvider, w as TransportType, x as isCallToolSuccess, y as isConnectAuthRequired, z as isConnectError, A as isConnectSuccess, B as isListToolsSuccess } from '../types-rIuN1CQi.js';
5
- import { e as ToolRouter } from '../tool-router-Dh2804tM.js';
6
- export { C as CompactTool, a as CompressionStats, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, b as ToolIndex, c as ToolIndexOptions, d as ToolListResult, f as ToolRouterClientInput, g as ToolRouterOptions, h as ToolRouterStrategy, i as ToolSearchOptions, j as ToolServerSummary, k as ToolSummary } from '../tool-router-Dh2804tM.js';
2
+ export { A as AuthenticationError, C as ConfigurationError, a as ConnectionError, I as InvalidStateError, M as McpError, N as NotConnectedError, R as RpcErrorCode, b as RpcErrorCodes, S as SessionNotFoundError, c as SessionValidationError, T as ToolExecutionError, U as UnauthorizedError, s as sanitizeServerLabel } from '../utils-DELRKQPU.js';
3
+ import { v as ToolInfo } from '../types-CxFaaZrM.js';
4
+ export { C as CallToolParams, a as CallToolRequest, b as CallToolResponse, c as ConnectAuthRequiredResponse, d as ConnectErrorResponse, e as ConnectParams, f as ConnectRequest, g as ConnectResponse, h as ConnectResult, i as ConnectSuccessResponse, D as DisconnectParams, j as DisconnectResult, F as FinishAuthParams, k as FinishAuthResult, G as GetPromptParams, l as GetSessionResult, L as ListPromptsResult, m as ListResourcesResult, n as ListToolsResponse, o as ListToolsRpcResult, M as McpRpcMethod, p as McpRpcParams, q as McpRpcRequest, r as McpRpcResponse, R as ReadResourceParams, S as SessionInfo, s as SessionListResult, t as SessionParams, T as ToolClient, u as ToolClientProvider, w as TransportType, x as isCallToolSuccess, y as isConnectAuthRequired, z as isConnectError, A as isConnectSuccess, B as isListToolsSuccess } from '../types-CxFaaZrM.js';
5
+ import { d as ToolRouter } from '../tool-router-BP8TT9mI.js';
6
+ export { C as CompactTool, E as EmbedFn, I as IndexedTool, S as SchemaCompressor, T as ToolGroupInfo, a as ToolIndex, b as ToolIndexOptions, c as ToolListResult, e as ToolRouterClientInput, f as ToolRouterOptions, g as ToolRouterStrategy, h as ToolSearchOptions, i as ToolServerSummary, j as ToolSummary } from '../tool-router-BP8TT9mI.js';
7
7
  import { Tool, CallToolResult } from '@modelcontextprotocol/sdk/types.js';
8
8
 
9
9
  /**
@@ -102,8 +102,8 @@ declare function createRegexSearchToolDefinition(): Tool;
102
102
  *
103
103
  * After discovering tools via `mcp_search_tools` or
104
104
  * `mcp_search_tool_regex`, the LLM calls this to load the full
105
- * inputSchema for a specific tool so it can construct the correct
106
- * arguments.
105
+ * input and output schemas for a specific tool so it can construct the
106
+ * correct arguments and plan around the result shape.
107
107
  */
108
108
  declare function createGetSchemaToolDefinition(): Tool;
109
109
  /**
@@ -156,7 +156,7 @@ var ToolExecutionError = class extends McpError {
156
156
  };
157
157
  var RpcErrorCodes = {
158
158
  EXECUTION_ERROR: "EXECUTION_ERROR",
159
- MISSING_IDENTITY: "MISSING_IDENTITY",
159
+ MISSING_USER_ID: "MISSING_USER_ID",
160
160
  UNAUTHORIZED: "UNAUTHORIZED",
161
161
  NO_CONNECTION: "NO_CONNECTION",
162
162
  UNKNOWN_METHOD: "UNKNOWN_METHOD",
@@ -213,17 +213,7 @@ function findToolByName(connections, toolName) {
213
213
  }
214
214
 
215
215
  // src/shared/tool-index.ts
216
- var CALIBRATION_DIVISOR = 3.6;
217
- function classifyChar(ch) {
218
- const code = ch.charCodeAt(0);
219
- if (code <= 32 || ch === "{" || ch === "}" || ch === "[" || ch === "]" || ch === ":" || ch === ",") return 1;
220
- if (code >= 33 && code <= 47) return 1.5;
221
- if (code >= 48 && code <= 57) return 2;
222
- if (code >= 65 && code <= 90) return 3.5;
223
- if (code >= 97 && code <= 122) return 4;
224
- return 2.5;
225
- }
226
- var ToolIndex = class _ToolIndex {
216
+ var ToolIndex = class {
227
217
  constructor(options = {}) {
228
218
  /** All indexed tools keyed by name (supports duplicates). */
229
219
  __publicField(this, "tools", /* @__PURE__ */ new Map());
@@ -241,8 +231,6 @@ var ToolIndex = class _ToolIndex {
241
231
  __publicField(this, "docLengths", /* @__PURE__ */ new Map());
242
232
  /** BM25: average document length across the entire index. */
243
233
  __publicField(this, "avgDocLength", 0);
244
- /** Cached total estimated token cost across all indexed tools. */
245
- __publicField(this, "totalTokenCost", 0);
246
234
  __publicField(this, "options");
247
235
  this.options = {
248
236
  embedFn: options.embedFn ?? void 0,
@@ -265,7 +253,6 @@ var ToolIndex = class _ToolIndex {
265
253
  this.embeddings.clear();
266
254
  this.docLengths.clear();
267
255
  this.avgDocLength = 0;
268
- this.totalTokenCost = 0;
269
256
  const allTokenSets = /* @__PURE__ */ new Map();
270
257
  let totalLength = 0;
271
258
  for (const tool of tools) {
@@ -274,19 +261,17 @@ var ToolIndex = class _ToolIndex {
274
261
  this.tools.set(tool.name, []);
275
262
  }
276
263
  this.tools.get(tool.name).push(tool);
277
- const estimatedTokens = _ToolIndex.estimateTokens(tool);
278
264
  this.toolSummaries.set(docKey, {
279
265
  name: tool.name,
280
266
  description: tool.description ?? "",
281
267
  serverName: tool.serverName,
282
268
  serverId: tool.serverId,
283
- sessionId: tool.sessionId,
284
- estimatedTokens
269
+ sessionId: tool.sessionId
285
270
  });
286
- this.totalTokenCost += estimatedTokens;
287
- const text = this.buildSearchableText(tool).toLowerCase();
271
+ const rawText = this.buildSearchableText(tool);
272
+ const text = rawText.toLowerCase();
288
273
  this.searchTexts.set(docKey, text);
289
- const tokens = this.tokenize(text);
274
+ const tokens = this.tokenize(rawText);
290
275
  const tf = /* @__PURE__ */ new Map();
291
276
  const uniqueTokens = /* @__PURE__ */ new Set();
292
277
  for (const tok of tokens) {
@@ -550,30 +535,6 @@ var ToolIndex = class _ToolIndex {
550
535
  }
551
536
  return count;
552
537
  }
553
- /** Total estimated token cost of all indexed tool schemas. */
554
- getTotalTokenCost() {
555
- return this.totalTokenCost;
556
- }
557
- // -----------------------------------------------------------------------
558
- // Static Helpers
559
- // -----------------------------------------------------------------------
560
- /**
561
- * Estimate token count of a tool's full schema (name + description + inputSchema).
562
- *
563
- * Uses character-class weighted counting calibrated against cl100k_base.
564
- * Accuracy is typically within ±10% for JSON Schema payloads.
565
- */
566
- static estimateTokens(tool) {
567
- const parts = [tool.name];
568
- if (tool.description) parts.push(tool.description);
569
- if (tool.inputSchema) parts.push(JSON.stringify(tool.inputSchema));
570
- const text = parts.join(" ");
571
- let weightedLen = 0;
572
- for (let i = 0; i < text.length; i++) {
573
- weightedLen += 1 / classifyChar(text[i]);
574
- }
575
- return Math.ceil(weightedLen / (1 / CALIBRATION_DIVISOR));
576
- }
577
538
  // -----------------------------------------------------------------------
578
539
  // Internals
579
540
  // -----------------------------------------------------------------------
@@ -582,18 +543,74 @@ var ToolIndex = class _ToolIndex {
582
543
  const parts = [tool.name];
583
544
  if (tool.description) parts.push(tool.description);
584
545
  if (tool.inputSchema && typeof tool.inputSchema === "object") {
585
- const schema = tool.inputSchema;
586
- const props = schema.properties;
587
- if (props) {
588
- for (const [key, val] of Object.entries(props)) {
589
- parts.push(key);
590
- if (val && typeof val === "object" && val.description) {
591
- parts.push(val.description);
592
- }
546
+ this.collectSchemaSearchText(tool.inputSchema, parts);
547
+ }
548
+ return parts.join(" ");
549
+ }
550
+ /** Recursively collect JSON Schema argument names and descriptions. */
551
+ collectSchemaSearchText(schema, parts, seen = /* @__PURE__ */ new WeakSet()) {
552
+ if (!schema || typeof schema !== "object") return;
553
+ if (seen.has(schema)) return;
554
+ seen.add(schema);
555
+ if (Array.isArray(schema)) {
556
+ for (const item of schema) {
557
+ this.collectSchemaSearchText(item, parts, seen);
558
+ }
559
+ return;
560
+ }
561
+ const schemaObject = schema;
562
+ this.pushStringValue(schemaObject.description, parts);
563
+ this.pushStringValue(schemaObject.title, parts);
564
+ const properties = schemaObject.properties;
565
+ if (properties && typeof properties === "object" && !Array.isArray(properties)) {
566
+ for (const [propertyName, propertySchema] of Object.entries(properties)) {
567
+ parts.push(propertyName);
568
+ this.collectSchemaSearchText(propertySchema, parts, seen);
569
+ }
570
+ }
571
+ const patternProperties = schemaObject.patternProperties;
572
+ if (patternProperties && typeof patternProperties === "object" && !Array.isArray(patternProperties)) {
573
+ for (const [propertyPattern, propertySchema] of Object.entries(patternProperties)) {
574
+ parts.push(propertyPattern);
575
+ this.collectSchemaSearchText(propertySchema, parts, seen);
576
+ }
577
+ }
578
+ const dependentSchemas = schemaObject.dependentSchemas;
579
+ if (dependentSchemas && typeof dependentSchemas === "object" && !Array.isArray(dependentSchemas)) {
580
+ for (const [propertyName, dependentSchema] of Object.entries(dependentSchemas)) {
581
+ parts.push(propertyName);
582
+ this.collectSchemaSearchText(dependentSchema, parts, seen);
583
+ }
584
+ }
585
+ for (const key of [
586
+ "items",
587
+ "additionalProperties",
588
+ "contains",
589
+ "propertyNames",
590
+ "if",
591
+ "then",
592
+ "else",
593
+ "not"
594
+ ]) {
595
+ this.collectSchemaSearchText(schemaObject[key], parts, seen);
596
+ }
597
+ for (const key of ["allOf", "anyOf", "oneOf", "prefixItems"]) {
598
+ this.collectSchemaSearchText(schemaObject[key], parts, seen);
599
+ }
600
+ for (const key of ["$defs", "definitions"]) {
601
+ const definitions = schemaObject[key];
602
+ if (definitions && typeof definitions === "object" && !Array.isArray(definitions)) {
603
+ for (const [definitionName, definitionSchema] of Object.entries(definitions)) {
604
+ parts.push(definitionName);
605
+ this.collectSchemaSearchText(definitionSchema, parts, seen);
593
606
  }
594
607
  }
595
608
  }
596
- return parts.join(" ");
609
+ }
610
+ pushStringValue(value, parts) {
611
+ if (typeof value === "string" && value.trim()) {
612
+ parts.push(value);
613
+ }
597
614
  }
598
615
  getDocumentKey(tool) {
599
616
  return `${tool.sessionId}::${tool.serverId}::${tool.name}`;
@@ -614,7 +631,7 @@ var ToolIndex = class _ToolIndex {
614
631
  }
615
632
  /** Simple whitespace + camelCase + snake_case tokenizer. */
616
633
  tokenize(text) {
617
- 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);
634
+ return text.replace(/([a-z])([A-Z])/g, "$1 $2").replace(/[_-]/g, " ").toLowerCase().replace(/[^a-z0-9\s]/g, "").split(/\s+/).filter((t) => t.length > 1);
618
635
  }
619
636
  /** Cosine similarity between two vectors. */
620
637
  cosineSimilarity(a, b) {
@@ -669,27 +686,6 @@ var SchemaCompressor = class _SchemaCompressor {
669
686
  const limited = options?.maxTools ? tools.slice(0, options.maxTools) : tools;
670
687
  return limited.map((t) => _SchemaCompressor.toCompact(t));
671
688
  }
672
- /**
673
- * Estimate token savings from using compact vs full tool schemas.
674
- */
675
- static estimateSavings(tools) {
676
- let fullTokens = 0;
677
- let compactTokens = 0;
678
- for (const tool of tools) {
679
- fullTokens += ToolIndex.estimateTokens(tool);
680
- const compact = _SchemaCompressor.toCompact(tool);
681
- const text = [compact.name, compact.description ?? "", compact.parameterHint ?? ""].join(" ");
682
- compactTokens += Math.ceil(text.length / 4);
683
- }
684
- const saved = fullTokens - compactTokens;
685
- const pct = fullTokens > 0 ? (saved / fullTokens * 100).toFixed(1) : "0.0";
686
- return {
687
- fullTokens,
688
- compactTokens,
689
- savedTokens: saved,
690
- savingsPercent: `${pct}%`
691
- };
692
- }
693
689
  };
694
690
 
695
691
  // src/shared/meta-tools.ts
@@ -768,7 +764,7 @@ function createRegexSearchToolDefinition() {
768
764
  function createGetSchemaToolDefinition() {
769
765
  return {
770
766
  name: "mcp_get_tool_schema",
771
- 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.",
767
+ description: "Get the full input schema (parameters) and output schema (result shape) for a specific tool. Call this after mcp_search_tools to get the parameter details needed to call a tool correctly and understand what it returns. Do NOT call the discovered tool directly; after reading the schema, call mcp_execute_tool.",
772
768
  inputSchema: {
773
769
  type: "object",
774
770
  properties: {
@@ -885,7 +881,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
885
881
  const lines = [];
886
882
  if (found.length > 0) {
887
883
  lines.push(...found.map(
888
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
884
+ (t, i) => `${i + 1}. **${t.name}** (serverName: ${t.serverName}, serverId: ${t.serverId})
889
885
  ${t.description}`
890
886
  ));
891
887
  }
@@ -913,7 +909,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
913
909
  serverName: query || void 0
914
910
  });
915
911
  const text = servers.length === 0 ? "No connected servers found." : servers.map(
916
- (server, i) => `${i + 1}. **${server.serverName}** (serverId: ${server.serverId}, sessionId: ${server.sessionId})
912
+ (server, i) => `${i + 1}. **${server.serverName}** (serverId: ${server.serverId})
917
913
  Tool count: ${server.toolCount}`
918
914
  ).join("\n");
919
915
  return {
@@ -953,6 +949,7 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
953
949
  name: tool.name,
954
950
  description: tool.description,
955
951
  inputSchema: tool.inputSchema,
952
+ outputSchema: tool.outputSchema,
956
953
  executionInstructions: {
957
954
  nextTool: "mcp_execute_tool",
958
955
  toolName: tool.name,
@@ -1020,9 +1017,8 @@ async function executeMetaTool(toolName, args, router, callToolFn) {
1020
1017
  }
1021
1018
  function formatToolSummaries(tools) {
1022
1019
  return tools.map(
1023
- (t, i) => `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})
1024
- ${t.description}
1025
- Estimated tokens: ${t.estimatedTokens}`
1020
+ (t, i) => `${i + 1}. **${t.name}** (serverName: ${t.serverName}, serverId: ${t.serverId})
1021
+ ${t.description}`
1026
1022
  );
1027
1023
  }
1028
1024
  function isMetaTool(toolName) {
@@ -1049,18 +1045,26 @@ var ToolRouter = class {
1049
1045
  this.options = options;
1050
1046
  __publicField(this, "index");
1051
1047
  __publicField(this, "allTools", []);
1048
+ __publicField(this, "pinnedTools", []);
1049
+ __publicField(this, "discoverableTools", []);
1052
1050
  __publicField(this, "groupsMap", /* @__PURE__ */ new Map());
1053
1051
  __publicField(this, "strategy");
1054
1052
  __publicField(this, "maxTools");
1055
1053
  __publicField(this, "compactSchemas");
1056
1054
  __publicField(this, "activeGroups");
1057
1055
  __publicField(this, "customGroups");
1056
+ __publicField(this, "pinnedToolNames");
1057
+ __publicField(this, "excludeToolMatchers");
1058
1058
  __publicField(this, "initialized", false);
1059
1059
  this.strategy = options.strategy ?? "all";
1060
1060
  this.maxTools = options.maxTools ?? 40;
1061
1061
  this.compactSchemas = options.compactSchemas ?? false;
1062
1062
  this.activeGroups = new Set(options.activeGroups ?? []);
1063
1063
  this.customGroups = options.groups;
1064
+ this.pinnedToolNames = new Set(options.pinnedTools ?? []);
1065
+ this.excludeToolMatchers = (options.excludeTools ?? []).map(
1066
+ (pattern) => globToRegExp(pattern)
1067
+ );
1064
1068
  this.index = new ToolIndex({
1065
1069
  embedFn: options.embedFn,
1066
1070
  keywordWeight: options.keywordWeight
@@ -1081,7 +1085,7 @@ var ToolRouter = class {
1081
1085
  await this.ensureInitialized();
1082
1086
  switch (this.strategy) {
1083
1087
  case "search":
1084
- return this.getMetaToolDefinitions();
1088
+ return [...this.getMetaToolDefinitions(), ...this.pinnedTools];
1085
1089
  case "groups":
1086
1090
  return this.getGroupFilteredTools();
1087
1091
  case "all":
@@ -1165,26 +1169,6 @@ var ToolRouter = class {
1165
1169
  getActiveGroups() {
1166
1170
  return [...this.activeGroups];
1167
1171
  }
1168
- // -----------------------------------------------------------------------
1169
- // Stats & Introspection
1170
- // -----------------------------------------------------------------------
1171
- /** Total token cost of all tools if loaded without filtering. */
1172
- getTotalTokenCost() {
1173
- return this.index.getTotalTokenCost();
1174
- }
1175
- /** Estimate token cost of the currently filtered tool set. */
1176
- async getFilteredTokenCost() {
1177
- const tools = await this.getFilteredTools();
1178
- let total = 0;
1179
- for (const tool of tools) {
1180
- total += ToolIndex.estimateTokens(tool);
1181
- }
1182
- return total;
1183
- }
1184
- /** Get compression stats showing savings from current strategy. */
1185
- getCompressionStats() {
1186
- return SchemaCompressor.estimateSavings(this.allTools);
1187
- }
1188
1172
  /** Number of total indexed tools. */
1189
1173
  get totalToolCount() {
1190
1174
  return this.allTools.length;
@@ -1228,8 +1212,11 @@ var ToolRouter = class {
1228
1212
  /** Lazy initialization — fetches tools from all connected clients. */
1229
1213
  async ensureInitialized() {
1230
1214
  if (this.initialized) return;
1231
- this.allTools = await this.fetchAllTools();
1232
- await this.index.buildIndex(this.allTools);
1215
+ const fetchedTools = await this.fetchAllTools();
1216
+ this.allTools = fetchedTools.filter((tool) => !this.matchesExcludedTool(tool.name));
1217
+ this.pinnedTools = this.allTools.filter((tool) => this.matchesPinnedTool(tool.name));
1218
+ this.discoverableTools = this.allTools.filter((tool) => !this.matchesPinnedTool(tool.name));
1219
+ await this.index.buildIndex(this.discoverableTools);
1233
1220
  this.buildGroups();
1234
1221
  this.initialized = true;
1235
1222
  }
@@ -1328,7 +1315,18 @@ var ToolRouter = class {
1328
1315
  createExecuteToolDefinition()
1329
1316
  ];
1330
1317
  }
1318
+ matchesPinnedTool(toolName) {
1319
+ return this.pinnedToolNames.has(toolName);
1320
+ }
1321
+ matchesExcludedTool(toolName) {
1322
+ return this.excludeToolMatchers.some((matcher) => matcher.test(toolName));
1323
+ }
1331
1324
  };
1325
+ function globToRegExp(pattern) {
1326
+ const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&");
1327
+ const regexPattern = `^${escaped.replace(/\*/g, ".*")}$`;
1328
+ return new RegExp(regexPattern);
1329
+ }
1332
1330
 
1333
1331
  exports.AuthenticationError = AuthenticationError;
1334
1332
  exports.ConfigurationError = ConfigurationError;