claude-flow 2.7.33 → 2.7.35

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 (99) hide show
  1. package/.claude/settings.local.json +9 -2
  2. package/.claude/skills/agentic-jujutsu/SKILL.md +1 -1
  3. package/CHANGELOG.md +140 -0
  4. package/bin/claude-flow +1 -1
  5. package/dist/src/cli/commands/mcp.js +61 -7
  6. package/dist/src/cli/commands/mcp.js.map +1 -1
  7. package/dist/src/cli/init/index.js +55 -33
  8. package/dist/src/cli/init/index.js.map +1 -1
  9. package/dist/src/cli/simple-cli.js +182 -172
  10. package/dist/src/cli/simple-cli.js.map +1 -1
  11. package/dist/src/cli/simple-commands/init/agent-copier.js +9 -3
  12. package/dist/src/cli/simple-commands/init/agent-copier.js.map +1 -1
  13. package/dist/src/core/DatabaseManager.js +39 -9
  14. package/dist/src/core/DatabaseManager.js.map +1 -1
  15. package/dist/src/mcp/async/job-manager-mcp25.js +240 -0
  16. package/dist/src/mcp/async/job-manager-mcp25.js.map +1 -0
  17. package/dist/src/mcp/index.js +8 -0
  18. package/dist/src/mcp/index.js.map +1 -1
  19. package/dist/src/mcp/protocol/version-negotiation.js +182 -0
  20. package/dist/src/mcp/protocol/version-negotiation.js.map +1 -0
  21. package/dist/src/mcp/registry/mcp-registry-client-2025.js +210 -0
  22. package/dist/src/mcp/registry/mcp-registry-client-2025.js.map +1 -0
  23. package/dist/src/mcp/server-factory.js +189 -0
  24. package/dist/src/mcp/server-factory.js.map +1 -0
  25. package/dist/src/mcp/server-mcp-2025.js +283 -0
  26. package/dist/src/mcp/server-mcp-2025.js.map +1 -0
  27. package/dist/src/mcp/tool-registry-progressive.js +319 -0
  28. package/dist/src/mcp/tool-registry-progressive.js.map +1 -0
  29. package/dist/src/mcp/tools/_template.js +62 -0
  30. package/dist/src/mcp/tools/_template.js.map +1 -0
  31. package/dist/src/mcp/tools/loader.js +228 -0
  32. package/dist/src/mcp/tools/loader.js.map +1 -0
  33. package/dist/src/mcp/tools/system/search.js +224 -0
  34. package/dist/src/mcp/tools/system/search.js.map +1 -0
  35. package/dist/src/mcp/tools/system/status.js +168 -0
  36. package/dist/src/mcp/tools/system/status.js.map +1 -0
  37. package/dist/src/mcp/validation/schema-validator-2025.js +198 -0
  38. package/dist/src/mcp/validation/schema-validator-2025.js.map +1 -0
  39. package/dist/src/utils/error-recovery.js +215 -0
  40. package/dist/src/utils/error-recovery.js.map +1 -0
  41. package/dist/src/utils/metrics-reader.js +10 -0
  42. package/dist/src/utils/metrics-reader.js.map +1 -1
  43. package/docs/.claude-flow/metrics/performance.json +3 -3
  44. package/docs/.claude-flow/metrics/task-metrics.json +3 -3
  45. package/docs/.github-release-issue-v2.7.33.md +488 -0
  46. package/docs/AGENTDB_BRANCH_MERGE_VERIFICATION.md +436 -0
  47. package/docs/AUTOMATIC_ERROR_RECOVERY_v2.7.35.md +321 -0
  48. package/docs/BRANCH_REVIEW_SUMMARY.md +439 -0
  49. package/docs/CONFIRMATION_AUTOMATIC_ERROR_RECOVERY.md +384 -0
  50. package/docs/DEEP_CODE_REVIEW_v2.7.33.md +1159 -0
  51. package/docs/DOCKER_TEST_RESULTS_v2.7.35.md +305 -0
  52. package/docs/MCP_2025_FEATURE_CONFIRMATION.md +698 -0
  53. package/docs/NPM_PUBLISH_GUIDE_v2.7.33.md +628 -0
  54. package/docs/REGRESSION_TEST_REPORT_v2.7.33.md +397 -0
  55. package/docs/RELEASE_NOTES_v2.7.33.md +618 -0
  56. package/docs/RELEASE_READINESS_SUMMARY.md +377 -0
  57. package/docs/RELEASE_SUMMARY_v2.7.33.md +456 -0
  58. package/docs/agentic-flow-agentdb-mcp-integration.md +1198 -0
  59. package/docs/features/automatic-error-recovery.md +333 -0
  60. package/docs/github-issues/README.md +88 -0
  61. package/docs/github-issues/wsl-enotempty-automatic-recovery.md +470 -0
  62. package/docs/mcp-2025-implementation-summary.md +459 -0
  63. package/docs/mcp-spec-2025-implementation-plan.md +1330 -0
  64. package/docs/phase-1-2-implementation-summary.md +676 -0
  65. package/docs/regression-analysis-phase-1-2.md +555 -0
  66. package/docs/troubleshooting/wsl-better-sqlite3-error.md +239 -0
  67. package/package.json +5 -2
  68. package/scripts/create-github-issue.sh +64 -0
  69. package/scripts/test-docker-wsl.sh +198 -0
  70. package/src/cli/commands/mcp.ts +86 -9
  71. package/src/cli/init/index.ts +72 -42
  72. package/src/cli/simple-commands/init/agent-copier.js +10 -5
  73. package/src/core/DatabaseManager.ts +55 -9
  74. package/src/mcp/async/job-manager-mcp25.ts +456 -0
  75. package/src/mcp/index.ts +60 -0
  76. package/src/mcp/protocol/version-negotiation.ts +329 -0
  77. package/src/mcp/registry/mcp-registry-client-2025.ts +334 -0
  78. package/src/mcp/server-factory.ts +426 -0
  79. package/src/mcp/server-mcp-2025.ts +507 -0
  80. package/src/mcp/tool-registry-progressive.ts +539 -0
  81. package/src/mcp/tools/_template.ts +174 -0
  82. package/src/mcp/tools/loader.ts +362 -0
  83. package/src/mcp/tools/system/search.ts +276 -0
  84. package/src/mcp/tools/system/status.ts +206 -0
  85. package/src/mcp/validation/schema-validator-2025.ts +294 -0
  86. package/src/utils/error-recovery.ts +325 -0
  87. package/docs/AGENTDB_V1.6.1_DEEP_REVIEW.md +0 -386
  88. package/docs/AGENT_FOLDER_STRUCTURE_FIX.md +0 -192
  89. package/docs/RECENT_RELEASES_SUMMARY.md +0 -375
  90. package/docs/V2.7.31_RELEASE_NOTES.md +0 -375
  91. /package/.claude/agents/analysis/{analyze-code-quality.md → code-review/analyze-code-quality.md} +0 -0
  92. /package/.claude/agents/architecture/{arch-system-design.md → system-design/arch-system-design.md} +0 -0
  93. /package/.claude/agents/data/{data-ml-model.md → ml/data-ml-model.md} +0 -0
  94. /package/.claude/agents/development/{dev-backend-api.md → backend/dev-backend-api.md} +0 -0
  95. /package/.claude/agents/devops/{ops-cicd-github.md → ci-cd/ops-cicd-github.md} +0 -0
  96. /package/.claude/agents/documentation/{docs-api-openapi.md → api-docs/docs-api-openapi.md} +0 -0
  97. /package/.claude/agents/specialized/{spec-mobile-react-native.md → mobile/spec-mobile-react-native.md} +0 -0
  98. /package/.claude/agents/testing/{tdd-london-swarm.md → unit/tdd-london-swarm.md} +0 -0
  99. /package/.claude/agents/testing/{production-validator.md → validation/production-validator.md} +0 -0
