@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.
- package/README.md +12 -6
- package/dist/adapters/agui-adapter.d.mts +3 -3
- package/dist/adapters/agui-adapter.d.ts +3 -3
- package/dist/adapters/agui-adapter.js +5 -5
- package/dist/adapters/agui-adapter.js.map +1 -1
- package/dist/adapters/agui-adapter.mjs +5 -5
- package/dist/adapters/agui-adapter.mjs.map +1 -1
- package/dist/adapters/agui-middleware.d.mts +3 -3
- package/dist/adapters/agui-middleware.d.ts +3 -3
- package/dist/adapters/ai-adapter.d.mts +9 -3
- package/dist/adapters/ai-adapter.d.ts +9 -3
- package/dist/adapters/ai-adapter.js +21 -6
- package/dist/adapters/ai-adapter.js.map +1 -1
- package/dist/adapters/ai-adapter.mjs +21 -6
- package/dist/adapters/ai-adapter.mjs.map +1 -1
- package/dist/adapters/langchain-adapter.d.mts +3 -3
- package/dist/adapters/langchain-adapter.d.ts +3 -3
- package/dist/adapters/langchain-adapter.js +10 -6
- package/dist/adapters/langchain-adapter.js.map +1 -1
- package/dist/adapters/langchain-adapter.mjs +10 -6
- package/dist/adapters/langchain-adapter.mjs.map +1 -1
- package/dist/adapters/mastra-adapter.d.mts +1 -1
- package/dist/adapters/mastra-adapter.d.ts +1 -1
- package/dist/adapters/mastra-adapter.js +5 -1
- package/dist/adapters/mastra-adapter.js.map +1 -1
- package/dist/adapters/mastra-adapter.mjs +5 -1
- package/dist/adapters/mastra-adapter.mjs.map +1 -1
- package/dist/bin/mcp-ts.js +7 -1
- package/dist/bin/mcp-ts.js.map +1 -1
- package/dist/bin/mcp-ts.mjs +7 -1
- package/dist/bin/mcp-ts.mjs.map +1 -1
- package/dist/client/index.d.mts +2 -2
- package/dist/client/index.d.ts +2 -2
- package/dist/client/index.js +9 -13
- package/dist/client/index.js.map +1 -1
- package/dist/client/index.mjs +9 -13
- package/dist/client/index.mjs.map +1 -1
- package/dist/client/react.d.mts +7 -7
- package/dist/client/react.d.ts +7 -7
- package/dist/client/react.js +15 -19
- package/dist/client/react.js.map +1 -1
- package/dist/client/react.mjs +15 -19
- package/dist/client/react.mjs.map +1 -1
- package/dist/client/vue.d.mts +7 -7
- package/dist/client/vue.d.ts +7 -7
- package/dist/client/vue.js +14 -18
- package/dist/client/vue.js.map +1 -1
- package/dist/client/vue.mjs +14 -18
- package/dist/client/vue.mjs.map +1 -1
- package/dist/{index-bFL4ZF2N.d.mts → index-Cfjsme-a.d.mts} +5 -5
- package/dist/{index-DhA-OEAe.d.ts → index-CmjMd2ac.d.ts} +5 -5
- package/dist/index.d.mts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +643 -374
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +642 -374
- package/dist/index.mjs.map +1 -1
- package/dist/{multi-session-client-CHE8QpVE.d.ts → multi-session-client-BYtguGJm.d.ts} +22 -22
- package/dist/{multi-session-client-CQsRbxYI.d.mts → multi-session-client-DYNe6az3.d.mts} +22 -22
- package/dist/server/index.d.mts +31 -34
- package/dist/server/index.d.ts +31 -34
- package/dist/server/index.js +531 -256
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +530 -256
- package/dist/server/index.mjs.map +1 -1
- package/dist/shared/index.d.mts +7 -7
- package/dist/shared/index.d.ts +7 -7
- package/dist/shared/index.js +103 -105
- package/dist/shared/index.js.map +1 -1
- package/dist/shared/index.mjs +103 -105
- package/dist/shared/index.mjs.map +1 -1
- package/dist/{tool-router-BVaV1udm.d.mts → tool-router-BP8TT9mI.d.ts} +87 -73
- package/dist/{tool-router-Dh2804tM.d.ts → tool-router-BkQnso27.d.mts} +87 -73
- package/dist/{types-rIuN1CQi.d.mts → types-CxFaaZrM.d.mts} +6 -5
- package/dist/{types-rIuN1CQi.d.ts → types-CxFaaZrM.d.ts} +6 -5
- package/dist/{utils-0qmYrqoa.d.mts → utils-DELRKQPU.d.mts} +1 -1
- package/dist/{utils-0qmYrqoa.d.ts → utils-DELRKQPU.d.ts} +1 -1
- package/migrations/neon/20260513010000_install_mcp_sessions.sql +69 -0
- package/migrations/neon/20260513020000_add_session_cleanup_cron.sql +35 -0
- package/{supabase/migrations → migrations/supabase}/20260330195700_install_mcp_sessions.sql +7 -9
- package/package.json +14 -5
- package/src/adapters/ai-adapter.ts +30 -1
- package/src/adapters/langchain-adapter.ts +6 -2
- package/src/adapters/mastra-adapter.ts +6 -2
- package/src/bin/mcp-ts.ts +8 -1
- package/src/client/core/app-host.ts +1 -1
- package/src/client/core/sse-client.ts +12 -14
- package/src/client/core/types.ts +1 -1
- package/src/client/react/use-mcp-apps.tsx +1 -1
- package/src/client/react/use-mcp.ts +11 -11
- package/src/client/vue/use-mcp.ts +10 -10
- package/src/server/handlers/nextjs-handler.ts +18 -15
- package/src/server/handlers/sse-handler.ts +29 -29
- package/src/server/index.ts +1 -1
- package/src/server/mcp/multi-session-client.ts +17 -17
- package/src/server/mcp/oauth-client.ts +37 -37
- package/src/server/mcp/storage-oauth-provider.ts +17 -17
- package/src/server/storage/file-backend.ts +25 -25
- package/src/server/storage/index.ts +67 -10
- package/src/server/storage/memory-backend.ts +34 -34
- package/src/server/storage/neon-backend.ts +281 -0
- package/src/server/storage/redis-backend.ts +64 -64
- package/src/server/storage/sqlite-backend.ts +33 -33
- package/src/server/storage/supabase-backend.ts +23 -24
- package/src/server/storage/types.ts +18 -21
- package/src/shared/errors.ts +1 -1
- package/src/shared/index.ts +1 -2
- package/src/shared/meta-tools.ts +9 -10
- package/src/shared/schema-compressor.ts +2 -42
- package/src/shared/tool-index.ts +90 -84
- package/src/shared/tool-router.ts +38 -27
- package/src/shared/types.ts +6 -5
- /package/{supabase/migrations → migrations/supabase}/20260421010000_add_session_cleanup_cron.sql +0 -0
package/src/shared/tool-index.ts
CHANGED
|
@@ -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. */
|
|
@@ -74,6 +72,7 @@ export interface IndexedTool extends Tool {
|
|
|
74
72
|
sessionId: string;
|
|
75
73
|
serverId: string;
|
|
76
74
|
serverName: string;
|
|
75
|
+
outputSchema?: Tool['outputSchema'];
|
|
77
76
|
}
|
|
78
77
|
|
|
79
78
|
/**
|
|
@@ -106,41 +105,6 @@ export interface ToolIndexOptions {
|
|
|
106
105
|
keywordWeight?: number;
|
|
107
106
|
}
|
|
108
107
|
|
|
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
108
|
// ---------------------------------------------------------------------------
|
|
145
109
|
// ToolIndex
|
|
146
110
|
// ---------------------------------------------------------------------------
|
|
@@ -170,9 +134,6 @@ export class ToolIndex {
|
|
|
170
134
|
/** BM25: average document length across the entire index. */
|
|
171
135
|
private avgDocLength = 0;
|
|
172
136
|
|
|
173
|
-
/** Cached total estimated token cost across all indexed tools. */
|
|
174
|
-
private totalTokenCost = 0;
|
|
175
|
-
|
|
176
137
|
private options: Required<ToolIndexOptions>;
|
|
177
138
|
|
|
178
139
|
constructor(options: ToolIndexOptions = {}) {
|
|
@@ -199,7 +160,6 @@ export class ToolIndex {
|
|
|
199
160
|
this.embeddings.clear();
|
|
200
161
|
this.docLengths.clear();
|
|
201
162
|
this.avgDocLength = 0;
|
|
202
|
-
this.totalTokenCost = 0;
|
|
203
163
|
|
|
204
164
|
// 1. Populate tool map + search text
|
|
205
165
|
const allTokenSets: Map<string, Set<string>> = new Map();
|
|
@@ -212,21 +172,19 @@ export class ToolIndex {
|
|
|
212
172
|
this.tools.set(tool.name, []);
|
|
213
173
|
}
|
|
214
174
|
this.tools.get(tool.name)!.push(tool);
|
|
215
|
-
const estimatedTokens = ToolIndex.estimateTokens(tool);
|
|
216
175
|
this.toolSummaries.set(docKey, {
|
|
217
176
|
name: tool.name,
|
|
218
177
|
description: tool.description ?? '',
|
|
219
178
|
serverName: tool.serverName,
|
|
220
179
|
serverId: tool.serverId,
|
|
221
180
|
sessionId: tool.sessionId,
|
|
222
|
-
estimatedTokens,
|
|
223
181
|
});
|
|
224
|
-
this.totalTokenCost += estimatedTokens;
|
|
225
182
|
|
|
226
|
-
const
|
|
183
|
+
const rawText = this.buildSearchableText(tool);
|
|
184
|
+
const text = rawText.toLowerCase();
|
|
227
185
|
this.searchTexts.set(docKey, text);
|
|
228
186
|
|
|
229
|
-
const tokens = this.tokenize(
|
|
187
|
+
const tokens = this.tokenize(rawText);
|
|
230
188
|
const tf = new Map<string, number>();
|
|
231
189
|
const uniqueTokens = new Set<string>();
|
|
232
190
|
|
|
@@ -578,60 +536,107 @@ export class ToolIndex {
|
|
|
578
536
|
return count;
|
|
579
537
|
}
|
|
580
538
|
|
|
581
|
-
/** Total estimated token cost of all indexed tool schemas. */
|
|
582
|
-
getTotalTokenCost(): number {
|
|
583
|
-
return this.totalTokenCost;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
539
|
// -----------------------------------------------------------------------
|
|
587
|
-
//
|
|
540
|
+
// Internals
|
|
588
541
|
// -----------------------------------------------------------------------
|
|
589
542
|
|
|
590
|
-
/**
|
|
591
|
-
|
|
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 {
|
|
543
|
+
/** Build a single searchable string from tool metadata. */
|
|
544
|
+
private buildSearchableText(tool: Tool): string {
|
|
597
545
|
const parts: string[] = [tool.name];
|
|
598
546
|
if (tool.description) parts.push(tool.description);
|
|
599
|
-
if (tool.inputSchema) parts.push(JSON.stringify(tool.inputSchema));
|
|
600
547
|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
for (let i = 0; i < text.length; i++) {
|
|
605
|
-
weightedLen += 1 / classifyChar(text[i]);
|
|
548
|
+
if (tool.inputSchema && typeof tool.inputSchema === 'object') {
|
|
549
|
+
this.collectSchemaSearchText(tool.inputSchema, parts);
|
|
606
550
|
}
|
|
607
551
|
|
|
608
|
-
return
|
|
552
|
+
return parts.join(' ');
|
|
609
553
|
}
|
|
610
554
|
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
555
|
+
/** Recursively collect JSON Schema argument names and descriptions. */
|
|
556
|
+
private collectSchemaSearchText(
|
|
557
|
+
schema: unknown,
|
|
558
|
+
parts: string[],
|
|
559
|
+
seen = new WeakSet<object>()
|
|
560
|
+
): void {
|
|
561
|
+
if (!schema || typeof schema !== 'object') return;
|
|
562
|
+
if (seen.has(schema)) return;
|
|
563
|
+
seen.add(schema);
|
|
564
|
+
|
|
565
|
+
if (Array.isArray(schema)) {
|
|
566
|
+
for (const item of schema) {
|
|
567
|
+
this.collectSchemaSearchText(item, parts, seen);
|
|
568
|
+
}
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
614
571
|
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
if (tool.description) parts.push(tool.description);
|
|
572
|
+
const schemaObject = schema as Record<string, unknown>;
|
|
573
|
+
this.pushStringValue(schemaObject.description, parts);
|
|
574
|
+
this.pushStringValue(schemaObject.title, parts);
|
|
619
575
|
|
|
620
|
-
|
|
621
|
-
if (
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
576
|
+
const properties = schemaObject.properties;
|
|
577
|
+
if (properties && typeof properties === 'object' && !Array.isArray(properties)) {
|
|
578
|
+
for (const [propertyName, propertySchema] of Object.entries(properties)) {
|
|
579
|
+
parts.push(propertyName);
|
|
580
|
+
this.collectSchemaSearchText(propertySchema, parts, seen);
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
const patternProperties = schemaObject.patternProperties;
|
|
585
|
+
if (
|
|
586
|
+
patternProperties &&
|
|
587
|
+
typeof patternProperties === 'object' &&
|
|
588
|
+
!Array.isArray(patternProperties)
|
|
589
|
+
) {
|
|
590
|
+
for (const [propertyPattern, propertySchema] of Object.entries(patternProperties)) {
|
|
591
|
+
parts.push(propertyPattern);
|
|
592
|
+
this.collectSchemaSearchText(propertySchema, parts, seen);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
const dependentSchemas = schemaObject.dependentSchemas;
|
|
597
|
+
if (
|
|
598
|
+
dependentSchemas &&
|
|
599
|
+
typeof dependentSchemas === 'object' &&
|
|
600
|
+
!Array.isArray(dependentSchemas)
|
|
601
|
+
) {
|
|
602
|
+
for (const [propertyName, dependentSchema] of Object.entries(dependentSchemas)) {
|
|
603
|
+
parts.push(propertyName);
|
|
604
|
+
this.collectSchemaSearchText(dependentSchema, parts, seen);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
for (const key of [
|
|
609
|
+
'items',
|
|
610
|
+
'additionalProperties',
|
|
611
|
+
'contains',
|
|
612
|
+
'propertyNames',
|
|
613
|
+
'if',
|
|
614
|
+
'then',
|
|
615
|
+
'else',
|
|
616
|
+
'not',
|
|
617
|
+
]) {
|
|
618
|
+
this.collectSchemaSearchText(schemaObject[key], parts, seen);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
for (const key of ['allOf', 'anyOf', 'oneOf', 'prefixItems']) {
|
|
622
|
+
this.collectSchemaSearchText(schemaObject[key], parts, seen);
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
for (const key of ['$defs', 'definitions']) {
|
|
626
|
+
const definitions = schemaObject[key];
|
|
627
|
+
if (definitions && typeof definitions === 'object' && !Array.isArray(definitions)) {
|
|
628
|
+
for (const [definitionName, definitionSchema] of Object.entries(definitions)) {
|
|
629
|
+
parts.push(definitionName);
|
|
630
|
+
this.collectSchemaSearchText(definitionSchema, parts, seen);
|
|
630
631
|
}
|
|
631
632
|
}
|
|
632
633
|
}
|
|
634
|
+
}
|
|
633
635
|
|
|
634
|
-
|
|
636
|
+
private pushStringValue(value: unknown, parts: string[]): void {
|
|
637
|
+
if (typeof value === 'string' && value.trim()) {
|
|
638
|
+
parts.push(value);
|
|
639
|
+
}
|
|
635
640
|
}
|
|
636
641
|
|
|
637
642
|
private getDocumentKey(tool: IndexedTool): string {
|
|
@@ -662,6 +667,7 @@ export class ToolIndex {
|
|
|
662
667
|
.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
663
668
|
// Split snake_case / kebab-case
|
|
664
669
|
.replace(/[_-]/g, ' ')
|
|
670
|
+
.toLowerCase()
|
|
665
671
|
// Remove non-alphanumeric (except spaces)
|
|
666
672
|
.replace(/[^a-z0-9\s]/g, '')
|
|
667
673
|
// Split on whitespace
|
|
@@ -99,6 +99,17 @@ export interface ToolRouterOptions {
|
|
|
99
99
|
*/
|
|
100
100
|
compactSchemas?: boolean;
|
|
101
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Tool names to expose directly when using `search` strategy.
|
|
104
|
+
* Pinned tools are removed from discovery results and should be called directly.
|
|
105
|
+
*/
|
|
106
|
+
pinnedTools?: string[];
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Tool names or glob-style patterns to omit entirely from the router catalog.
|
|
110
|
+
*/
|
|
111
|
+
excludeTools?: string[];
|
|
112
|
+
|
|
102
113
|
/**
|
|
103
114
|
* Optional embedding function for semantic search.
|
|
104
115
|
* When not provided, keyword TF-IDF matching is used.
|
|
@@ -136,12 +147,16 @@ export type ToolRouterClientInput = ToolClientProvider | ToolClient[];
|
|
|
136
147
|
export class ToolRouter {
|
|
137
148
|
private index: ToolIndex;
|
|
138
149
|
private allTools: IndexedTool[] = [];
|
|
150
|
+
private pinnedTools: IndexedTool[] = [];
|
|
151
|
+
private discoverableTools: IndexedTool[] = [];
|
|
139
152
|
private groupsMap = new Map<string, ToolGroupInfo>();
|
|
140
153
|
private strategy: ToolRouterStrategy;
|
|
141
154
|
private maxTools: number;
|
|
142
155
|
private compactSchemas: boolean;
|
|
143
156
|
private activeGroups: Set<string>;
|
|
144
157
|
private customGroups?: Record<string, string[]>;
|
|
158
|
+
private pinnedToolNames: Set<string>;
|
|
159
|
+
private excludeToolMatchers: RegExp[];
|
|
145
160
|
private initialized = false;
|
|
146
161
|
|
|
147
162
|
constructor(
|
|
@@ -153,6 +168,10 @@ export class ToolRouter {
|
|
|
153
168
|
this.compactSchemas = options.compactSchemas ?? false;
|
|
154
169
|
this.activeGroups = new Set(options.activeGroups ?? []);
|
|
155
170
|
this.customGroups = options.groups;
|
|
171
|
+
this.pinnedToolNames = new Set(options.pinnedTools ?? []);
|
|
172
|
+
this.excludeToolMatchers = (options.excludeTools ?? []).map((pattern) =>
|
|
173
|
+
globToRegExp(pattern)
|
|
174
|
+
);
|
|
156
175
|
|
|
157
176
|
this.index = new ToolIndex({
|
|
158
177
|
embedFn: options.embedFn,
|
|
@@ -177,7 +196,7 @@ export class ToolRouter {
|
|
|
177
196
|
|
|
178
197
|
switch (this.strategy) {
|
|
179
198
|
case 'search':
|
|
180
|
-
return this.getMetaToolDefinitions();
|
|
199
|
+
return [...this.getMetaToolDefinitions(), ...this.pinnedTools];
|
|
181
200
|
|
|
182
201
|
case 'groups':
|
|
183
202
|
return this.getGroupFilteredTools();
|
|
@@ -290,30 +309,6 @@ export class ToolRouter {
|
|
|
290
309
|
return [...this.activeGroups];
|
|
291
310
|
}
|
|
292
311
|
|
|
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
312
|
/** Number of total indexed tools. */
|
|
318
313
|
get totalToolCount(): number {
|
|
319
314
|
return this.allTools.length;
|
|
@@ -376,8 +371,11 @@ export class ToolRouter {
|
|
|
376
371
|
private async ensureInitialized(): Promise<void> {
|
|
377
372
|
if (this.initialized) return;
|
|
378
373
|
|
|
379
|
-
|
|
380
|
-
|
|
374
|
+
const fetchedTools = await this.fetchAllTools();
|
|
375
|
+
this.allTools = fetchedTools.filter((tool) => !this.matchesExcludedTool(tool.name));
|
|
376
|
+
this.pinnedTools = this.allTools.filter((tool) => this.matchesPinnedTool(tool.name));
|
|
377
|
+
this.discoverableTools = this.allTools.filter((tool) => !this.matchesPinnedTool(tool.name));
|
|
378
|
+
await this.index.buildIndex(this.discoverableTools);
|
|
381
379
|
this.buildGroups();
|
|
382
380
|
this.initialized = true;
|
|
383
381
|
}
|
|
@@ -500,4 +498,17 @@ export class ToolRouter {
|
|
|
500
498
|
];
|
|
501
499
|
}
|
|
502
500
|
|
|
501
|
+
private matchesPinnedTool(toolName: string): boolean {
|
|
502
|
+
return this.pinnedToolNames.has(toolName);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
private matchesExcludedTool(toolName: string): boolean {
|
|
506
|
+
return this.excludeToolMatchers.some((matcher) => matcher.test(toolName));
|
|
507
|
+
}
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
function globToRegExp(pattern: string): RegExp {
|
|
511
|
+
const escaped = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
|
|
512
|
+
const regexPattern = `^${escaped.replace(/\*/g, '.*')}$`;
|
|
513
|
+
return new RegExp(regexPattern);
|
|
503
514
|
}
|
package/src/shared/types.ts
CHANGED
|
@@ -162,11 +162,12 @@ export function isCallToolSuccess(
|
|
|
162
162
|
export type ToolInfo = {
|
|
163
163
|
name: string;
|
|
164
164
|
description?: string;
|
|
165
|
-
inputSchema?:
|
|
165
|
+
inputSchema?: Tool['inputSchema'];
|
|
166
|
+
outputSchema?: Tool['outputSchema'];
|
|
166
167
|
};
|
|
167
168
|
|
|
168
169
|
// Transport type
|
|
169
|
-
export type TransportType = 'sse' | '
|
|
170
|
+
export type TransportType = 'sse' | 'streamable-http';
|
|
170
171
|
|
|
171
172
|
// SSE/RPC types
|
|
172
173
|
export type McpRpcMethod =
|
|
@@ -174,8 +175,8 @@ export type McpRpcMethod =
|
|
|
174
175
|
| 'disconnect'
|
|
175
176
|
| 'listTools'
|
|
176
177
|
| 'callTool'
|
|
177
|
-
| '
|
|
178
|
-
| '
|
|
178
|
+
| 'listSessions'
|
|
179
|
+
| 'getSession'
|
|
179
180
|
| 'finishAuth'
|
|
180
181
|
| 'listPrompts'
|
|
181
182
|
| 'getPrompt'
|
|
@@ -275,7 +276,7 @@ export interface DisconnectResult {
|
|
|
275
276
|
success: boolean;
|
|
276
277
|
}
|
|
277
278
|
|
|
278
|
-
export interface
|
|
279
|
+
export interface GetSessionResult {
|
|
279
280
|
success: boolean;
|
|
280
281
|
toolCount: number;
|
|
281
282
|
}
|
/package/{supabase/migrations → migrations/supabase}/20260421010000_add_session_cleanup_cron.sql
RENAMED
|
File without changes
|