@mcp-ts/sdk 1.6.1 → 2.0.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 (114) 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 +4 -5
  5. package/dist/adapters/agui-adapter.js.map +1 -1
  6. package/dist/adapters/agui-adapter.mjs +4 -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 +20 -6
  13. package/dist/adapters/ai-adapter.js.map +1 -1
  14. package/dist/adapters/ai-adapter.mjs +20 -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 +9 -6
  19. package/dist/adapters/langchain-adapter.js.map +1 -1
  20. package/dist/adapters/langchain-adapter.mjs +9 -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 +111 -63
  41. package/dist/client/react.js.map +1 -1
  42. package/dist/client/react.mjs +111 -63
  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-DhA-OEAe.d.ts → index-C9gvpxy5.d.ts} +5 -5
  51. package/dist/{index-bFL4ZF2N.d.mts → index-eaH14_5u.d.mts} +5 -5
  52. package/dist/index.d.mts +6 -6
  53. package/dist/index.d.ts +6 -6
  54. package/dist/index.js +616 -370
  55. package/dist/index.js.map +1 -1
  56. package/dist/index.mjs +615 -370
  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 +5 -5
  67. package/dist/shared/index.d.ts +5 -5
  68. package/dist/shared/index.js +76 -101
  69. package/dist/shared/index.js.map +1 -1
  70. package/dist/shared/index.mjs +76 -101
  71. package/dist/shared/index.mjs.map +1 -1
  72. package/dist/{tool-router-Dh2804tM.d.ts → tool-router-Ddtybmr0.d.ts} +71 -73
  73. package/dist/{tool-router-BVaV1udm.d.mts → tool-router-Dnd6IOKC.d.mts} +71 -73
  74. package/dist/{types-rIuN1CQi.d.mts → types-BCAG20P6.d.mts} +4 -4
  75. package/dist/{types-rIuN1CQi.d.ts → types-BCAG20P6.d.ts} +4 -4
  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/oauth-popup.tsx +111 -51
  90. package/src/client/react/use-mcp-apps.tsx +1 -1
  91. package/src/client/react/use-mcp.ts +11 -11
  92. package/src/client/vue/use-mcp.ts +10 -10
  93. package/src/server/handlers/nextjs-handler.ts +18 -15
  94. package/src/server/handlers/sse-handler.ts +29 -29
  95. package/src/server/index.ts +1 -1
  96. package/src/server/mcp/multi-session-client.ts +17 -17
  97. package/src/server/mcp/oauth-client.ts +37 -37
  98. package/src/server/mcp/storage-oauth-provider.ts +17 -17
  99. package/src/server/storage/file-backend.ts +25 -25
  100. package/src/server/storage/index.ts +67 -10
  101. package/src/server/storage/memory-backend.ts +34 -34
  102. package/src/server/storage/neon-backend.ts +281 -0
  103. package/src/server/storage/redis-backend.ts +64 -64
  104. package/src/server/storage/sqlite-backend.ts +33 -33
  105. package/src/server/storage/supabase-backend.ts +23 -24
  106. package/src/server/storage/types.ts +18 -21
  107. package/src/shared/errors.ts +1 -1
  108. package/src/shared/index.ts +1 -2
  109. package/src/shared/meta-tools.ts +4 -6
  110. package/src/shared/schema-compressor.ts +2 -42
  111. package/src/shared/tool-index.ts +89 -84
  112. package/src/shared/tool-router.ts +0 -24
  113. package/src/shared/types.ts +4 -4
  114. /package/{supabase/migrations → migrations/supabase}/20260421010000_add_session_cleanup_cron.sql +0 -0
@@ -5,15 +5,15 @@ import type {
5
5
  OAuthClientInformationMixed,
6
6
  } from '@modelcontextprotocol/sdk/shared/auth.js';
7
7
 
