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,456 @@
1
+ /**
2
+ * MCP 2025-11 Async Job Manager
3
+ *
4
+ * Implements async job lifecycle per MCP 2025-11 specification:
5
+ * - Job handles with request_id
6
+ * - Poll/resume semantics
7
+ * - Progress tracking
8
+ * - Job persistence
9
+ */
10
+
11
+ import { EventEmitter } from 'events';
12
+ import { v4 as uuidv4 } from 'uuid';
13
+ import type { ILogger } from '../../interfaces/logger.js';
14
+
15
+ /**
16
+ * MCP tool request (2025-11 format)
17
+ */
18
+ export interface MCPToolRequest {
19
+ request_id: string;
20
+ tool_id: string;
21
+ arguments: Record<string, any>;
22
+ session?: string;
23
+ mode: 'async' | 'sync';
24
+ context?: {
25
+ trace_id?: string;
26
+ client_name?: string;
27
+ [key: string]: any;
28
+ };
29
+ }
30
+
31
+ /**
32
+ * MCP job handle (2025-11 format)
33
+ */
34
+ export interface MCPJobHandle {
35
+ request_id: string;
36
+ job_id: string;
37
+ status: 'in_progress' | 'success' | 'error';
38
+ poll_after: number; // seconds
39
+ progress?: {
40
+ percent: number;
41
+ message?: string;
42
+ };
43
+ }
44
+
45
+ /**
46
+ * MCP job result (2025-11 format)
47
+ */
48
+ export interface MCPJobResult {
49
+ request_id: string;
50
+ status: 'success' | 'error' | 'in_progress';
51
+ result?: any;
52
+ error?: {
53
+ code: string;
54
+ message: string;
55
+ details?: any;
56
+ };
57
+ progress?: {
58
+ percent: number;
59
+ message?: string;
60
+ };
61
+ metadata: {
62
+ duration_ms?: number;
63
+ tokens_used?: number;
64
+ [key: string]: any;
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Internal job state
70
+ */
71
+ interface AsyncJob {
72
+ request_id: string;
73
+ job_id: string;
74
+ tool_id: string;
75
+ arguments: Record<string, any>;
76
+ mode: 'async' | 'sync';
77
+ status: 'queued' | 'running' | 'success' | 'error' | 'cancelled';
78
+ progress: number;
79
+ progress_message?: string;
80
+ result?: any;
81
+ error?: any;
82
+ context?: any;
83
+ created_at: Date;
84
+ started_at?: Date;
85
+ completed_at?: Date;
86
+ tokens_used?: number;
87
+ abortController?: AbortController;
88
+ }
89
+
90
+ /**
91
+ * Job persistence interface
92
+ */
93
+ export interface JobPersistence {
94
+ save(job: AsyncJob): Promise<void>;
95
+ load(job_id: string): Promise<AsyncJob | null>;
96
+ list(filter?: { status?: string; limit?: number }): Promise<AsyncJob[]>;
97
+ delete(job_id: string): Promise<void>;
98
+ }
99
+
100
+ /**
101
+ * Simple in-memory job persistence (fallback)
102
+ */
103
+ export class MemoryJobPersistence implements JobPersistence {
104
+ private jobs: Map<string, AsyncJob> = new Map();
105
+
106
+ async save(job: AsyncJob): Promise<void> {
107
+ this.jobs.set(job.job_id, { ...job });
108
+ }
109
+
110
+ async load(job_id: string): Promise<AsyncJob | null> {
111
+ const job = this.jobs.get(job_id);
112
+ return job ? { ...job } : null;
113
+ }
114
+
115
+ async list(filter?: { status?: string; limit?: number }): Promise<AsyncJob[]> {
116
+ let jobs = Array.from(this.jobs.values());
117
+
118
+ if (filter?.status) {
119
+ jobs = jobs.filter(j => j.status === filter.status);
120
+ }
121
+
122
+ if (filter?.limit) {
123
+ jobs = jobs.slice(0, filter.limit);
124
+ }
125
+
126
+ return jobs;
127
+ }
128
+
129
+ async delete(job_id: string): Promise<void> {
130
+ this.jobs.delete(job_id);
131
+ }
132
+ }
133
+
134
+ /**
135
+ * MCP 2025-11 Async Job Manager
136
+ */
137
+ export class MCPAsyncJobManager extends EventEmitter {
138
+ private jobs: Map<string, AsyncJob> = new Map();
139
+ private executors: Map<string, Promise<any>> = new Map();
140
+ private persistence: JobPersistence;
141
+
142
+ constructor(
143
+ persistence: JobPersistence | null,
144
+ private logger: ILogger,
145
+ private config: {
146
+ maxJobs?: number;
147
+ jobTTL?: number;
148
+ defaultPollInterval?: number;
149
+ } = {}
150
+ ) {
151
+ super();
152
+ this.persistence = persistence || new MemoryJobPersistence();
153
+
154
+ // Default config
155
+ this.config.maxJobs = this.config.maxJobs || 1000;
156
+ this.config.jobTTL = this.config.jobTTL || 86400000; // 24 hours
157
+ this.config.defaultPollInterval = this.config.defaultPollInterval || 5;
158
+
159
+ // Cleanup expired jobs periodically
160
+ setInterval(() => this.cleanupExpiredJobs(), 3600000); // Every hour
161
+ }
162
+
163
+ /**
164
+ * Submit async job (MCP 2025-11 format)
165
+ */
166
+ async submitJob(
167
+ request: MCPToolRequest,
168
+ executor: (args: any, onProgress: (percent: number, message?: string) => void) => Promise<any>
169
+ ): Promise<MCPJobHandle> {
170
+ // Check capacity
171
+ if (this.jobs.size >= this.config.maxJobs!) {
172
+ throw new Error('Job queue full. Please try again later.');
173
+ }
174
+
175
+ // Check for duplicate request_id (prevent race conditions)
176
+ const existingJob = Array.from(this.jobs.values()).find(
177
+ j => j.request_id === request.request_id &&
178
+ (j.status === 'queued' || j.status === 'running')
179
+ );
180
+ if (existingJob) {
181
+ throw new Error(`Duplicate request_id: ${request.request_id}. Job already submitted.`);
182
+ }
183
+
184
+ // Create job
185
+ const job: AsyncJob = {
186
+ request_id: request.request_id,
187
+ job_id: uuidv4(),
188
+ tool_id: request.tool_id,
189
+ arguments: request.arguments,
190
+ mode: request.mode,
191
+ status: 'queued',
192
+ progress: 0,
193
+ context: request.context,
194
+ created_at: new Date(),
195
+ };
196
+
197
+ // Save to persistence
198
+ await this.persistence.save(job);
199
+ this.jobs.set(job.job_id, job);
200
+
201
+ this.logger.info('Job submitted', {
202
+ job_id: job.job_id,
203
+ request_id: job.request_id,
204
+ tool_id: job.tool_id,
205
+ });
206
+
207
+ // Start execution in background
208
+ this.executeJob(job, executor);
209
+
210
+ // Return job handle immediately
211
+ return {
212
+ request_id: job.request_id,
213
+ job_id: job.job_id,
214
+ status: 'in_progress',
215
+ poll_after: this.config.defaultPollInterval!,
216
+ };
217
+ }
218
+
219
+ /**
220
+ * Poll job status
221
+ */
222
+ async pollJob(job_id: string): Promise<MCPJobHandle> {
223
+ const job = await this.persistence.load(job_id);
224
+
225
+ if (!job) {
226
+ throw new Error(`Job not found: ${job_id}`);
227
+ }
228
+
229
+ const status = job.status === 'success' ? 'success' :
230
+ job.status === 'error' ? 'error' : 'in_progress';
231
+
232
+ const handle: MCPJobHandle = {
233
+ request_id: job.request_id,
234
+ job_id: job.job_id,
235
+ status,
236
+ poll_after: status === 'in_progress' ? this.config.defaultPollInterval! : 0,
237
+ };
238
+
239
+ if (status === 'in_progress') {
240
+ handle.progress = {
241
+ percent: job.progress,
242
+ message: job.progress_message,
243
+ };
244
+ }
245
+
246
+ return handle;
247
+ }
248
+
249
+ /**
250
+ * Resume job (get results)
251
+ */
252
+ async resumeJob(job_id: string): Promise<MCPJobResult> {
253
+ const job = await this.persistence.load(job_id);
254
+
255
+ if (!job) {
256
+ throw new Error(`Job not found: ${job_id}`);
257
+ }
258
+
259
+ const result: MCPJobResult = {
260
+ request_id: job.request_id,
261
+ status: job.status === 'success' ? 'success' :
262
+ job.status === 'error' ? 'error' : 'in_progress',
263
+ metadata: {},
264
+ };
265
+
266
+ if (job.status === 'success') {
267
+ result.result = job.result;
268
+ result.metadata.duration_ms = job.completed_at && job.started_at
269
+ ? job.completed_at.getTime() - job.started_at.getTime()
270
+ : undefined;
271
+ result.metadata.tokens_used = job.tokens_used;
272
+ } else if (job.status === 'error') {
273
+ result.error = {
274
+ code: 'EXECUTION_ERROR',
275
+ message: job.error?.message || 'Job execution failed',
276
+ details: job.error,
277
+ };
278
+ } else {
279
+ // Still in progress
280
+ result.progress = {
281
+ percent: job.progress,
282
+ message: job.progress_message,
283
+ };
284
+ }
285
+
286
+ return result;
287
+ }
288
+
289
+ /**
290
+ * Cancel a running job
291
+ */
292
+ async cancelJob(job_id: string): Promise<boolean> {
293
+ const job = this.jobs.get(job_id);
294
+
295
+ if (!job) {
296
+ return false;
297
+ }
298
+
299
+ if (job.status === 'success' || job.status === 'error') {
300
+ return false; // Already finished
301
+ }
302
+
303
+ // Abort execution if AbortController is available
304
+ if (job.abortController) {
305
+ job.abortController.abort();
306
+ }
307
+
308
+ job.status = 'cancelled';
309
+ job.completed_at = new Date();
310
+ await this.persistence.save(job);
311
+
312
+ this.emit('job:cancelled', job_id);
313
+ this.logger.info('Job cancelled', { job_id });
314
+
315
+ return true;
316
+ }
317
+
318
+ /**
319
+ * List jobs
320
+ */
321
+ async listJobs(filter?: {
322
+ status?: string;
323
+ limit?: number;
324
+ }): Promise<AsyncJob[]> {
325
+ return await this.persistence.list(filter);
326
+ }
327
+
328
+ /**
329
+ * Execute job in background
330
+ */
331
+ private async executeJob(
332
+ job: AsyncJob,
333
+ executor: (args: any, onProgress: (percent: number, message?: string) => void) => Promise<any>
334
+ ): Promise<void> {
335
+ // Update status to running
336
+ job.status = 'running';
337
+ job.started_at = new Date();
338
+
339
+ // Create AbortController for cancellation support
340
+ job.abortController = new AbortController();
341
+
342
+ await this.persistence.save(job);
343
+
344
+ this.emit('job:started', job.job_id);
345
+ this.logger.info('Job started', { job_id: job.job_id, tool_id: job.tool_id });
346
+
347
+ try {
348
+ // Progress callback
349
+ const onProgress = (percent: number, message?: string) => {
350
+ job.progress = Math.min(100, Math.max(0, percent));
351
+ job.progress_message = message;
352
+ this.persistence.save(job).catch(err =>
353
+ this.logger.error('Failed to save progress', { job_id: job.job_id, error: err })
354
+ );
355
+ this.emit('job:progress', job.job_id, job.progress, message);
356
+ };
357
+
358
+ // Check if already cancelled
359
+ if (job.abortController.signal.aborted) {
360
+ throw new Error('Job cancelled before execution');
361
+ }
362
+
363
+ // Execute with abort support
364
+ const result = await executor(job.arguments, onProgress);
365
+
366
+ // Mark successful
367
+ job.status = 'success';
368
+ job.result = result;
369
+ job.progress = 100;
370
+ job.completed_at = new Date();
371
+ await this.persistence.save(job);
372
+
373
+ this.emit('job:completed', job.job_id, result);
374
+ this.logger.info('Job completed', {
375
+ job_id: job.job_id,
376
+ duration_ms: job.completed_at.getTime() - job.started_at!.getTime(),
377
+ });
378
+ } catch (error: any) {
379
+ // Mark failed
380
+ job.status = 'error';
381
+ job.error = {
382
+ message: error.message,
383
+ stack: error.stack,
384
+ code: error.code,
385
+ };
386
+ job.completed_at = new Date();
387
+ await this.persistence.save(job);
388
+
389
+ this.emit('job:failed', job.job_id, error);
390
+ this.logger.error('Job failed', {
391
+ job_id: job.job_id,
392
+ error: error.message,
393
+ });
394
+ }
395
+ }
396
+
397
+ /**
398
+ * Cleanup expired jobs
399
+ */
400
+ private async cleanupExpiredJobs(): Promise<number> {
401
+ const now = Date.now();
402
+ const jobs = await this.persistence.list();
403
+ let cleaned = 0;
404
+
405
+ for (const job of jobs) {
406
+ const age = now - job.created_at.getTime();
407
+
408
+ // Remove if expired and not running
409
+ if (age > this.config.jobTTL! && job.status !== 'running') {
410
+ await this.persistence.delete(job.job_id);
411
+ this.jobs.delete(job.job_id);
412
+ cleaned++;
413
+ }
414
+ }
415
+
416
+ if (cleaned > 0) {
417
+ this.logger.info('Cleaned up expired jobs', { count: cleaned });
418
+ }
419
+
420
+ return cleaned;
421
+ }
422
+
423
+ /**
424
+ * Get metrics
425
+ */
426
+ getMetrics() {
427
+ const jobs = Array.from(this.jobs.values());
428
+
429
+ return {
430
+ total: jobs.length,
431
+ byStatus: {
432
+ queued: jobs.filter(j => j.status === 'queued').length,
433
+ running: jobs.filter(j => j.status === 'running').length,
434
+ success: jobs.filter(j => j.status === 'success').length,
435
+ error: jobs.filter(j => j.status === 'error').length,
436
+ cancelled: jobs.filter(j => j.status === 'cancelled').length,
437
+ },
438
+ averageDuration: this.calculateAverageDuration(jobs),
439
+ };
440
+ }
441
+
442
+ private calculateAverageDuration(jobs: AsyncJob[]): number {
443
+ const completed = jobs.filter(j =>
444
+ (j.status === 'success' || j.status === 'error') &&
445
+ j.started_at && j.completed_at
446
+ );
447
+
448
+ if (completed.length === 0) return 0;
449
+
450
+ const total = completed.reduce((sum, j) =>
451
+ sum + (j.completed_at!.getTime() - j.started_at!.getTime()), 0
452
+ );
453
+
454
+ return total / completed.length;
455
+ }
456
+ }
package/src/mcp/index.ts CHANGED
@@ -27,6 +27,66 @@ export type { SDKIntegrationConfig } from './sdk-integration.js';
27
27
  // Core MCP Server
28
28
  export { MCPServer, type IMCPServer } from './server.js';
29
29
 
30
+ // MCP 2025-11 Server and Components
31
+ export { MCP2025Server, type MCP2025ServerConfig } from './server-mcp-2025.js';
32
+ export {
33
+ MCPServerFactory,
34
+ createMCPServer,
35
+ isMCP2025Available,
36
+ getServerCapabilities,
37
+ type MCPFeatureFlags,
38
+ type ExtendedMCPConfig,
39
+ } from './server-factory.js';
40
+
41
+ // MCP 2025-11 Protocol Components
42
+ export {
43
+ VersionNegotiator,
44
+ BackwardCompatibilityAdapter,
45
+ type MCPHandshake,
46
+ type MCPVersion,
47
+ type MCPCapability,
48
+ type NegotiationResult as MCP2025NegotiationResult,
49
+ } from './protocol/version-negotiation.js';
50
+
51
+ // MCP 2025-11 Async Job Management
52
+ export {
53
+ MCPAsyncJobManager,
54
+ type MCPToolRequest,
55
+ type MCPJobHandle,
56
+ type MCPJobResult,
57
+ type AsyncJob,
58
+ type JobStatus,
59
+ } from './async/job-manager-mcp25.js';
60
+
61
+ // MCP 2025-11 Registry Integration
62
+ export {
63
+ MCPRegistryClient,
64
+ type RegistryConfig,
65
+ type ServerRegistryEntry,
66
+ } from './registry/mcp-registry-client-2025.js';
67
+
68
+ // MCP 2025-11 Schema Validation
69
+ export {
70
+ SchemaValidator,
71
+ upgradeToolSchema,
72
+ type ValidationResult,
73
+ } from './validation/schema-validator-2025.js';
74
+
75
+ // Progressive Tool Registry (Phase 1 & 2)
76
+ export {
77
+ ProgressiveToolRegistry,
78
+ createProgressiveToolRegistry,
79
+ createProgressiveClaudeFlowSdkServer,
80
+ type ProgressiveToolRegistryConfig,
81
+ } from './tool-registry-progressive.js';
82
+
83
+ // Dynamic Tool Loader (Phase 1)
84
+ export {
85
+ DynamicToolLoader,
86
+ type ToolMetadata,
87
+ type ToolSearchQuery,
88
+ } from './tools/loader.js';
89
+
30
90
  // Lifecycle Management
31
91
  export {
32
92
  MCPLifecycleManager,