@@ -0,0 +1,507 @@
1
+ /**
2
+ * MCP 2025-11 Enhanced Server
3
+ *
4
+ * Integrates all MCP 2025-11 features with full backward compatibility:
5
+ * - Version negotiation
6
+ * - Async job support
7
+ * - Registry integration
8
+ * - JSON Schema 1.1 validation
9
+ * - Dual-mode operation (2025-11 + legacy)
10
+ */
11
+
12
+ import type { ILogger } from '../interfaces/logger.js';
13
+ import type { IEventBus } from '../interfaces/event-bus.js';
14
+ import { VersionNegotiator, BackwardCompatibilityAdapter, type MCPHandshake, type MCPVersion, type MCPCapability } from './protocol/version-negotiation.js';
15
+ import { MCPAsyncJobManager, type MCPToolRequest, type MCPJobHandle, type MCPJobResult } from './async/job-manager-mcp25.js';
16
+ import { MCPRegistryClient, type RegistryConfig } from './registry/mcp-registry-client-2025.js';
17
+ import { SchemaValidator, upgradeToolSchema } from './validation/schema-validator-2025.js';
18
+ import { ProgressiveToolRegistry } from './tool-registry-progressive.js';
19
+
20
+ /**
21
+ * MCP 2025-11 server configuration
22
+ */
23
+ export interface MCP2025ServerConfig {
24
+ serverId: string;
25
+ transport: 'stdio' | 'http' | 'ws';
26
+
27
+ // Version & capabilities
28
+ enableMCP2025: boolean; // Feature flag for gradual rollout
29
+ supportLegacyClients: boolean; // Backward compatibility
30
+
31
+ // Async jobs
32
+ async: {
33
+ enabled: boolean;
34
+ maxJobs?: number;
35
+ jobTTL?: number;
36
+ persistence?: 'memory' | 'redis' | 'sqlite';
37
+ };
38
+
39
+ // Registry
40
+ registry: RegistryConfig;
41
+
42
+ // Schema validation
43
+ validation: {
44
+ enabled: boolean;
45
+ strictMode?: boolean;
46
+ };
47
+
48
+ // Tool registry
49
+ toolsDirectory?: string;
50
+
51
+ // Existing config
52
+ orchestratorContext?: any;
53
+ }
54
+
55
+ /**
56
+ * MCP 2025-11 Enhanced Server
57
+ */
58
+ export class MCP2025Server {
59
+ private versionNegotiator: VersionNegotiator;
60
+ private compatibilityAdapter: BackwardCompatibilityAdapter;
61
+ private jobManager?: MCPAsyncJobManager;
62
+ private registryClient?: MCPRegistryClient;
63
+ private schemaValidator: SchemaValidator;
64
+ private toolRegistry: ProgressiveToolRegistry;
65
+
66
+ // Session state
67
+ private sessions: Map<string, {
68
+ clientId: string;
69
+ version: MCPVersion;
70
+ capabilities: MCPCapability[];
71
+ isLegacy: boolean;
72
+ createdAt: number;
73
+ lastAccess: number;
74
+ }> = new Map();
75
+
76
+ // Session management constants
77
+ private readonly MAX_SESSIONS = 10000;
78
+ private readonly SESSION_TTL = 3600000; // 1 hour
79
+ private sessionCleanupInterval?: NodeJS.Timeout;
80
+
81
+ constructor(
82
+ private config: MCP2025ServerConfig,
83
+ private eventBus: IEventBus,
84
+ private logger: ILogger
85
+ ) {
86
+ // Initialize version negotiation
87
+ this.versionNegotiator = new VersionNegotiator(logger);
88
+ this.compatibilityAdapter = new BackwardCompatibilityAdapter(logger);
89
+
90
+ // Initialize schema validator
91
+ this.schemaValidator = new SchemaValidator(logger);
92
+
93
+ // Initialize tool registry (progressive)
94
+ this.toolRegistry = new ProgressiveToolRegistry({
95
+ enableInProcess: true,
96
+ enableMetrics: true,
97
+ enableCaching: true,
98
+ orchestratorContext: config.orchestratorContext,
99
+ toolsDirectory: config.toolsDirectory,
100
+ });
101
+
102
+ this.logger.info('MCP 2025-11 server created', {
103
+ serverId: config.serverId,
104
+ mcp2025Enabled: config.enableMCP2025,
105
+ legacySupport: config.supportLegacyClients,
106
+ });
107
+ }
108
+
109
+ /**
110
+ * Initialize server
111
+ */
112
+ async initialize(): Promise<void> {
113
+ this.logger.info('Initializing MCP 2025-11 server');
114
+
115
+ // Initialize tool registry
116
+ await this.toolRegistry.initialize();
117
+
118
+ // Start session cleanup interval
119
+ this.sessionCleanupInterval = setInterval(
120
+ () => this.cleanupExpiredSessions(),
121
+ 300000 // Every 5 minutes
122
+ );
123
+
124
+ // Initialize async job manager if enabled
125
+ if (this.config.async.enabled) {
126
+ this.jobManager = new MCPAsyncJobManager(
127
+ null, // Use memory persistence for now
128
+ this.logger,
129
+ {
130
+ maxJobs: this.config.async.maxJobs,
131
+ jobTTL: this.config.async.jobTTL,
132
+ }
133
+ );
134
+
135
+ this.logger.info('Async job manager initialized');
136
+ }
137
+
138
+ // Initialize registry client if enabled
139
+ if (this.config.registry.enabled) {
140
+ this.registryClient = new MCPRegistryClient(
141
+ this.config.registry,
142
+ this.logger,
143
+ () => this.toolRegistry.getToolNames(),
144
+ () => this.versionNegotiator.getServerCapabilities(),
145
+ async () => this.getHealthStatus()
146
+ );
147
+
148
+ // Register with MCP Registry
149
+ try {
150
+ await this.registryClient.register();
151
+ } catch (error) {
152
+ this.logger.error('Failed to register with MCP Registry', { error });
153
+ // Don't fail initialization if registry is unavailable
154
+ }
155
+ }
156
+
157
+ this.logger.info('MCP 2025-11 server initialized successfully');
158
+ }
159
+
160
+ /**
161
+ * Handle client connection/handshake
162
+ */
163
+ async handleHandshake(clientHandshake: any, sessionId: string): Promise<MCPHandshake> {
164
+ // Check if legacy client
165
+ const isLegacy = this.compatibilityAdapter.isLegacyRequest(clientHandshake);
166
+
167
+ let handshake: MCPHandshake;
168
+ if (isLegacy && this.config.supportLegacyClients) {
169
+ this.logger.info('Legacy client detected, enabling compatibility mode', { sessionId });
170
+ handshake = this.compatibilityAdapter.convertToModern(clientHandshake);
171
+ } else {
172
+ handshake = clientHandshake;
173
+ }
174
+
175
+ // Negotiate version and capabilities
176
+ const negotiation = await this.versionNegotiator.negotiate(handshake);
177
+
178
+ if (!negotiation.success) {
179
+ throw new Error(`Version negotiation failed: ${negotiation.error}`);
180
+ }
181
+
182
+ // Enforce session limit
183
+ if (this.sessions.size >= this.MAX_SESSIONS) {
184
+ // Remove oldest session
185
+ const oldestSession = Array.from(this.sessions.entries())
186
+ .sort((a, b) => a[1].createdAt - b[1].createdAt)[0];
187
+ if (oldestSession) {
188
+ this.sessions.delete(oldestSession[0]);
189
+ this.logger.warn('Session limit reached, removed oldest session', {
190
+ removedSessionId: oldestSession[0],
191
+ });
192
+ }
193
+ }
194
+
195
+ // Store session info
196
+ const now = Date.now();
197
+ this.sessions.set(sessionId, {
198
+ clientId: handshake.client_id || 'unknown',
199
+ version: negotiation.agreed_version,
200
+ capabilities: negotiation.agreed_capabilities,
201
+ isLegacy,
202
+ createdAt: now,
203
+ lastAccess: now,
204
+ });
205
+
206
+ // Create server handshake response
207
+ const serverHandshake = this.versionNegotiator.createServerHandshake(
208
+ this.config.serverId,
209
+ this.config.transport,
210
+ {
211
+ name: 'Claude Flow',
212
+ version: '2.7.32',
213
+ description: 'Enterprise AI orchestration with MCP 2025-11 support',
214
+ }
215
+ );
216
+
217
+ // Apply agreed version and capabilities
218
+ serverHandshake.mcp_version = negotiation.agreed_version;
219
+ serverHandshake.capabilities = negotiation.agreed_capabilities;
220
+
221
+ this.logger.info('Handshake completed', {
222
+ sessionId,
223
+ version: serverHandshake.mcp_version,
224
+ capabilities: serverHandshake.capabilities,
225
+ isLegacy,
226
+ });
227
+
228
+ return serverHandshake;
229
+ }
230
+
231
+ /**
232
+ * Handle tool call request (with async support)
233
+ */
234
+ async handleToolCall(
235
+ request: MCPToolRequest | any,
236
+ sessionId: string
237
+ ): Promise<MCPJobHandle | MCPJobResult | any> {
238
+ const session = this.sessions.get(sessionId);
239
+
240
+ // Update last access time
241
+ if (session) {
242
+ session.lastAccess = Date.now();
243
+ }
244
+
245
+ // Handle legacy request format
246
+ if (session?.isLegacy) {
247
+ return this.handleLegacyToolCall(request, sessionId);
248
+ }
249
+
250
+ // MCP 2025-11 format
251
+ const mcpRequest = request as MCPToolRequest;
252
+
253
+ // Validate request
254
+ if (!mcpRequest.tool_id) {
255
+ throw new Error('Missing tool_id in request');
256
+ }
257
+
258
+ // Get tool
259
+ const tool = await this.toolRegistry.getTool(mcpRequest.tool_id);
260
+ if (!tool) {
261
+ throw new Error(`Tool not found: ${mcpRequest.tool_id}`);
262
+ }
263
+
264
+ // Validate input if validation enabled
265
+ if (this.config.validation.enabled) {
266
+ const validation = this.schemaValidator.validateInput(
267
+ upgradeToolSchema(tool.inputSchema),
268
+ mcpRequest.arguments
269
+ );
270
+
271
+ if (!validation.valid) {
272
+ throw new Error(
273
+ `Invalid input: ${validation.errors?.map(e => e.message).join(', ')}`
274
+ );
275
+ }
276
+ }
277
+
278
+ // Check if async mode requested
279
+ const hasAsyncCapability = session?.capabilities.includes('async');
280
+ const isAsyncRequest = mcpRequest.mode === 'async' && hasAsyncCapability;
281
+
282
+ if (isAsyncRequest && this.jobManager) {
283
+ // Submit as async job
284
+ this.logger.info('Submitting async job', {
285
+ tool_id: mcpRequest.tool_id,
286
+ request_id: mcpRequest.request_id,
287
+ });
288
+
289
+ return await this.jobManager.submitJob(
290
+ mcpRequest,
291
+ async (args, onProgress) => {
292
+ // Execute tool with progress tracking
293
+ return await tool.handler(args, {
294
+ orchestrator: this.config.orchestratorContext,
295
+ sessionId,
296
+ });
297
+ }
298
+ );
299
+ } else {
300
+ // Execute synchronously
301
+ this.logger.info('Executing tool synchronously', {
302
+ tool_id: mcpRequest.tool_id,
303
+ request_id: mcpRequest.request_id,
304
+ });
305
+
306
+ const startTime = Date.now();
307
+ const result = await tool.handler(mcpRequest.arguments, {
308
+ orchestrator: this.config.orchestratorContext,
309
+ sessionId,
310
+ });
311
+
312
+ // Validate output if validation enabled
313
+ if (this.config.validation.enabled && tool.metadata?.outputSchema) {
314
+ const validation = this.schemaValidator.validateOutput(
315
+ tool.metadata.outputSchema,
316
+ result
317
+ );
318
+
319
+ if (!validation.valid) {
320
+ this.logger.warn('Output validation failed', {
321
+ tool_id: mcpRequest.tool_id,
322
+ errors: validation.errors,
323
+ });
324
+ }
325
+ }
326
+
327
+ // Return in MCP 2025-11 format
328
+ return {
329
+ request_id: mcpRequest.request_id,
330
+ status: 'success',
331
+ result,
332
+ metadata: {
333
+ duration_ms: Date.now() - startTime,
334
+ },
335
+ } as MCPJobResult;
336
+ }
337
+ }
338
+
339
+ /**
340
+ * Handle legacy tool call
341
+ */
342
+ private async handleLegacyToolCall(request: any, sessionId: string): Promise<any> {
343
+ this.logger.info('Handling legacy tool call', {
344
+ toolName: request.name || request.method,
345
+ sessionId,
346
+ });
347
+
348
+ // Convert to modern format internally
349
+ const toolId = request.name || request.method;
350
+ const args = request.arguments || request.params || {};
351
+
352
+ const tool = await this.toolRegistry.getTool(toolId);
353
+ if (!tool) {
354
+ throw new Error(`Tool not found: ${toolId}`);
355
+ }
356
+
357
+ const result = await tool.handler(args, {
358
+ orchestrator: this.config.orchestratorContext,
359
+ sessionId,
360
+ });
361
+
362
+ // Return in legacy format
363
+ return this.compatibilityAdapter.convertToLegacy(
364
+ { result, status: 'success' },
365
+ true
366
+ );
367
+ }
368
+
369
+ /**
370
+ * Poll async job
371
+ */
372
+ async pollJob(job_id: string): Promise<MCPJobHandle> {
373
+ if (!this.jobManager) {
374
+ throw new Error('Async jobs not enabled');
375
+ }
376
+
377
+ return await this.jobManager.pollJob(job_id);
378
+ }
379
+
380
+ /**
381
+ * Resume async job (get results)
382
+ */
383
+ async resumeJob(job_id: string): Promise<MCPJobResult> {
384
+ if (!this.jobManager) {
385
+ throw new Error('Async jobs not enabled');
386
+ }
387
+
388
+ return await this.jobManager.resumeJob(job_id);
389
+ }
390
+
391
+ /**
392
+ * Cancel async job
393
+ */
394
+ async cancelJob(job_id: string): Promise<boolean> {
395
+ if (!this.jobManager) {
396
+ throw new Error('Async jobs not enabled');
397
+ }
398
+
399
+ return await this.jobManager.cancelJob(job_id);
400
+ }
401
+
402
+ /**
403
+ * List async jobs
404
+ */
405
+ async listJobs(filter?: { status?: string; limit?: number }) {
406
+ if (!this.jobManager) {
407
+ throw new Error('Async jobs not enabled');
408
+ }
409
+
410
+ return await this.jobManager.listJobs(filter);
411
+ }
412
+
413
+ /**
414
+ * Get health status
415
+ */
416
+ private async getHealthStatus(): Promise<{
417
+ status: 'healthy' | 'degraded' | 'unhealthy';
418
+ latency_ms: number;
419
+ }> {
420
+ const startTime = Date.now();
421
+
422
+ // Perform health checks
423
+ const latency = Date.now() - startTime;
424
+
425
+ // Determine status based on metrics
426
+ let status: 'healthy' | 'degraded' | 'unhealthy' = 'healthy';
427
+
428
+ if (latency > 100) {
429
+ status = 'degraded';
430
+ }
431
+ if (latency > 500) {
432
+ status = 'unhealthy';
433
+ }
434
+
435
+ return { status, latency_ms: latency };
436
+ }
437
+
438
+ /**
439
+ * Get metrics
440
+ */
441
+ getMetrics() {
442
+ return {
443
+ sessions: {
444
+ total: this.sessions.size,
445
+ byVersion: this.getSessionsByVersion(),
446
+ legacy: Array.from(this.sessions.values()).filter(s => s.isLegacy).length,
447
+ },
448
+ jobs: this.jobManager?.getMetrics(),
449
+ tools: this.toolRegistry.getMetrics(),
450
+ validation: this.schemaValidator.getCacheStats(),
451
+ };
452
+ }
453
+
454
+ private getSessionsByVersion() {
455
+ const counts: Record<string, number> = {};
456
+ for (const session of this.sessions.values()) {
457
+ counts[session.version] = (counts[session.version] || 0) + 1;
458
+ }
459
+ return counts;
460
+ }
461
+
462
+ /**
463
+ * Cleanup expired sessions
464
+ */
465
+ private cleanupExpiredSessions(): void {
466
+ const now = Date.now();
467
+ let cleaned = 0;
468
+
469
+ for (const [sessionId, session] of this.sessions.entries()) {
470
+ // Remove if last access was more than TTL ago
471
+ if (now - session.lastAccess > this.SESSION_TTL) {
472
+ this.sessions.delete(sessionId);
473
+ cleaned++;
474
+ }
475
+ }
476
+
477
+ if (cleaned > 0) {
478
+ this.logger.info('Cleaned up expired sessions', { count: cleaned });
479
+ }
480
+ }
481
+
482
+ /**
483
+ * Cleanup resources
484
+ */
485
+ async cleanup(): Promise<void> {
486
+ this.logger.info('Cleaning up MCP 2025-11 server');
487
+
488
+ // Stop session cleanup interval
489
+ if (this.sessionCleanupInterval) {
490
+ clearInterval(this.sessionCleanupInterval);
491
+ }
492
+
493
+ // Unregister from registry
494
+ if (this.registryClient) {
495
+ await this.registryClient.unregister();
496
+ }
497
+
498
+ // Clear caches
499
+ this.schemaValidator.clearCache();
500
+ await this.toolRegistry.cleanup();
501
+
502
+ // Clear sessions
503
+ this.sessions.clear();
504
+
505
+ this.logger.info('Cleanup complete');
506
+ }
507
+ }