8
- export interface SessionData {
8
+ export interface Session {
9
9
  sessionId: string;
10
10
  serverId?: string; // Database server ID for mapping
11
11
  serverName?: string;
12
12
  serverUrl: string;
13
- transportType: 'sse' | 'streamable_http';
13
+ transportType: 'sse' | 'streamable-http';
14
14
  callbackUrl: string;
15
15
  createdAt: number;
16
- identity: string;
16
+ userId: string;
17
17
  headers?: Record<string, string>;
18
18
  /**
19
19
  * Session status marker used for TTL transitions:
@@ -36,15 +36,15 @@ export interface SetClientOptions {
36
36
  client?: MCPClient;
37
37
  serverUrl?: string;
38
38
  callbackUrl?: string;
39
- transportType?: 'sse' | 'streamable_http';
40
- identity?: string;
39
+ transportType?: 'sse' | 'streamable-http';
40
+ userId?: string;
41
41
  headers?: Record<string, string>;
42
42
  }
43
43
 
44
44
  /**
45
- * Interface for MCP Session Storage Backends
45
+ * Interface for MCP session stores.
46
46
  */
47
- export interface StorageBackend {
47
+ export interface SessionStore {
48
48
  /**
49
49
  * Optional initialization (e.g., database connection)
50
50
  */
@@ -55,49 +55,46 @@ export interface StorageBackend {
55
55
  */
56
56
  generateSessionId(): string;
57
57
 
58
- /**
59
- * Stores or updates a session
60
- */
61
58
  /**
62
59
  * Creates a new session. Throws if session already exists.
63
60
  * @param session - Session data to create
64
61
  * @param ttl - Optional TTL in seconds (defaults to backend's default)
65
62
  */
66
- createSession(session: SessionData, ttl?: number): Promise<void>;
63
+ create(session: Session, ttl?: number): Promise<void>;
67
64
 
68
65
  /**
69
66
  * Updates an existing session with partial data. Throws if session does not exist.
70
- * @param identity - User identity
67
+ * @param userId - User identifier
71
68
  * @param sessionId - Session identifier
72
69
  * @param data - Partial session data to update
73
70
  * @param ttl - Optional TTL in seconds (defaults to backend's default)
74
71
  */
75
- updateSession(identity: string, sessionId: string, data: Partial<SessionData>, ttl?: number): Promise<void>;
72
+ update(userId: string, sessionId: string, data: Partial<Session>, ttl?: number): Promise<void>;
76
73
 
77
74
  /**
78
75
  * Retrieves a session
79
76
  */
80
- getSession(identity: string, sessionId: string): Promise<SessionData | null>;
77
+ get(userId: string, sessionId: string): Promise<Session | null>;
81
78
 
82
79
  /**
83
- * Gets full session data for all of an identity's sessions
80
+ * Gets full session data for all sessions owned by a user
84
81
  */
85
- getIdentitySessionsData(identity: string): Promise<SessionData[]>;
82
+ list(userId: string): Promise<Session[]>;
86
83
 
87
84
  /**
88
85
  * Removes a session
89
86
  */
90
- removeSession(identity: string, sessionId: string): Promise<void>;
87
+ delete(userId: string, sessionId: string): Promise<void>;
91
88
 
92
89
  /**
93
- * Gets all sessions IDs of an identity
90
+ * Gets all session IDs owned by a user
94
91
  */
95
- getIdentityMcpSessions(identity: string): Promise<string[]>;
92
+ listIds(userId: string): Promise<string[]>;
96
93
 
97
94
  /**
98
95
  * Gets all session IDs across all users (Admin)
99
96
  */
100
- getAllSessionIds(): Promise<string[]>;
97
+ listAllIds(): Promise<string[]>;
101
98
 
102
99
  /**
103
100
  * Clears all sessions (Admin)
@@ -107,7 +104,7 @@ export interface StorageBackend {
107
104
  /**
108
105
  * Clean up expired sessions
109
106
  */
110
- cleanupExpiredSessions(): Promise<void>;
107
+ cleanupExpired(): Promise<void>;
111
108
 
112
109
  /**
113
110
  * Disconnect from storage backend
@@ -123,7 +123,7 @@ export class ToolExecutionError extends McpError {
123
123
  */
124
124
  export const RpcErrorCodes = {
125
125
  EXECUTION_ERROR: 'EXECUTION_ERROR',
126
- MISSING_IDENTITY: 'MISSING_IDENTITY',
126
+ MISSING_USER_ID: 'MISSING_USER_ID',
127
127
  UNAUTHORIZED: 'UNAUTHORIZED',
128
128
  NO_CONNECTION: 'NO_CONNECTION',
129
129
  UNKNOWN_METHOD: 'UNKNOWN_METHOD',
@@ -52,7 +52,7 @@ export type {
52
52
  SessionListResult,
53
53
  ConnectResult,
54
54
  DisconnectResult,
55
- RestoreSessionResult,
55
+ GetSessionResult,
56
56
  FinishAuthResult,
57
57
  ListToolsRpcResult,
58
58
  ListPromptsResult,
@@ -98,7 +98,6 @@ export {
98
98
  export {
99
99
  SchemaCompressor,
100
100
  type CompactTool,
101
- type CompressionStats,
102
101
  } from './schema-compressor.js';
103
102
 
104
103
  export {
@@ -337,7 +337,7 @@ export async function executeMetaTool(
337
337
 
338
338
  if (found.length > 0) {
339
339
  lines.push(...found.map((t, i) =>
340
- `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})\n ${t.description}`
340
+ `${i + 1}. **${t.name}** (serverName: ${t.serverName}, serverId: ${t.serverId})\n ${t.description}`
341
341
  ));
342
342
  }
343
343
 
@@ -380,7 +380,7 @@ export async function executeMetaTool(
380
380
  : servers
381
381
  .map(
382
382
  (server, i) =>
383
- `${i + 1}. **${server.serverName}** (serverId: ${server.serverId}, sessionId: ${server.sessionId})\n` +
383
+ `${i + 1}. **${server.serverName}** (serverId: ${server.serverId})\n` +
384
384
  ` Tool count: ${server.toolCount}`
385
385
  )
386
386
  .join('\n');
@@ -518,14 +518,12 @@ function formatToolSummaries(
518
518
  description: string;
519
519
  serverName: string;
520
520
  serverId: string;
521
- estimatedTokens: number;
522
521
  }>
523
522
  ): string[] {
524
523
  return tools.map(
525
524
  (t, i) =>
526
- `${i + 1}. **${t.name}** (server: ${t.serverName}, serverId: ${t.serverId})\n` +
527
- ` ${t.description}\n` +
528
- ` Estimated tokens: ${t.estimatedTokens}`
525
+ `${i + 1}. **${t.name}** (serverName: ${t.serverName}, serverId: ${t.serverId})\n` +
526
+ ` ${t.description}`
529
527
  );
530
528
  }
531
529
 
@@ -1,14 +1,13 @@
1
1
  /**
2
- * SchemaCompressor — Utilities for reducing tool schema token overhead.
2
+ * SchemaCompressor — Utilities for compact tool representations.
3
3
  *
4
4
  * Provides compact representations of tools (name + description only,
5
- * no inputSchema) and token savings estimation.
5
+ * no inputSchema).
6
6
  *
7
7
  * @packageDocumentation
8
8
  */
9
9
 
10
10
  import type { Tool } from '@modelcontextprotocol/sdk/types.js';
11
- import { ToolIndex } from './tool-index.js';
12
11
 
13
12
  // ---------------------------------------------------------------------------
14
13
  // Types
@@ -28,17 +27,6 @@ export interface CompactTool {
28
27
  parameterHint?: string;
29
28
  }
30
29
 
31
- export interface CompressionStats {
32
- /** Estimated tokens for the *full* tool list. */
33
- fullTokens: number;
34
- /** Estimated tokens for the *compact* tool list. */
35
- compactTokens: number;
36
- /** Absolute token savings. */
37
- savedTokens: number;
38
- /** Percentage savings as a human-readable string, e.g. "82.3%". */
39
- savingsPercent: string;
40
- }
41
-
42
30
  // ---------------------------------------------------------------------------
43
31
  // SchemaCompressor
44
32
  // ---------------------------------------------------------------------------
@@ -93,32 +81,4 @@ export class SchemaCompressor {
93
81
  const limited = options?.maxTools ? tools.slice(0, options.maxTools) : tools;
94
82
  return limited.map((t) => SchemaCompressor.toCompact(t));
95
83
  }
96
-
97
- /**
98
- * Estimate token savings from using compact vs full tool schemas.
99
- */
100
- static estimateSavings(tools: Tool[]): CompressionStats {
101
- let fullTokens = 0;
102
- let compactTokens = 0;
103
-
104
- for (const tool of tools) {
105
- fullTokens += ToolIndex.estimateTokens(tool);
106
-
107
- // Compact form: name + description + parameterHint
108
- const compact = SchemaCompressor.toCompact(tool);
109
- const text = [compact.name, compact.description ?? '', compact.parameterHint ?? ''].join(' ');
110
- // Simple estimation for compact: ~4 chars per token for plain text
111
- compactTokens += Math.ceil(text.length / 4);
112
- }
113
-
114
- const saved = fullTokens - compactTokens;
115
- const pct = fullTokens > 0 ? ((saved / fullTokens) * 100).toFixed(1) : '0.0';
116
-
117
- return {
118
- fullTokens,
119
- compactTokens,
120
- savedTokens: saved,
121
- savingsPercent: `${pct}%`,
122
- };
123
- }
124
84
  }
@@ -28,8 +28,6 @@ export interface ToolSummary {
28
28
  serverId: string;
29
29
  /** Session the tool belongs to */
30
30
  sessionId: string;
31
- /** Estimated token cost of the full inputSchema */
32
- estimatedTokens: number;
33
31
  }
34
32
 
35
33
  /** Server-level summary derived from indexed tools. */
@@ -106,41 +104,6 @@ export interface ToolIndexOptions {
106
104
  keywordWeight?: number;
107
105
  }
108
106
 
109
- // ---------------------------------------------------------------------------
110
- // Token Estimation
111
- // ---------------------------------------------------------------------------
112
-
113
- /**
114
- * Character-class weights for accurate-ish token estimation without a real
115
- * tokenizer. Empirically calibrated against cl100k_base on typical JSON
116
- * Schema payloads.
117
- *
118
- * | Char class | Approx chars per token |
119
- * |--------------------|------------------------|
120
- * | Whitespace / punct | 1–2 |
121
- * | English words | ~4 |
122
- * | JSON keys/values | ~3.5 |
123
- *
124
- * We walk the string once and accumulate a weighted character count, then
125
- * divide by a calibrated divisor.
126
- */
127
- const CALIBRATION_DIVISOR = 3.6;
128
-
129
- function classifyChar(ch: string): number {
130
- const code = ch.charCodeAt(0);
131
- // whitespace / common JSON structural chars → high token density
132
- if (code <= 0x20 || ch === '{' || ch === '}' || ch === '[' || ch === ']' || ch === ':' || ch === ',') return 1.0;
133
- // digits and symbols
134
- if (code >= 0x21 && code <= 0x2f) return 1.5;
135
- if (code >= 0x30 && code <= 0x39) return 2.0;
136
- // uppercase (often JSON keys)
137
- if (code >= 0x41 && code <= 0x5a) return 3.5;
138
- // lowercase (natural language in descriptions)
139
- if (code >= 0x61 && code <= 0x7a) return 4.0;
140
- // everything else (unicode, emojis, etc.)
141
- return 2.5;
142
- }
143
-
144
107
  // ---------------------------------------------------------------------------
145
108
  // ToolIndex
146
109
  // ---------------------------------------------------------------------------
@@ -170,9 +133,6 @@ export class ToolIndex {
170
133
  /** BM25: average document length across the entire index. */
171
134
  private avgDocLength = 0;
172
135
 
173
- /** Cached total estimated token cost across all indexed tools. */
174
- private totalTokenCost = 0;
175
-
176
136
  private options: Required<ToolIndexOptions>;
177
137
 
178
138
  constructor(options: ToolIndexOptions = {}) {
@@ -199,7 +159,6 @@ export class ToolIndex {
199
159
  this.embeddings.clear();
200
160
  this.docLengths.clear();
201
161
  this.avgDocLength = 0;
202
- this.totalTokenCost = 0;
203
162
 
204
163
  // 1. Populate tool map + search text
205
164
  const allTokenSets: Map<string, Set<string>> = new Map();
@@ -212,21 +171,19 @@ export class ToolIndex {
212
171
  this.tools.set(tool.name, []);
213
172
  }
214
173
  this.tools.get(tool.name)!.push(tool);
215
- const estimatedTokens = ToolIndex.estimateTokens(tool);
216
174
  this.toolSummaries.set(docKey, {
217
175
  name: tool.name,
218
176
  description: tool.description ?? '',
219
177
  serverName: tool.serverName,
220
178
  serverId: tool.serverId,
221
179
  sessionId: tool.sessionId,
222
- estimatedTokens,
223
180
  });
224
- this.totalTokenCost += estimatedTokens;
225
181
 
226
- const text = this.buildSearchableText(tool).toLowerCase();
182
+ const rawText = this.buildSearchableText(tool);
183
+ const text = rawText.toLowerCase();
227
184
  this.searchTexts.set(docKey, text);
228
185
 
229
- const tokens = this.tokenize(text);
186
+ const tokens = this.tokenize(rawText);
230
187
  const tf = new Map<string, number>();
231
188
  const uniqueTokens = new Set<string>();
232
189
 
@@ -578,60 +535,107 @@ export class ToolIndex {
578
535
  return count;
579
536
  }
580
537
 
581
- /** Total estimated token cost of all indexed tool schemas. */
582
- getTotalTokenCost(): number {
583
- return this.totalTokenCost;
584
- }
585
-
586
538
  // -----------------------------------------------------------------------
587
- // Static Helpers
539
+ // Internals
588
540
  // -----------------------------------------------------------------------
589
541
 
590
- /**
591
- * Estimate token count of a tool's full schema (name + description + inputSchema).
592
- *
593
- * Uses character-class weighted counting calibrated against cl100k_base.
594
- * Accuracy is typically within ±10% for JSON Schema payloads.
595
- */
596
- static estimateTokens(tool: Tool): number {
542
+ /** Build a single searchable string from tool metadata. */
543
+ private buildSearchableText(tool: Tool): string {
597
544
  const parts: string[] = [tool.name];
598
545
  if (tool.description) parts.push(tool.description);
599
- if (tool.inputSchema) parts.push(JSON.stringify(tool.inputSchema));
600
546
 
601
- const text = parts.join(' ');
602
- let weightedLen = 0;
603
-
604
- for (let i = 0; i < text.length; i++) {
605
- weightedLen += 1 / classifyChar(text[i]);
547
+ if (tool.inputSchema && typeof tool.inputSchema === 'object') {
548
+ this.collectSchemaSearchText(tool.inputSchema, parts);
606
549
  }
607
550
 
608
- return Math.ceil(weightedLen / (1 / CALIBRATION_DIVISOR));
551
+ return parts.join(' ');
609
552
  }
610
553
 
611
- // -----------------------------------------------------------------------
612
- // Internals
613
- // -----------------------------------------------------------------------
554
+ /** Recursively collect JSON Schema argument names and descriptions. */
555
+ private collectSchemaSearchText(
556
+ schema: unknown,
557
+ parts: string[],
558
+ seen = new WeakSet<object>()
559
+ ): void {
560
+ if (!schema || typeof schema !== 'object') return;
561
+ if (seen.has(schema)) return;
562
+ seen.add(schema);
563
+
564
+ if (Array.isArray(schema)) {
565
+ for (const item of schema) {
566
+ this.collectSchemaSearchText(item, parts, seen);
567
+ }
568
+ return;
569
+ }
614
570
 
615
- /** Build a single searchable string from tool metadata. */
616
- private buildSearchableText(tool: Tool): string {
617
- const parts: string[] = [tool.name];
618
- if (tool.description) parts.push(tool.description);
571
+ const schemaObject = schema as Record<string, unknown>;
572
+ this.pushStringValue(schemaObject.description, parts);
573
+ this.pushStringValue(schemaObject.title, parts);
619
574
 
620
- // Include property names and descriptions from schema
621
- if (tool.inputSchema && typeof tool.inputSchema === 'object') {
622
- const schema = tool.inputSchema as Record<string, unknown>;
623
- const props = schema.properties as Record<string, { description?: string }> | undefined;
624
- if (props) {
625
- for (const [key, val] of Object.entries(props)) {
626
- parts.push(key);
627
- if (val && typeof val === 'object' && val.description) {
628
- parts.push(val.description);
629
- }
575
+ const properties = schemaObject.properties;
576
+ if (properties && typeof properties === 'object' && !Array.isArray(properties)) {
577
+ for (const [propertyName, propertySchema] of Object.entries(properties)) {
578
+ parts.push(propertyName);
579
+ this.collectSchemaSearchText(propertySchema, parts, seen);
580
+ }
581
+ }
582
+
583
+ const patternProperties = schemaObject.patternProperties;
584
+ if (
585
+ patternProperties &&
586
+ typeof patternProperties === 'object' &&
587
+ !Array.isArray(patternProperties)
588
+ ) {
589
+ for (const [propertyPattern, propertySchema] of Object.entries(patternProperties)) {
590
+ parts.push(propertyPattern);
591
+ this.collectSchemaSearchText(propertySchema, parts, seen);
592
+ }
593
+ }
594
+
595
+ const dependentSchemas = schemaObject.dependentSchemas;
596
+ if (
597
+ dependentSchemas &&
598
+ typeof dependentSchemas === 'object' &&
599
+ !Array.isArray(dependentSchemas)
600
+ ) {
601
+ for (const [propertyName, dependentSchema] of Object.entries(dependentSchemas)) {
602
+ parts.push(propertyName);
603
+ this.collectSchemaSearchText(dependentSchema, parts, seen);
604
+ }
605
+ }
606
+
607
+ for (const key of [
608
+ 'items',
609
+ 'additionalProperties',
610
+ 'contains',
611
+ 'propertyNames',
612
+ 'if',
613
+ 'then',
614
+ 'else',
615
+ 'not',
616
+ ]) {
617
+ this.collectSchemaSearchText(schemaObject[key], parts, seen);
618
+ }
619
+
620
+ for (const key of ['allOf', 'anyOf', 'oneOf', 'prefixItems']) {
621
+ this.collectSchemaSearchText(schemaObject[key], parts, seen);
622
+ }
623
+
624
+ for (const key of ['$defs', 'definitions']) {
625
+ const definitions = schemaObject[key];
626
+ if (definitions && typeof definitions === 'object' && !Array.isArray(definitions)) {
627
+ for (const [definitionName, definitionSchema] of Object.entries(definitions)) {
628
+ parts.push(definitionName);
629
+ this.collectSchemaSearchText(definitionSchema, parts, seen);
630
630
  }
631
631
  }
632
632
  }
633
+ }
633
634
 
634
- return parts.join(' ');
635
+ private pushStringValue(value: unknown, parts: string[]): void {
636
+ if (typeof value === 'string' && value.trim()) {
637
+ parts.push(value);
638
+ }
635
639
  }
636
640
 
637
641
  private getDocumentKey(tool: IndexedTool): string {
@@ -662,6 +666,7 @@ export class ToolIndex {
662
666
  .replace(/([a-z])([A-Z])/g, '$1 $2')
663
667
  // Split snake_case / kebab-case
664
668
  .replace(/[_-]/g, ' ')
669
+ .toLowerCase()
665
670
  // Remove non-alphanumeric (except spaces)
666
671
  .replace(/[^a-z0-9\s]/g, '')
667
672
  // Split on whitespace
@@ -290,30 +290,6 @@ export class ToolRouter {
290
290
  return [...this.activeGroups];
291
291
  }
292
292
 
293
- // -----------------------------------------------------------------------
294
- // Stats & Introspection
295
- // -----------------------------------------------------------------------
296
-
297
- /** Total token cost of all tools if loaded without filtering. */
298
- getTotalTokenCost(): number {
299
- return this.index.getTotalTokenCost();
300
- }
301
-
302
- /** Estimate token cost of the currently filtered tool set. */
303
- async getFilteredTokenCost(): Promise<number> {
304
- const tools = await this.getFilteredTools();
305
- let total = 0;
306
- for (const tool of tools) {
307
- total += ToolIndex.estimateTokens(tool);
308
- }
309
- return total;
310
- }
311
-
312
- /** Get compression stats showing savings from current strategy. */
313
- getCompressionStats() {
314
- return SchemaCompressor.estimateSavings(this.allTools);
315
- }
316
-
317
293
  /** Number of total indexed tools. */
318
294
  get totalToolCount(): number {
319
295
  return this.allTools.length;
@@ -166,7 +166,7 @@ export type ToolInfo = {
166
166
  };
167
167
 
168
168
  // Transport type
169
- export type TransportType = 'sse' | 'streamable_http';
169
+ export type TransportType = 'sse' | 'streamable-http';
170
170
 
171
171
  // SSE/RPC types
172
172
  export type McpRpcMethod =
@@ -174,8 +174,8 @@ export type McpRpcMethod =
174
174
  | 'disconnect'
175
175
  | 'listTools'
176
176
  | 'callTool'
177
- | 'getSessions'
178
- | 'restoreSession'
177
+ | 'listSessions'
178
+ | 'getSession'
179
179
  | 'finishAuth'
180
180
  | 'listPrompts'
181
181
  | 'getPrompt'
@@ -275,7 +275,7 @@ export interface DisconnectResult {
275
275
  success: boolean;
276
276
  }
277
277
 
278
- export interface RestoreSessionResult {
278
+ export interface GetSessionResult {
279
279
  success: boolean;
280
280
  toolCount: number;
281
281
  }