mcp-filter 1.0.1 → 1.0.2

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 (47) hide show
  1. package/README.md +23 -13
  2. package/dist/index.js +0 -0
  3. package/package.json +1 -1
  4. package/dist/core/config-loader.d.ts +0 -22
  5. package/dist/core/config-loader.d.ts.map +0 -1
  6. package/dist/core/config-loader.js +0 -308
  7. package/dist/core/config-loader.js.map +0 -1
  8. package/dist/core/config-schema.d.ts +0 -1363
  9. package/dist/core/config-schema.d.ts.map +0 -1
  10. package/dist/core/config-schema.js +0 -139
  11. package/dist/core/config-schema.js.map +0 -1
  12. package/dist/core/server-manager.d.ts +0 -51
  13. package/dist/core/server-manager.d.ts.map +0 -1
  14. package/dist/core/server-manager.js +0 -149
  15. package/dist/core/server-manager.js.map +0 -1
  16. package/dist/features/discovery/config-init.d.ts +0 -37
  17. package/dist/features/discovery/config-init.d.ts.map +0 -1
  18. package/dist/features/discovery/config-init.js +0 -95
  19. package/dist/features/discovery/config-init.js.map +0 -1
  20. package/dist/features/discovery/discovery-handler.d.ts +0 -128
  21. package/dist/features/discovery/discovery-handler.d.ts.map +0 -1
  22. package/dist/features/discovery/discovery-handler.js +0 -629
  23. package/dist/features/discovery/discovery-handler.js.map +0 -1
  24. package/dist/features/discovery/initialization.d.ts +0 -126
  25. package/dist/features/discovery/initialization.d.ts.map +0 -1
  26. package/dist/features/discovery/initialization.js +0 -314
  27. package/dist/features/discovery/initialization.js.map +0 -1
  28. package/dist/features/discovery/search-phase.d.ts +0 -19
  29. package/dist/features/discovery/search-phase.d.ts.map +0 -1
  30. package/dist/features/discovery/search-phase.js +0 -76
  31. package/dist/features/discovery/search-phase.js.map +0 -1
  32. package/dist/features/discovery/simple-rag.d.ts +0 -30
  33. package/dist/features/discovery/simple-rag.d.ts.map +0 -1
  34. package/dist/features/discovery/simple-rag.js +0 -85
  35. package/dist/features/discovery/simple-rag.js.map +0 -1
  36. package/dist/features/filtering/filter.d.ts +0 -18
  37. package/dist/features/filtering/filter.d.ts.map +0 -1
  38. package/dist/features/filtering/filter.js +0 -43
  39. package/dist/features/filtering/filter.js.map +0 -1
  40. package/dist/features/overrides/override-manager.d.ts +0 -25
  41. package/dist/features/overrides/override-manager.d.ts.map +0 -1
  42. package/dist/features/overrides/override-manager.js +0 -67
  43. package/dist/features/overrides/override-manager.js.map +0 -1
  44. package/dist/utils/debug-logger.d.ts +0 -2
  45. package/dist/utils/debug-logger.d.ts.map +0 -1
  46. package/dist/utils/debug-logger.js +0 -33
  47. package/dist/utils/debug-logger.js.map +0 -1
@@ -1,629 +0,0 @@
1
- import { SearchPhase } from "./search-phase.js";
2
- import { SimpleRAG } from "./simple-rag.js";
3
- import { ConfigInitializer } from "./config-init.js";
4
- import { logger } from "../../logger.js";
5
- import { z } from "zod";
6
- import { RequestSchema, ResultSchema } from "@modelcontextprotocol/sdk/types.js";
7
- // Zod schemas for custom request methods
8
- const DiscoverToolsRequestSchema = RequestSchema.extend({
9
- method: z.literal("discover_tools"),
10
- params: z.object({
11
- query: z.string().optional(),
12
- serverId: z.string().optional(),
13
- initialized: z.boolean().optional(),
14
- limit: z.number().int().positive().optional(),
15
- }).optional(),
16
- });
17
- const CallToolRequestSchema = RequestSchema.extend({
18
- method: z.literal("call_tool"),
19
- params: z.object({
20
- toolName: z.string(),
21
- toolArguments: z.record(z.any()).optional(),
22
- serverId: z.string().optional(),
23
- }),
24
- });
25
- const InitRequestSchema = RequestSchema.extend({
26
- method: z.literal("initialize_mcp_servers"),
27
- params: z.object({
28
- configPath: z.string().optional(),
29
- servers: z.array(z.object({
30
- id: z.string(),
31
- transport: z.any(),
32
- filters: z.object({
33
- include: z.array(z.string()).optional(),
34
- exclude: z.array(z.string()).optional(),
35
- }).optional(),
36
- enabled: z.boolean().optional(),
37
- })).optional(),
38
- }).optional(),
39
- });
40
- // Result schemas for custom methods
41
- const DiscoverToolsResultSchema = ResultSchema.extend({
42
- tools: z.array(z.object({
43
- name: z.string(),
44
- serverId: z.string(),
45
- description: z.string(),
46
- initialized: z.boolean(),
47
- arguments: z.array(z.object({
48
- name: z.string(),
49
- description: z.string(),
50
- })).optional(),
51
- })),
52
- servers: z.array(z.object({
53
- id: z.string(),
54
- initialized: z.boolean(),
55
- toolCount: z.number(),
56
- short_description: z.string().optional(),
57
- methodNames: z.array(z.string()).optional(),
58
- })),
59
- summary: z.object({
60
- totalTools: z.number(),
61
- searchEnabled: z.boolean(),
62
- message: z.string(),
63
- }).optional(),
64
- });
65
- // Init result is a union: either instructions (not initialized) or summary (initialized)
66
- const InitResultSchema = ResultSchema.extend({
67
- initialized: z.boolean(),
68
- }).and(z.union([
69
- // Not initialized - has instructions with RGC prompt
70
- z.object({
71
- initialized: z.literal(false),
72
- instructions: z.object({
73
- summary: z.string(),
74
- role: z.string().optional(),
75
- goal: z.string().optional(),
76
- context: z.string().optional(),
77
- servers: z.array(z.string()).optional(),
78
- steps: z.array(z.object({
79
- step: z.number(),
80
- action: z.string(),
81
- reason: z.string().optional(),
82
- note: z.string().optional(),
83
- })),
84
- important: z.string(),
85
- validationErrors: z.object({
86
- message: z.string(),
87
- errors: z.array(z.string()),
88
- help: z.string(),
89
- }).optional(),
90
- toolOverrides: z.object({
91
- note: z.string(),
92
- example: z.string(),
93
- }).optional(),
94
- }),
95
- }),
96
- // Initialized - has summary with concise server-level format
97
- z.object({
98
- initialized: z.literal(true),
99
- summary: z.object({
100
- totalTools: z.number(),
101
- connectedServers: z.array(z.object({
102
- id: z.string(),
103
- short_description: z.string().optional(),
104
- toolCount: z.number(),
105
- methodNames: z.array(z.string()).optional(),
106
- })),
107
- erroredServers: z.array(z.object({
108
- id: z.string(),
109
- short_description: z.string().optional(),
110
- error: z.string().optional(),
111
- })),
112
- }),
113
- descriptionPrompt: z.object({
114
- role: z.string(),
115
- goal: z.string(),
116
- context: z.string(),
117
- examples: z.array(z.string()),
118
- }),
119
- searchEnabled: z.boolean(),
120
- message: z.string(),
121
- }),
122
- ]));
123
- /**
124
- * Handles discovery-related MCP methods
125
- */
126
- export class DiscoveryHandler {
127
- serverManager;
128
- initializationTracker;
129
- overrideManager;
130
- searchPhase;
131
- simpleRAG;
132
- configInitializer;
133
- validationErrors;
134
- constructor(serverManager, initializationTracker, overrideManager, validationErrors) {
135
- this.serverManager = serverManager;
136
- this.initializationTracker = initializationTracker;
137
- this.overrideManager = overrideManager;
138
- this.searchPhase = new SearchPhase();
139
- this.simpleRAG = new SimpleRAG();
140
- this.configInitializer = new ConfigInitializer();
141
- this.validationErrors = validationErrors;
142
- }
143
- /**
144
- * Register discovery methods with the MCP server
145
- */
146
- registerHandlers(server) {
147
- // #region agent log
148
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:64', message: 'registerHandlers entry', data: { serverExists: !!server }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
149
- // #endregion
150
- // Register discover-tools method
151
- // #region agent log
152
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:67', message: 'registering discover-tools handler', data: { schemaType: typeof DiscoverToolsRequestSchema }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
153
- // #endregion
154
- // Register discover-tools method with result schema validation
155
- server.setRequestHandler(DiscoverToolsRequestSchema, async (request) => {
156
- // #region agent log
157
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:71', message: 'discover-tools handler called', data: { hasParams: !!request.params }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
158
- // #endregion
159
- const params = request.params;
160
- const result = await this.discoverTools(params || {});
161
- // Validate result against schema
162
- const validatedResult = DiscoverToolsResultSchema.parse(result);
163
- return validatedResult;
164
- });
165
- // Register initialize_mcp_servers method with result schema validation
166
- // #region agent log
167
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:79', message: 'registering initialize_mcp_servers handler', data: { schemaType: typeof InitRequestSchema }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
168
- // #endregion
169
- server.setRequestHandler(InitRequestSchema, async (request) => {
170
- // #region agent log
171
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:83', message: 'initialize_mcp_servers handler called', data: { hasParams: !!request.params }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
172
- // #endregion
173
- const params = request.params;
174
- const result = await this.init(params?.configPath, params?.servers);
175
- // #region agent log
176
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:226', message: 'init result before validation', data: { initialized: result.initialized, hasSummary: !!result.summary, hasInstructions: !!result.instructions, hasDescriptionPrompt: !!result.descriptionPrompt, hasSearchEnabled: typeof result.searchEnabled, hasMessage: !!result.message, summaryKeys: result.initialized ? Object.keys(result.summary || {}) : undefined, topLevelKeys: Object.keys(result) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
177
- // #endregion
178
- // Validate result against schema
179
- const validatedResult = InitResultSchema.parse(result);
180
- // #region agent log
181
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:230', message: 'init result validated', data: { initialized: validatedResult.initialized }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
182
- // #endregion
183
- return validatedResult;
184
- });
185
- // Register call_tool method
186
- server.setRequestHandler(CallToolRequestSchema, async (request) => {
187
- const params = request.params;
188
- return await this.callTool(params);
189
- });
190
- // #region agent log
191
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:96', message: 'registerHandlers completed', data: {}, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run2', hypothesisId: 'D' }) }).catch(() => { });
192
- // #endregion
193
- }
194
- /**
195
- * Call a specific tool from an upstream MCP server
196
- */
197
- async callTool(params) {
198
- const servers = params.serverId
199
- ? [this.serverManager.getServer(params.serverId)].filter((s) => s !== null && s !== undefined)
200
- : this.serverManager.getEnabledServers();
201
- const searchedServerNames = [];
202
- const uninitializedServerNames = [];
203
- // Find server with tool
204
- for (const server of servers) {
205
- if (!server)
206
- continue;
207
- if (!this.initializationTracker.isInitialized(server.id)) {
208
- uninitializedServerNames.push(server.id);
209
- continue;
210
- }
211
- searchedServerNames.push(server.id);
212
- try {
213
- const tools = await server.client.listTools();
214
- const tool = tools.tools.find((t) => t.name === params.toolName);
215
- if (tool && !server.filter.shouldExclude(tool.name)) {
216
- // Execute tool
217
- return await server.client.callTool({
218
- name: params.toolName,
219
- arguments: params.toolArguments || {},
220
- });
221
- }
222
- }
223
- catch (error) {
224
- // Continue searching
225
- }
226
- }
227
- // Check if it's an uninitialized server issue
228
- if (uninitializedServerNames.length > 0) {
229
- const error = this.initializationTracker.createInitializationError(uninitializedServerNames[0]);
230
- throw new Error(`${error.error.message}\n\n${JSON.stringify(error.initializationInstructions, null, 2)}`);
231
- }
232
- // Build error message with server names
233
- const serverList = searchedServerNames.length > 0
234
- ? ` Searched servers: ${searchedServerNames.join(", ")}.`
235
- : "";
236
- throw new Error(`Tool '${params.toolName}' not found or excluded.${serverList}`);
237
- }
238
- /**
239
- * Discover tools across all configured servers
240
- */
241
- async discoverTools(params) {
242
- // Check if we have any servers configured
243
- const allServers = this.serverManager.getAllServers();
244
- if (allServers.length === 0) {
245
- // Return empty response if no servers configured
246
- return {
247
- tools: [],
248
- servers: [],
249
- summary: {
250
- totalTools: 0,
251
- searchEnabled: false,
252
- message: "No servers configured. Call discover_tools to initialize.",
253
- },
254
- };
255
- }
256
- // Check if servers need initialization - if so, initialize them first
257
- const uninitializedServers = allServers.filter((server) => !this.initializationTracker.isInitialized(server.id));
258
- if (uninitializedServers.length > 0) {
259
- // Initialize servers by calling init() internally
260
- await this.init();
261
- // Continue with tool discovery even if some servers failed to initialize
262
- }
263
- const tools = [];
264
- const servers = params.serverId
265
- ? [this.serverManager.getServer(params.serverId)].filter(Boolean)
266
- : this.serverManager.getEnabledServers();
267
- for (const server of servers) {
268
- if (!server)
269
- continue;
270
- const isInitialized = this.initializationTracker.isInitialized(server.id);
271
- // Filter by initialization state if specified
272
- if (params.initialized !== undefined && params.initialized !== isInitialized) {
273
- continue;
274
- }
275
- try {
276
- if (!isInitialized) {
277
- // Return placeholder for uninitialized servers
278
- continue;
279
- }
280
- const upstreamTools = await server.client.listTools();
281
- const filteredTools = server.filter.filterList(upstreamTools.tools);
282
- for (const tool of filteredTools) {
283
- // Apply overrides
284
- const toolWithOverrides = this.overrideManager.applyOverrides(server.id, tool, true // Use brief descriptions
285
- );
286
- // Extract arguments
287
- const arguments_ = tool.inputSchema?.properties
288
- ? Object.entries(tool.inputSchema.properties).map(([name, prop]) => ({
289
- name,
290
- description: typeof prop === "object" && "description" in prop
291
- ? prop.description || ""
292
- : "",
293
- }))
294
- : undefined;
295
- tools.push({
296
- name: tool.name,
297
- serverId: server.id,
298
- description: toolWithOverrides.description || "",
299
- initialized: true,
300
- arguments: arguments_,
301
- });
302
- }
303
- }
304
- catch (error) {
305
- logger.error(`Error discovering tools from server ${server.id}: ${error}`);
306
- }
307
- }
308
- // Apply search if query provided - always use both algorithms
309
- let searchResults = tools;
310
- if (params.query) {
311
- const searchableTools = tools.map((t) => ({
312
- name: t.name,
313
- description: t.description,
314
- serverId: t.serverId,
315
- }));
316
- // Always use both phase (keyword) and RAG (semantic) search
317
- const ragResults = this.simpleRAG.search(searchableTools.map((t) => ({
318
- name: t.name,
319
- description: t.description,
320
- })), params.query);
321
- // Calculate phase (keyword) search scores using same logic as fuzzySearch
322
- const queryLower = params.query.toLowerCase();
323
- const phaseScoredResults = [];
324
- for (const tool of searchableTools) {
325
- // Filter by serverId if specified
326
- if (params.serverId && tool.serverId !== params.serverId) {
327
- continue;
328
- }
329
- let score = 0;
330
- // Exact match in name
331
- if (tool.name.toLowerCase() === queryLower) {
332
- score = 1.0;
333
- }
334
- // Name contains query
335
- else if (tool.name.toLowerCase().includes(queryLower)) {
336
- score = 0.8;
337
- }
338
- // Description contains query
339
- else if (tool.description?.toLowerCase().includes(queryLower)) {
340
- score = 0.6;
341
- }
342
- // Simple substring match
343
- else {
344
- const nameWords = tool.name.toLowerCase().split(/[_\-\s]+/);
345
- const queryWords = queryLower.split(/[_\-\s]+/);
346
- let matches = 0;
347
- for (const qw of queryWords) {
348
- if (nameWords.some((nw) => nw.includes(qw) || qw.includes(nw))) {
349
- matches++;
350
- }
351
- }
352
- if (matches > 0) {
353
- score = matches / Math.max(nameWords.length, queryWords.length);
354
- }
355
- }
356
- // Include if score > 0 (no threshold filtering, we'll combine with RAG)
357
- if (score > 0) {
358
- phaseScoredResults.push({ tool, score });
359
- }
360
- }
361
- // Build score map: tool key -> max confidence score from either algorithm
362
- const scoreMap = new Map();
363
- const toolMap = new Map(tools.map((t) => [`${t.name}:${t.serverId}`, t]));
364
- // Add phase search scores
365
- for (const result of phaseScoredResults) {
366
- const key = `${result.tool.name}:${result.tool.serverId}`;
367
- scoreMap.set(key, Math.max(scoreMap.get(key) ?? 0, result.score));
368
- }
369
- // Add RAG search scores (already has scores)
370
- for (const result of ragResults) {
371
- const matching = tools.find((t) => t.name === result.tool.name);
372
- if (matching) {
373
- const key = `${matching.name}:${matching.serverId}`;
374
- scoreMap.set(key, Math.max(scoreMap.get(key) ?? 0, result.score));
375
- }
376
- }
377
- // Combine results: include tools from either algorithm, sorted by highest confidence
378
- const scoredResults = Array.from(scoreMap.entries())
379
- .map(([key, score]) => ({
380
- tool: toolMap.get(key),
381
- score,
382
- }))
383
- .filter((r) => r.tool !== undefined)
384
- .sort((a, b) => b.score - a.score) // Sort by confidence descending
385
- .map((r) => r.tool);
386
- searchResults = scoredResults;
387
- }
388
- // Apply limit (default: 3) - results are already sorted by highest confidence
389
- const limit = params.limit ?? 3;
390
- const limitedResults = searchResults.slice(0, limit);
391
- // Build server status
392
- const serverStatus = this.serverManager
393
- .getEnabledServers()
394
- .map((server) => {
395
- const shortDescription = server.config.short_description ||
396
- server.config.shortDescription ||
397
- undefined;
398
- const serverTools = searchResults.filter((t) => t.serverId === server.id);
399
- return {
400
- id: server.id,
401
- initialized: this.initializationTracker.isInitialized(server.id),
402
- toolCount: serverTools.length,
403
- short_description: shortDescription && shortDescription.length < 100 ? shortDescription : undefined,
404
- methodNames: serverTools.map((t) => t.name),
405
- };
406
- });
407
- // If initialized and no query, return summary format
408
- const allInitialized = serverStatus.every((s) => s.initialized);
409
- if (allInitialized && !params.query) {
410
- return {
411
- tools: limitedResults,
412
- servers: serverStatus,
413
- summary: {
414
- totalTools: searchResults.length,
415
- searchEnabled: true,
416
- message: `Found ${searchResults.length} tool(s) across ${serverStatus.length} server(s). Showing ${limitedResults.length} of ${searchResults.length} (limit: ${limit}). Use query parameter for semantic search.`,
417
- },
418
- };
419
- }
420
- return {
421
- tools: limitedResults,
422
- servers: serverStatus,
423
- };
424
- }
425
- /**
426
- * Single unified method: returns initialization instructions if not initialized,
427
- * or returns tool summaries from config if initialized
428
- */
429
- async init(configPath, servers) {
430
- const allServers = this.serverManager.getAllServers();
431
- // Stage 1: No config file - no servers configured
432
- if (allServers.length === 0) {
433
- const initError = this.initializationTracker.createConfigInitError();
434
- return {
435
- initialized: false,
436
- instructions: {
437
- summary: initError.initializationInstructions.summary,
438
- role: initError.initializationInstructions.role,
439
- goal: initError.initializationInstructions.goal,
440
- context: initError.initializationInstructions.context,
441
- steps: initError.initializationInstructions.steps,
442
- important: initError.initializationInstructions.important,
443
- },
444
- };
445
- }
446
- // Stage 2: Invalid config file - validation errors exist
447
- if (this.validationErrors && !this.validationErrors.valid) {
448
- const invalidConfigError = this.initializationTracker.createInvalidConfigError(this.validationErrors.formattedErrors || []);
449
- return {
450
- initialized: false,
451
- instructions: {
452
- summary: invalidConfigError.summary,
453
- role: invalidConfigError.role,
454
- goal: invalidConfigError.goal,
455
- context: invalidConfigError.context,
456
- steps: invalidConfigError.steps,
457
- important: invalidConfigError.important,
458
- validationErrors: invalidConfigError.validationErrors,
459
- },
460
- };
461
- }
462
- // Stage 3: Valid config but servers not initialized
463
- const uninitializedServers = allServers.filter((server) => !this.initializationTracker.isInitialized(server.id));
464
- // #region agent log
465
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:506', message: 'Stage 3 check', data: { allServersCount: allServers.length, uninitializedCount: uninitializedServers.length, uninitializedIds: uninitializedServers.map(s => s.id), initializationStatus: allServers.map(s => ({ id: s.id, initialized: this.initializationTracker.isInitialized(s.id) })) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
466
- // #endregion
467
- if (uninitializedServers.length > 0) {
468
- // Actually connect to servers when discover_tools is called (code performs initialization)
469
- // Retry connection up to 3 times with delays for servers that might not be ready
470
- // #region agent log
471
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:510', message: 'Stage 3 connecting servers', data: { uninitializedIds: uninitializedServers.map(s => s.id) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
472
- // #endregion
473
- for (const server of uninitializedServers) {
474
- let connected = false;
475
- for (let attempt = 0; attempt < 3; attempt++) {
476
- try {
477
- // #region agent log
478
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:515', message: 'connection attempt', data: { serverId: server.id, attempt: attempt + 1 }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
479
- // #endregion
480
- await this.serverManager.connectServer(server.id);
481
- // #region agent log
482
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:518', message: 'connection attempt succeeded', data: { serverId: server.id, attempt: attempt + 1, isInitialized: this.initializationTracker.isInitialized(server.id) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
483
- // #endregion
484
- connected = true;
485
- break;
486
- }
487
- catch (error) {
488
- // #region agent log
489
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:522', message: 'connection attempt failed', data: { serverId: server.id, attempt: attempt + 1, errorMessage: error instanceof Error ? error.message : String(error) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
490
- // #endregion
491
- if (attempt < 2) {
492
- // Wait a bit before retrying
493
- await new Promise(resolve => setTimeout(resolve, 500));
494
- }
495
- else {
496
- logger.error(`Failed to connect to server ${server.id} after ${attempt + 1} attempts: ${error}`);
497
- }
498
- }
499
- }
500
- if (!connected) {
501
- // #region agent log
502
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:530', message: 'server connection failed after retries', data: { serverId: server.id, isInitialized: this.initializationTracker.isInitialized(server.id) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'B' }) }).catch(() => { });
503
- // #endregion
504
- logger.warn(`Server ${server.id} could not be connected after retries`);
505
- }
506
- }
507
- // After connecting, check if all servers are now initialized
508
- const stillUninitialized = allServers.filter((server) => !this.initializationTracker.isInitialized(server.id));
509
- // #region agent log
510
- fetch('http://127.0.0.1:7243/ingest/198b6a8b-7e4f-4c81-a922-32b1e2e171c8', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ location: 'discovery-handler.ts:535', message: 'Stage 3 after connection attempts', data: { stillUninitializedCount: stillUninitialized.length, stillUninitializedIds: stillUninitialized.map(s => s.id), initializationStatus: allServers.map(s => ({ id: s.id, initialized: this.initializationTracker.isInitialized(s.id) })) }, timestamp: Date.now(), sessionId: 'debug-session', runId: 'run1', hypothesisId: 'D' }) }).catch(() => { });
511
- // #endregion
512
- if (stillUninitialized.length > 0) {
513
- // Some servers failed to initialize - return instructions
514
- const instructions = this.initializationTracker.createInitInstructions(stillUninitialized.map((s) => s.id));
515
- return {
516
- initialized: false,
517
- instructions: {
518
- summary: instructions.summary,
519
- role: instructions.role,
520
- goal: instructions.goal,
521
- context: instructions.context,
522
- servers: instructions.servers,
523
- steps: instructions.steps,
524
- important: instructions.important,
525
- toolOverrides: instructions.toolOverrides,
526
- },
527
- };
528
- }
529
- // All servers initialized - fall through to Stage 4
530
- }
531
- // Stage 4: All servers are initialized - return concise server-level summaries
532
- // Check if config file needs to be created (for backward compatibility)
533
- const needsConfig = servers && servers.length > 0;
534
- if (needsConfig) {
535
- const path = configPath || ".mcp-filter.json";
536
- try {
537
- await this.configInitializer.initConfig(path, servers);
538
- }
539
- catch (error) {
540
- logger.error(`Failed to create config file: ${error}`);
541
- // Continue even if config creation fails
542
- }
543
- }
544
- // Collect server information for concise summaries and RGC prompt
545
- const connectedServers = [];
546
- const erroredServers = [];
547
- const serverInfoForPrompt = [];
548
- let totalTools = 0;
549
- for (const server of allServers) {
550
- // Only process initialized servers
551
- if (!this.initializationTracker.isInitialized(server.id)) {
552
- // Server not initialized - add to errored servers
553
- const shortDescription = server.config.short_description ||
554
- server.config.shortDescription ||
555
- undefined;
556
- erroredServers.push({
557
- id: server.id,
558
- short_description: shortDescription && shortDescription.length < 100 ? shortDescription : undefined,
559
- error: "Server not initialized",
560
- });
561
- continue;
562
- }
563
- try {
564
- const toolsResponse = await server.client.listTools();
565
- const filteredTools = server.filter.filterList(toolsResponse.tools);
566
- const toolNames = filteredTools.map((t) => t.name);
567
- totalTools += toolNames.length;
568
- // Get short_description from config if available
569
- // Check both new format (mcpServers) and old format (servers) config
570
- const shortDescription = server.config.short_description ||
571
- server.config.shortDescription ||
572
- undefined;
573
- connectedServers.push({
574
- id: server.id,
575
- short_description: shortDescription && shortDescription.length < 100 ? shortDescription : undefined,
576
- toolCount: toolNames.length,
577
- toolNames,
578
- });
579
- serverInfoForPrompt.push({
580
- id: server.id,
581
- toolNames,
582
- });
583
- }
584
- catch (error) {
585
- logger.error(`Error listing tools from server ${server.id}: ${error}`);
586
- const shortDescription = server.config.short_description ||
587
- server.config.shortDescription ||
588
- undefined;
589
- erroredServers.push({
590
- id: server.id,
591
- short_description: shortDescription && shortDescription.length < 100 ? shortDescription : undefined,
592
- error: error instanceof Error ? error.message : String(error),
593
- });
594
- }
595
- }
596
- // Create RGC prompt for generating short_description
597
- const descriptionPrompt = this.initializationTracker.createShortDescriptionPrompt(serverInfoForPrompt);
598
- return {
599
- initialized: true,
600
- summary: {
601
- totalTools,
602
- connectedServers: connectedServers.map((s) => ({
603
- id: s.id,
604
- short_description: s.short_description,
605
- toolCount: s.toolCount,
606
- methodNames: s.toolNames,
607
- })),
608
- erroredServers: erroredServers.map((s) => ({
609
- id: s.id,
610
- short_description: s.short_description,
611
- error: s.error,
612
- })),
613
- },
614
- descriptionPrompt: {
615
- role: descriptionPrompt.role,
616
- goal: descriptionPrompt.goal,
617
- context: descriptionPrompt.context,
618
- examples: descriptionPrompt.examples,
619
- },
620
- searchEnabled: true,
621
- message: `Found ${totalTools} tool(s) across ${connectedServers.length} server(s). Use discover_tools with query parameter for semantic search.\n\n` +
622
- `OPTIONAL: Optimize tool names and descriptions using 'toolOverrides' in .mcp-filter.json. ` +
623
- `Only optimize when necessary: non-English names, excessively long names (>50 chars), or unclear descriptions. ` +
624
- `Don't optimize if names are already short, clear, and in English. ` +
625
- `Only include information the LLM doesn't already know - remove obvious information that's clear from the name.`,
626
- };
627
- }
628
- }
629
- //# sourceMappingURL=discovery-handler.js.map