claude-flow 2.7.33 → 2.7.34

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 (79) hide show
  1. package/.claude/settings.local.json +9 -2
  2. package/.claude/skills/agentic-jujutsu/SKILL.md +1 -1
  3. package/CHANGELOG.md +75 -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/help-formatter.js +5 -0
  8. package/dist/src/cli/simple-commands/init/agent-copier.js +9 -3
  9. package/dist/src/cli/simple-commands/init/agent-copier.js.map +1 -1
  10. package/dist/src/core/version.js +1 -1
  11. package/dist/src/mcp/async/job-manager-mcp25.js +240 -0
  12. package/dist/src/mcp/async/job-manager-mcp25.js.map +1 -0
  13. package/dist/src/mcp/index.js +8 -0
  14. package/dist/src/mcp/index.js.map +1 -1
  15. package/dist/src/mcp/protocol/version-negotiation.js +182 -0
  16. package/dist/src/mcp/protocol/version-negotiation.js.map +1 -0
  17. package/dist/src/mcp/registry/mcp-registry-client-2025.js +210 -0
  18. package/dist/src/mcp/registry/mcp-registry-client-2025.js.map +1 -0
  19. package/dist/src/mcp/server-factory.js +189 -0
  20. package/dist/src/mcp/server-factory.js.map +1 -0
  21. package/dist/src/mcp/server-mcp-2025.js +283 -0
  22. package/dist/src/mcp/server-mcp-2025.js.map +1 -0
  23. package/dist/src/mcp/tool-registry-progressive.js +319 -0
  24. package/dist/src/mcp/tool-registry-progressive.js.map +1 -0
  25. package/dist/src/mcp/tools/_template.js +62 -0
  26. package/dist/src/mcp/tools/_template.js.map +1 -0
  27. package/dist/src/mcp/tools/loader.js +228 -0
  28. package/dist/src/mcp/tools/loader.js.map +1 -0
  29. package/dist/src/mcp/tools/system/search.js +224 -0
  30. package/dist/src/mcp/tools/system/search.js.map +1 -0
  31. package/dist/src/mcp/tools/system/status.js +168 -0
  32. package/dist/src/mcp/tools/system/status.js.map +1 -0
  33. package/dist/src/mcp/validation/schema-validator-2025.js +198 -0
  34. package/dist/src/mcp/validation/schema-validator-2025.js.map +1 -0
  35. package/docs/.claude-flow/metrics/performance.json +3 -3
  36. package/docs/.claude-flow/metrics/task-metrics.json +3 -3
  37. package/docs/.github-release-issue-v2.7.33.md +488 -0
  38. package/docs/AGENTDB_BRANCH_MERGE_VERIFICATION.md +436 -0
  39. package/docs/BRANCH_REVIEW_SUMMARY.md +439 -0
  40. package/docs/DEEP_CODE_REVIEW_v2.7.33.md +1159 -0
  41. package/docs/MCP_2025_FEATURE_CONFIRMATION.md +698 -0
  42. package/docs/NPM_PUBLISH_GUIDE_v2.7.33.md +628 -0
  43. package/docs/REGRESSION_TEST_REPORT_v2.7.33.md +397 -0
  44. package/docs/RELEASE_NOTES_v2.7.33.md +618 -0
  45. package/docs/RELEASE_READINESS_SUMMARY.md +377 -0
  46. package/docs/RELEASE_SUMMARY_v2.7.33.md +456 -0
  47. package/docs/agentic-flow-agentdb-mcp-integration.md +1198 -0
  48. package/docs/mcp-2025-implementation-summary.md +459 -0
  49. package/docs/mcp-spec-2025-implementation-plan.md +1330 -0
  50. package/docs/phase-1-2-implementation-summary.md +676 -0
  51. package/docs/regression-analysis-phase-1-2.md +555 -0
  52. package/package.json +5 -2
  53. package/src/cli/commands/mcp.ts +86 -9
  54. package/src/cli/simple-commands/init/agent-copier.js +10 -5
  55. package/src/mcp/async/job-manager-mcp25.ts +456 -0
  56. package/src/mcp/index.ts +60 -0
  57. package/src/mcp/protocol/version-negotiation.ts +329 -0
  58. package/src/mcp/registry/mcp-registry-client-2025.ts +334 -0
  59. package/src/mcp/server-factory.ts +426 -0
  60. package/src/mcp/server-mcp-2025.ts +507 -0
  61. package/src/mcp/tool-registry-progressive.ts +539 -0
  62. package/src/mcp/tools/_template.ts +174 -0
  63. package/src/mcp/tools/loader.ts +362 -0
  64. package/src/mcp/tools/system/search.ts +276 -0
  65. package/src/mcp/tools/system/status.ts +206 -0
  66. package/src/mcp/validation/schema-validator-2025.ts +294 -0
  67. package/docs/AGENTDB_V1.6.1_DEEP_REVIEW.md +0 -386
  68. package/docs/AGENT_FOLDER_STRUCTURE_FIX.md +0 -192
  69. package/docs/RECENT_RELEASES_SUMMARY.md +0 -375
  70. package/docs/V2.7.31_RELEASE_NOTES.md +0 -375
  71. /package/.claude/agents/analysis/{analyze-code-quality.md → code-review/analyze-code-quality.md} +0 -0
  72. /package/.claude/agents/architecture/{arch-system-design.md → system-design/arch-system-design.md} +0 -0
  73. /package/.claude/agents/data/{data-ml-model.md → ml/data-ml-model.md} +0 -0
  74. /package/.claude/agents/development/{dev-backend-api.md → backend/dev-backend-api.md} +0 -0
  75. /package/.claude/agents/devops/{ops-cicd-github.md → ci-cd/ops-cicd-github.md} +0 -0
  76. /package/.claude/agents/documentation/{docs-api-openapi.md → api-docs/docs-api-openapi.md} +0 -0
  77. /package/.claude/agents/specialized/{spec-mobile-react-native.md → mobile/spec-mobile-react-native.md} +0 -0
  78. /package/.claude/agents/testing/{tdd-london-swarm.md → unit/tdd-london-swarm.md} +0 -0
  79. /package/.claude/agents/testing/{production-validator.md → validation/production-validator.md} +0 -0
@@ -0,0 +1,1330 @@
1
+ # MCP Spec 2025 Implementation Plan for Claude Flow
2
+
3
+ **Timeline**: RC November 14, 2025 → Final November 25, 2025
4
+ **Status**: Implementation Phase
5
+ **Priority**: CRITICAL - Spec-breaking changes require immediate action
6
+
7
+ ---
8
+
9
+ ## Executive Summary
10
+
11
+ The upcoming MCP spec introduces **3 major changes** that require updates to Claude Flow:
12
+
13
+ 1. **Async Operations** (First-class support for long-running tasks)
14
+ 2. **Registry-Backed Discovery** (Formal MCP Registry integration)
15
+ 3. **Code Execution Pattern** (98% token reduction - already planned)
16
+
17
+ Combined with Anthropic's engineering guidance, these changes will:
18
+ - Enable resumable workflows without blocking
19
+ - Provide automatic server discovery via MCP Registry
20
+ - Reduce token usage by 98% (150k → 2k tokens)
21
+ - Improve privacy with execution-environment data processing
22
+
23
+ ---
24
+
25
+ ## 🎯 Implementation Phases
26
+
27
+ ### Phase 0: Pre-RC Preparation (Before Nov 14)
28
+ **Goal**: Have infrastructure ready for RC validation
29
+
30
+ ### Phase 1: RC Validation Window (Nov 14-25)
31
+ **Goal**: Test compatibility and fix issues before final spec
32
+
33
+ ### Phase 2: Production Rollout (After Nov 25)
34
+ **Goal**: Deploy to production with full spec compliance
35
+
36
+ ---
37
+
38
+ ## 📋 Detailed Implementation Plan
39
+
40
+ ## PHASE 0A: Async Operations Architecture (PRIORITY 1)
41
+
42
+ ### Overview
43
+ MCP will support first-class async operations:
44
+ - Servers start long-running work and return job handles
45
+ - Clients poll or resume to retrieve results without blocking
46
+ - Job state persisted for resumability
47
+
48
+ ### Current State: Claude Flow
49
+ - Tools execute synchronously in `handler()` functions
50
+ - No job persistence or state management
51
+ - Long-running tasks block the MCP connection
52
+
53
+ ### Required Changes
54
+
55
+ #### 1. Job Management System
56
+
57
+ **Create**: `src/mcp/async/job-manager.ts`
58
+
59
+ ```typescript
60
+ import { EventEmitter } from 'events';
61
+ import { v4 as uuidv4 } from 'uuid';
62
+
63
+ export type JobStatus =
64
+ | 'queued' // Job submitted but not started
65
+ | 'running' // Job in progress
66
+ | 'completed' // Job finished successfully
67
+ | 'failed' // Job failed with error
68
+ | 'cancelled'; // Job cancelled by user
69
+
70
+ export interface AsyncJob<TInput = any, TResult = any> {
71
+ id: string;
72
+ toolName: string;
73
+ status: JobStatus;
74
+ progress?: number; // 0-100
75
+ input: TInput;
76
+ result?: TResult;
77
+ error?: {
78
+ code: string;
79
+ message: string;
80
+ details?: any;
81
+ };
82
+ metadata: {
83
+ createdAt: Date;
84
+ startedAt?: Date;
85
+ completedAt?: Date;
86
+ estimatedDuration?: number; // milliseconds
87
+ actualDuration?: number;
88
+ };
89
+ context?: any; // Tool context
90
+ }
91
+
92
+ export interface JobHandle {
93
+ jobId: string;
94
+ status: JobStatus;
95
+ progress?: number;
96
+ pollUrl?: string; // URL to poll for status
97
+ webhookUrl?: string; // Optional webhook for completion
98
+ }
99
+
100
+ /**
101
+ * Manages async job lifecycle for MCP tools
102
+ * Supports polling, resumption, and cancellation
103
+ */
104
+ export class JobManager extends EventEmitter {
105
+ private jobs: Map<string, AsyncJob> = new Map();
106
+ private executors: Map<string, Promise<any>> = new Map();
107
+
108
+ constructor(
109
+ private maxJobs: number = 1000,
110
+ private jobTTL: number = 86400000 // 24 hours
111
+ ) {
112
+ super();
113
+
114
+ // Cleanup expired jobs every hour
115
+ setInterval(() => this.cleanupExpiredJobs(), 3600000);
116
+ }
117
+
118
+ /**
119
+ * Submit a new async job
120
+ * Returns job handle immediately, execution happens in background
121
+ */
122
+ async submitJob<TInput, TResult>(
123
+ toolName: string,
124
+ input: TInput,
125
+ executor: (input: TInput, progress: (percent: number) => void) => Promise<TResult>,
126
+ context?: any
127
+ ): Promise<JobHandle> {
128
+ // Check capacity
129
+ if (this.jobs.size >= this.maxJobs) {
130
+ this.cleanupExpiredJobs();
131
+ if (this.jobs.size >= this.maxJobs) {
132
+ throw new Error('Job queue full. Please try again later.');
133
+ }
134
+ }
135
+
136
+ // Create job
137
+ const jobId = uuidv4();
138
+ const job: AsyncJob<TInput, TResult> = {
139
+ id: jobId,
140
+ toolName,
141
+ status: 'queued',
142
+ input,
143
+ metadata: {
144
+ createdAt: new Date(),
145
+ },
146
+ context,
147
+ };
148
+
149
+ this.jobs.set(jobId, job);
150
+
151
+ // Start execution in background
152
+ this.executeJob(job, executor);
153
+
154
+ // Return handle immediately
155
+ return {
156
+ jobId,
157
+ status: 'queued',
158
+ pollUrl: `/mcp/jobs/${jobId}`,
159
+ };
160
+ }
161
+
162
+ /**
163
+ * Execute job in background
164
+ */
165
+ private async executeJob<TInput, TResult>(
166
+ job: AsyncJob<TInput, TResult>,
167
+ executor: (input: TInput, progress: (percent: number) => void) => Promise<TResult>
168
+ ): Promise<void> {
169
+ // Update status to running
170
+ job.status = 'running';
171
+ job.metadata.startedAt = new Date();
172
+ this.emit('job:started', job.id);
173
+
174
+ try {
175
+ // Execute with progress callback
176
+ const progressCallback = (percent: number) => {
177
+ job.progress = Math.min(100, Math.max(0, percent));
178
+ this.emit('job:progress', job.id, job.progress);
179
+ };
180
+
181
+ const result = await executor(job.input, progressCallback);
182
+
183
+ // Mark completed
184
+ job.status = 'completed';
185
+ job.result = result;
186
+ job.progress = 100;
187
+ job.metadata.completedAt = new Date();
188
+ job.metadata.actualDuration =
189
+ job.metadata.completedAt.getTime() - job.metadata.startedAt!.getTime();
190
+
191
+ this.emit('job:completed', job.id, result);
192
+ } catch (error: any) {
193
+ // Mark failed
194
+ job.status = 'failed';
195
+ job.error = {
196
+ code: error.code || 'EXECUTION_ERROR',
197
+ message: error.message,
198
+ details: error.details || error.stack,
199
+ };
200
+ job.metadata.completedAt = new Date();
201
+
202
+ this.emit('job:failed', job.id, error);
203
+ }
204
+ }
205
+
206
+ /**
207
+ * Get job status (for polling)
208
+ */
209
+ getJobStatus(jobId: string): JobHandle | null {
210
+ const job = this.jobs.get(jobId);
211
+ if (!job) return null;
212
+
213
+ return {
214
+ jobId: job.id,
215
+ status: job.status,
216
+ progress: job.progress,
217
+ pollUrl: `/mcp/jobs/${jobId}`,
218
+ };
219
+ }
220
+
221
+ /**
222
+ * Get full job details
223
+ */
224
+ getJob(jobId: string): AsyncJob | null {
225
+ return this.jobs.get(jobId) || null;
226
+ }
227
+
228
+ /**
229
+ * Get job result (blocks until completed or failed)
230
+ */
231
+ async waitForJob<TResult>(
232
+ jobId: string,
233
+ timeout: number = 300000 // 5 minutes default
234
+ ): Promise<TResult> {
235
+ const job = this.jobs.get(jobId);
236
+ if (!job) {
237
+ throw new Error(`Job not found: ${jobId}`);
238
+ }
239
+
240
+ // If already completed, return immediately
241
+ if (job.status === 'completed') {
242
+ return job.result as TResult;
243
+ }
244
+
245
+ if (job.status === 'failed') {
246
+ throw new Error(job.error?.message || 'Job failed');
247
+ }
248
+
249
+ // Wait for completion
250
+ return new Promise((resolve, reject) => {
251
+ const timeoutHandle = setTimeout(() => {
252
+ this.removeListener('job:completed', completedHandler);
253
+ this.removeListener('job:failed', failedHandler);
254
+ reject(new Error('Job timeout'));
255
+ }, timeout);
256
+
257
+ const completedHandler = (completedJobId: string, result: TResult) => {
258
+ if (completedJobId === jobId) {
259
+ clearTimeout(timeoutHandle);
260
+ this.removeListener('job:failed', failedHandler);
261
+ resolve(result);
262
+ }
263
+ };
264
+
265
+ const failedHandler = (failedJobId: string, error: Error) => {
266
+ if (failedJobId === jobId) {
267
+ clearTimeout(timeoutHandle);
268
+ this.removeListener('job:completed', completedHandler);
269
+ reject(error);
270
+ }
271
+ };
272
+
273
+ this.on('job:completed', completedHandler);
274
+ this.on('job:failed', failedHandler);
275
+ });
276
+ }
277
+
278
+ /**
279
+ * Cancel a running job
280
+ */
281
+ async cancelJob(jobId: string): Promise<boolean> {
282
+ const job = this.jobs.get(jobId);
283
+ if (!job) return false;
284
+
285
+ if (job.status === 'completed' || job.status === 'failed') {
286
+ return false; // Already finished
287
+ }
288
+
289
+ job.status = 'cancelled';
290
+ job.metadata.completedAt = new Date();
291
+
292
+ this.emit('job:cancelled', jobId);
293
+ return true;
294
+ }
295
+
296
+ /**
297
+ * List jobs with filtering
298
+ */
299
+ listJobs(filter?: {
300
+ status?: JobStatus;
301
+ toolName?: string;
302
+ limit?: number;
303
+ }): AsyncJob[] {
304
+ let jobs = Array.from(this.jobs.values());
305
+
306
+ if (filter?.status) {
307
+ jobs = jobs.filter(j => j.status === filter.status);
308
+ }
309
+
310
+ if (filter?.toolName) {
311
+ jobs = jobs.filter(j => j.toolName === filter.toolName);
312
+ }
313
+
314
+ // Sort by creation time (newest first)
315
+ jobs.sort((a, b) =>
316
+ b.metadata.createdAt.getTime() - a.metadata.createdAt.getTime()
317
+ );
318
+
319
+ if (filter?.limit) {
320
+ jobs = jobs.slice(0, filter.limit);
321
+ }
322
+
323
+ return jobs;
324
+ }
325
+
326
+ /**
327
+ * Cleanup expired jobs
328
+ */
329
+ private cleanupExpiredJobs(): number {
330
+ const now = Date.now();
331
+ let cleaned = 0;
332
+
333
+ for (const [jobId, job] of this.jobs.entries()) {
334
+ const age = now - job.metadata.createdAt.getTime();
335
+
336
+ // Remove if expired and not running
337
+ if (age > this.jobTTL && job.status !== 'running') {
338
+ this.jobs.delete(jobId);
339
+ cleaned++;
340
+ }
341
+ }
342
+
343
+ return cleaned;
344
+ }
345
+
346
+ /**
347
+ * Get metrics
348
+ */
349
+ getMetrics() {
350
+ const jobs = Array.from(this.jobs.values());
351
+
352
+ return {
353
+ total: jobs.length,
354
+ byStatus: {
355
+ queued: jobs.filter(j => j.status === 'queued').length,
356
+ running: jobs.filter(j => j.status === 'running').length,
357
+ completed: jobs.filter(j => j.status === 'completed').length,
358
+ failed: jobs.filter(j => j.status === 'failed').length,
359
+ cancelled: jobs.filter(j => j.status === 'cancelled').length,
360
+ },
361
+ averageDuration: this.calculateAverageDuration(jobs),
362
+ };
363
+ }
364
+
365
+ private calculateAverageDuration(jobs: AsyncJob[]): number {
366
+ const completed = jobs.filter(j =>
367
+ j.status === 'completed' && j.metadata.actualDuration
368
+ );
369
+
370
+ if (completed.length === 0) return 0;
371
+
372
+ const total = completed.reduce((sum, j) =>
373
+ sum + (j.metadata.actualDuration || 0), 0
374
+ );
375
+
376
+ return total / completed.length;
377
+ }
378
+ }
379
+ ```
380
+
381
+ #### 2. Async Tool Wrapper
382
+
383
+ **Create**: `src/mcp/async/async-tool.ts`
384
+
385
+ ```typescript
386
+ import type { MCPTool } from '../types.js';
387
+ import type { ILogger } from '../../interfaces/logger.js';
388
+ import { JobManager, JobHandle } from './job-manager.js';
389
+
390
+ /**
391
+ * Wraps synchronous tools to support async execution
392
+ */
393
+ export function makeToolAsync(
394
+ tool: MCPTool,
395
+ jobManager: JobManager,
396
+ logger: ILogger
397
+ ): MCPTool {
398
+ return {
399
+ ...tool,
400
+ name: `${tool.name}:async`,
401
+ description: `${tool.description} (Async version - returns job handle immediately)`,
402
+
403
+ // Add async-specific parameters
404
+ inputSchema: {
405
+ type: 'object',
406
+ properties: {
407
+ ...((tool.inputSchema as any).properties || {}),
408
+ _async: {
409
+ type: 'object',
410
+ properties: {
411
+ mode: {
412
+ type: 'string',
413
+ enum: ['fire-and-forget', 'wait', 'poll'],
414
+ description: 'Execution mode',
415
+ default: 'poll',
416
+ },
417
+ timeout: {
418
+ type: 'number',
419
+ description: 'Timeout in ms (for wait mode)',
420
+ default: 300000,
421
+ },
422
+ webhook: {
423
+ type: 'string',
424
+ description: 'Webhook URL for completion notification',
425
+ },
426
+ },
427
+ },
428
+ },
429
+ required: (tool.inputSchema as any).required || [],
430
+ },
431
+
432
+ handler: async (input: any, context?: any) => {
433
+ const { _async, ...toolInput } = input;
434
+ const mode = _async?.mode || 'poll';
435
+
436
+ // Submit job
437
+ const jobHandle = await jobManager.submitJob(
438
+ tool.name,
439
+ toolInput,
440
+ async (input, onProgress) => {
441
+ // Execute original tool
442
+ return await tool.handler(input, context);
443
+ },
444
+ context
445
+ );
446
+
447
+ logger.info('Async job submitted', {
448
+ jobId: jobHandle.jobId,
449
+ tool: tool.name,
450
+ mode
451
+ });
452
+
453
+ // Handle different modes
454
+ if (mode === 'fire-and-forget') {
455
+ // Return job handle immediately
456
+ return {
457
+ async: true,
458
+ jobHandle,
459
+ message: 'Job submitted. Use jobs/status to check progress.',
460
+ };
461
+ } else if (mode === 'wait') {
462
+ // Wait for completion
463
+ try {
464
+ const result = await jobManager.waitForJob(
465
+ jobHandle.jobId,
466
+ _async?.timeout || 300000
467
+ );
468
+
469
+ return {
470
+ async: true,
471
+ jobHandle,
472
+ completed: true,
473
+ result,
474
+ };
475
+ } catch (error: any) {
476
+ return {
477
+ async: true,
478
+ jobHandle,
479
+ completed: false,
480
+ error: error.message,
481
+ message: 'Use jobs/status to check current state.',
482
+ };
483
+ }
484
+ } else {
485
+ // Poll mode (default)
486
+ return {
487
+ async: true,
488
+ jobHandle,
489
+ message: 'Job submitted. Poll the jobHandle.pollUrl to check status.',
490
+ };
491
+ }
492
+ },
493
+ };
494
+ }
495
+ ```
496
+
497
+ #### 3. Job Management Tools
498
+
499
+ **Create**: `src/mcp/tools/jobs/status.ts`
500
+
501
+ ```typescript
502
+ import type { MCPTool, ClaudeFlowToolContext } from '../../types.js';
503
+ import type { ILogger } from '../../../interfaces/logger.js';
504
+
505
+ export function createJobStatusTool(logger: ILogger): MCPTool {
506
+ return {
507
+ name: 'jobs/status',
508
+ description: 'Get status of an async job. Use for polling long-running operations.',
509
+
510
+ inputSchema: {
511
+ type: 'object',
512
+ properties: {
513
+ jobId: {
514
+ type: 'string',
515
+ description: 'Job ID returned from async tool call',
516
+ },
517
+ },
518
+ required: ['jobId'],
519
+ },
520
+
521
+ metadata: {
522
+ category: 'jobs',
523
+ tags: ['async', 'status', 'polling'],
524
+ detailLevel: 'standard',
525
+ },
526
+
527
+ handler: async (input: any, context?: ClaudeFlowToolContext) => {
528
+ if (!context?.jobManager) {
529
+ throw new Error('Job manager not available');
530
+ }
531
+
532
+ const { jobId } = input;
533
+ const job = context.jobManager.getJob(jobId);
534
+
535
+ if (!job) {
536
+ return {
537
+ success: false,
538
+ error: 'Job not found',
539
+ jobId,
540
+ };
541
+ }
542
+
543
+ return {
544
+ success: true,
545
+ job: {
546
+ id: job.id,
547
+ toolName: job.toolName,
548
+ status: job.status,
549
+ progress: job.progress,
550
+ result: job.status === 'completed' ? job.result : undefined,
551
+ error: job.status === 'failed' ? job.error : undefined,
552
+ metadata: job.metadata,
553
+ },
554
+ };
555
+ },
556
+ };
557
+ }
558
+
559
+ export const toolMetadata = {
560
+ name: 'jobs/status',
561
+ description: 'Get async job status',
562
+ category: 'jobs',
563
+ detailLevel: 'standard',
564
+ };
565
+ ```
566
+
567
+ **Create**: `src/mcp/tools/jobs/list.ts`
568
+
569
+ ```typescript
570
+ import type { MCPTool, ClaudeFlowToolContext } from '../../types.js';
571
+ import type { ILogger } from '../../../interfaces/logger.js';
572
+
573
+ export function createJobListTool(logger: ILogger): MCPTool {
574
+ return {
575
+ name: 'jobs/list',
576
+ description: 'List async jobs with optional filtering',
577
+
578
+ inputSchema: {
579
+ type: 'object',
580
+ properties: {
581
+ status: {
582
+ type: 'string',
583
+ enum: ['queued', 'running', 'completed', 'failed', 'cancelled'],
584
+ description: 'Filter by status',
585
+ },
586
+ toolName: {
587
+ type: 'string',
588
+ description: 'Filter by tool name',
589
+ },
590
+ limit: {
591
+ type: 'number',
592
+ description: 'Maximum number of jobs to return',
593
+ default: 20,
594
+ },
595
+ },
596
+ },
597
+
598
+ handler: async (input: any, context?: ClaudeFlowToolContext) => {
599
+ if (!context?.jobManager) {
600
+ throw new Error('Job manager not available');
601
+ }
602
+
603
+ const jobs = context.jobManager.listJobs(input);
604
+
605
+ return {
606
+ success: true,
607
+ jobs: jobs.map(j => ({
608
+ id: j.id,
609
+ toolName: j.toolName,
610
+ status: j.status,
611
+ progress: j.progress,
612
+ createdAt: j.metadata.createdAt,
613
+ duration: j.metadata.actualDuration,
614
+ })),
615
+ total: jobs.length,
616
+ };
617
+ },
618
+ };
619
+ }
620
+
621
+ export const toolMetadata = {
622
+ name: 'jobs/list',
623
+ description: 'List async jobs',
624
+ category: 'jobs',
625
+ detailLevel: 'standard',
626
+ };
627
+ ```
628
+
629
+ **Create**: `src/mcp/tools/jobs/cancel.ts`
630
+
631
+ ```typescript
632
+ import type { MCPTool, ClaudeFlowToolContext } from '../../types.js';
633
+ import type { ILogger } from '../../../interfaces/logger.js';
634
+
635
+ export function createJobCancelTool(logger: ILogger): MCPTool {
636
+ return {
637
+ name: 'jobs/cancel',
638
+ description: 'Cancel a running async job',
639
+
640
+ inputSchema: {
641
+ type: 'object',
642
+ properties: {
643
+ jobId: {
644
+ type: 'string',
645
+ description: 'Job ID to cancel',
646
+ },
647
+ },
648
+ required: ['jobId'],
649
+ },
650
+
651
+ handler: async (input: any, context?: ClaudeFlowToolContext) => {
652
+ if (!context?.jobManager) {
653
+ throw new Error('Job manager not available');
654
+ }
655
+
656
+ const { jobId } = input;
657
+ const cancelled = await context.jobManager.cancelJob(jobId);
658
+
659
+ return {
660
+ success: cancelled,
661
+ jobId,
662
+ message: cancelled
663
+ ? 'Job cancelled successfully'
664
+ : 'Job not found or already completed',
665
+ };
666
+ },
667
+ };
668
+ }
669
+
670
+ export const toolMetadata = {
671
+ name: 'jobs/cancel',
672
+ description: 'Cancel async job',
673
+ category: 'jobs',
674
+ detailLevel: 'standard',
675
+ };
676
+ ```
677
+
678
+ #### 4. Integration with MCP Server
679
+
680
+ **Update**: `src/mcp/server.ts`
681
+
682
+ ```typescript
683
+ import { JobManager } from './async/job-manager.js';
684
+ import { makeToolAsync } from './async/async-tool.js';
685
+
686
+ export class MCPServer {
687
+ private jobManager: JobManager;
688
+
689
+ constructor(config: MCPConfig, eventBus: IEventBus, logger: ILogger) {
690
+ // ... existing code ...
691
+
692
+ // Initialize job manager
693
+ this.jobManager = new JobManager(
694
+ config.async?.maxJobs || 1000,
695
+ config.async?.jobTTL || 86400000
696
+ );
697
+
698
+ logger.info('Job manager initialized', {
699
+ maxJobs: config.async?.maxJobs || 1000,
700
+ });
701
+ }
702
+
703
+ /**
704
+ * Register tool with optional async support
705
+ */
706
+ async registerTool(tool: MCPTool, enableAsync: boolean = true): Promise<void> {
707
+ // Register synchronous version
708
+ await this.toolRegistry.registerTool(tool);
709
+
710
+ // Also register async version if enabled
711
+ if (enableAsync && this.isLongRunningTool(tool)) {
712
+ const asyncTool = makeToolAsync(tool, this.jobManager, this.logger);
713
+ await this.toolRegistry.registerTool(asyncTool);
714
+
715
+ this.logger.info('Registered async version of tool', {
716
+ tool: tool.name,
717
+ asyncName: asyncTool.name
718
+ });
719
+ }
720
+ }
721
+
722
+ /**
723
+ * Determine if tool should have async version
724
+ */
725
+ private isLongRunningTool(tool: MCPTool): boolean {
726
+ // Tools that typically take > 5 seconds should be async
727
+ const longRunningCategories = [
728
+ 'agents/spawn',
729
+ 'agents/spawn-parallel',
730
+ 'tasks/create',
731
+ 'workflow/execute',
732
+ 'data/filter',
733
+ 'swarm/',
734
+ ];
735
+
736
+ return longRunningCategories.some(prefix => tool.name.startsWith(prefix));
737
+ }
738
+
739
+ /**
740
+ * Add job manager to tool context
741
+ */
742
+ private get toolContext(): ClaudeFlowToolContext {
743
+ return {
744
+ orchestrator: this.orchestrator,
745
+ swarmCoordinator: this.swarmCoordinator,
746
+ jobManager: this.jobManager, // NEW
747
+ sessionId: this.currentSessionId,
748
+ };
749
+ }
750
+ }
751
+ ```
752
+
753
+ #### 5. Configuration Updates
754
+
755
+ **Update**: `src/config/default-config.ts`
756
+
757
+ ```typescript
758
+ export interface MCPConfig {
759
+ // ... existing config ...
760
+
761
+ async: {
762
+ enabled: boolean;
763
+ maxJobs: number;
764
+ jobTTL: number; // milliseconds
765
+ defaultTimeout: number; // milliseconds
766
+ enableWebhooks: boolean;
767
+ };
768
+ }
769
+
770
+ export const defaultConfig: MCPConfig = {
771
+ // ... existing config ...
772
+
773
+ async: {
774
+ enabled: true,
775
+ maxJobs: 1000,
776
+ jobTTL: 86400000, // 24 hours
777
+ defaultTimeout: 300000, // 5 minutes
778
+ enableWebhooks: false,
779
+ },
780
+ };
781
+ ```
782
+
783
+ ---
784
+
785
+ ## PHASE 0B: MCP Registry Integration (PRIORITY 2)
786
+
787
+ ### Overview
788
+ The MCP Registry provides:
789
+ - Centralized server catalog with metadata
790
+ - API for server discovery
791
+ - Capability negotiation
792
+ - Health checks and monitoring
793
+
794
+ ### Required Changes
795
+
796
+ #### 1. Registry Client
797
+
798
+ **Create**: `src/mcp/registry/client.ts`
799
+
800
+ ```typescript
801
+ /**
802
+ * MCP Registry Client
803
+ * Integrates with official MCP Registry for server discovery
804
+ */
805
+
806
+ export interface ServerMetadata {
807
+ name: string;
808
+ version: string;
809
+ description: string;
810
+ author: string;
811
+ homepage?: string;
812
+ repository?: string;
813
+ capabilities: {
814
+ tools: boolean;
815
+ resources: boolean;
816
+ prompts: boolean;
817
+ async: boolean;
818
+ streaming: boolean;
819
+ };
820
+ categories: string[];
821
+ tags: string[];
822
+ transport: Array<'stdio' | 'http' | 'websocket'>;
823
+ healthCheck?: {
824
+ endpoint: string;
825
+ interval: number; // seconds
826
+ };
827
+ security: {
828
+ authRequired: boolean;
829
+ authMethods: Array<'token' | 'basic' | 'oauth'>;
830
+ piiHandling: 'none' | 'tokenized' | 'encrypted';
831
+ };
832
+ }
833
+
834
+ export class RegistryClient {
835
+ private baseUrl: string = 'https://registry.mcp.anthropic.com/api/v1';
836
+
837
+ constructor(private apiKey?: string) {}
838
+
839
+ /**
840
+ * Publish server to registry
841
+ */
842
+ async publishServer(metadata: ServerMetadata): Promise<{
843
+ success: boolean;
844
+ serverId: string;
845
+ url: string;
846
+ }> {
847
+ const response = await fetch(`${this.baseUrl}/servers`, {
848
+ method: 'POST',
849
+ headers: {
850
+ 'Content-Type': 'application/json',
851
+ 'Authorization': `Bearer ${this.apiKey}`,
852
+ },
853
+ body: JSON.stringify(metadata),
854
+ });
855
+
856
+ if (!response.ok) {
857
+ throw new Error(`Failed to publish server: ${response.statusText}`);
858
+ }
859
+
860
+ return await response.json();
861
+ }
862
+
863
+ /**
864
+ * Update server metadata
865
+ */
866
+ async updateServer(
867
+ serverId: string,
868
+ metadata: Partial<ServerMetadata>
869
+ ): Promise<void> {
870
+ const response = await fetch(`${this.baseUrl}/servers/${serverId}`, {
871
+ method: 'PATCH',
872
+ headers: {
873
+ 'Content-Type': 'application/json',
874
+ 'Authorization': `Bearer ${this.apiKey}`,
875
+ },
876
+ body: JSON.stringify(metadata),
877
+ });
878
+
879
+ if (!response.ok) {
880
+ throw new Error(`Failed to update server: ${response.statusText}`);
881
+ }
882
+ }
883
+
884
+ /**
885
+ * Report health status
886
+ */
887
+ async reportHealth(
888
+ serverId: string,
889
+ health: {
890
+ status: 'healthy' | 'degraded' | 'unhealthy';
891
+ latency?: number;
892
+ metrics?: Record<string, number>;
893
+ }
894
+ ): Promise<void> {
895
+ await fetch(`${this.baseUrl}/servers/${serverId}/health`, {
896
+ method: 'POST',
897
+ headers: {
898
+ 'Content-Type': 'application/json',
899
+ 'Authorization': `Bearer ${this.apiKey}`,
900
+ },
901
+ body: JSON.stringify(health),
902
+ });
903
+ }
904
+
905
+ /**
906
+ * Search registry for servers
907
+ */
908
+ async searchServers(query: {
909
+ category?: string;
910
+ tags?: string[];
911
+ capabilities?: string[];
912
+ limit?: number;
913
+ }): Promise<ServerMetadata[]> {
914
+ const params = new URLSearchParams();
915
+ if (query.category) params.set('category', query.category);
916
+ if (query.tags) params.set('tags', query.tags.join(','));
917
+ if (query.capabilities) params.set('capabilities', query.capabilities.join(','));
918
+ if (query.limit) params.set('limit', query.limit.toString());
919
+
920
+ const response = await fetch(`${this.baseUrl}/servers?${params}`);
921
+
922
+ if (!response.ok) {
923
+ throw new Error(`Failed to search servers: ${response.statusText}`);
924
+ }
925
+
926
+ return await response.json();
927
+ }
928
+ }
929
+ ```
930
+
931
+ #### 2. Auto-Publish Script
932
+
933
+ **Create**: `scripts/publish-to-registry.ts`
934
+
935
+ ```typescript
936
+ #!/usr/bin/env node
937
+
938
+ import { RegistryClient, ServerMetadata } from '../src/mcp/registry/client.js';
939
+ import { version } from '../package.json';
940
+
941
+ async function main() {
942
+ const apiKey = process.env.MCP_REGISTRY_API_KEY;
943
+ if (!apiKey) {
944
+ console.error('❌ MCP_REGISTRY_API_KEY not set');
945
+ process.exit(1);
946
+ }
947
+
948
+ const client = new RegistryClient(apiKey);
949
+
950
+ const metadata: ServerMetadata = {
951
+ name: 'claude-flow',
952
+ version,
953
+ description: 'Advanced MCP server with swarm coordination, async operations, and neural capabilities',
954
+ author: 'ruvnet',
955
+ homepage: 'https://github.com/ruvnet/claude-flow',
956
+ repository: 'https://github.com/ruvnet/claude-flow',
957
+ capabilities: {
958
+ tools: true,
959
+ resources: true,
960
+ prompts: true,
961
+ async: true,
962
+ streaming: true,
963
+ },
964
+ categories: [
965
+ 'orchestration',
966
+ 'swarm-coordination',
967
+ 'task-management',
968
+ 'memory-management',
969
+ ],
970
+ tags: [
971
+ 'async',
972
+ 'swarm',
973
+ 'neural',
974
+ 'coordination',
975
+ 'agentdb',
976
+ 'reasoningbank',
977
+ ],
978
+ transport: ['stdio', 'http'],
979
+ healthCheck: {
980
+ endpoint: '/health',
981
+ interval: 60,
982
+ },
983
+ security: {
984
+ authRequired: true,
985
+ authMethods: ['token', 'oauth'],
986
+ piiHandling: 'tokenized',
987
+ },
988
+ };
989
+
990
+ console.log('📤 Publishing to MCP Registry...');
991
+
992
+ const result = await client.publishServer(metadata);
993
+
994
+ console.log('✅ Published successfully!');
995
+ console.log(` Server ID: ${result.serverId}`);
996
+ console.log(` URL: ${result.url}`);
997
+ }
998
+
999
+ main().catch(console.error);
1000
+ ```
1001
+
1002
+ #### 3. Health Check Endpoint
1003
+
1004
+ **Create**: `src/mcp/endpoints/health.ts`
1005
+
1006
+ ```typescript
1007
+ export class HealthCheckHandler {
1008
+ constructor(
1009
+ private server: MCPServer,
1010
+ private jobManager: JobManager,
1011
+ private toolRegistry: ToolRegistry
1012
+ ) {}
1013
+
1014
+ async getHealth(): Promise<{
1015
+ status: 'healthy' | 'degraded' | 'unhealthy';
1016
+ uptime: number;
1017
+ metrics: {
1018
+ activeJobs: number;
1019
+ totalTools: number;
1020
+ avgResponseTime: number;
1021
+ errorRate: number;
1022
+ };
1023
+ }> {
1024
+ const jobMetrics = this.jobManager.getMetrics();
1025
+ const toolMetrics = await this.toolRegistry.getMetrics();
1026
+
1027
+ // Calculate health status
1028
+ const errorRate = toolMetrics.failedInvocations / toolMetrics.totalInvocations;
1029
+ const status = errorRate > 0.1 ? 'unhealthy' : errorRate > 0.05 ? 'degraded' : 'healthy';
1030
+
1031
+ return {
1032
+ status,
1033
+ uptime: process.uptime(),
1034
+ metrics: {
1035
+ activeJobs: jobMetrics.byStatus.running,
1036
+ totalTools: toolMetrics.totalTools,
1037
+ avgResponseTime: toolMetrics.averageExecutionTime,
1038
+ errorRate,
1039
+ },
1040
+ };
1041
+ }
1042
+ }
1043
+ ```
1044
+
1045
+ #### 4. CI Integration
1046
+
1047
+ **Update**: `.github/workflows/publish.yml`
1048
+
1049
+ ```yaml
1050
+ name: Publish to MCP Registry
1051
+
1052
+ on:
1053
+ release:
1054
+ types: [published]
1055
+ push:
1056
+ branches: [main]
1057
+
1058
+ jobs:
1059
+ publish-registry:
1060
+ runs-on: ubuntu-latest
1061
+ steps:
1062
+ - uses: actions/checkout@v3
1063
+
1064
+ - name: Setup Node.js
1065
+ uses: actions/setup-node@v3
1066
+ with:
1067
+ node-version: '20'
1068
+
1069
+ - name: Install dependencies
1070
+ run: npm ci
1071
+
1072
+ - name: Build
1073
+ run: npm run build
1074
+
1075
+ - name: Run tests
1076
+ run: npm test
1077
+
1078
+ - name: Publish to MCP Registry
1079
+ env:
1080
+ MCP_REGISTRY_API_KEY: ${{ secrets.MCP_REGISTRY_API_KEY }}
1081
+ run: npm run registry:publish
1082
+
1083
+ - name: Update health check
1084
+ env:
1085
+ MCP_REGISTRY_API_KEY: ${{ secrets.MCP_REGISTRY_API_KEY }}
1086
+ run: npm run registry:health
1087
+ ```
1088
+
1089
+ ---
1090
+
1091
+ ## PHASE 0C: Code Execution Pattern (Already Planned)
1092
+
1093
+ This is covered in the original plan (Phase 1: Progressive Disclosure, Phase 4: Data Processing).
1094
+
1095
+ **Status**: Implementation details provided in main plan
1096
+
1097
+ ---
1098
+
1099
+ ## PHASE 1: RC Validation (November 14-25)
1100
+
1101
+ ### Test Suite for Spec Compliance
1102
+
1103
+ **Create**: `tests/mcp-spec-2025-compliance.test.ts`
1104
+
1105
+ ```typescript
1106
+ import { describe, it, expect, beforeAll } from '@jest/globals';
1107
+
1108
+ describe('MCP Spec 2025 Compliance', () => {
1109
+ describe('Async Operations', () => {
1110
+ it('should return job handle immediately for long-running tasks', async () => {
1111
+ const result = await mcpClient.callTool('agents/spawn:async', {
1112
+ type: 'researcher',
1113
+ name: 'Test Agent',
1114
+ _async: { mode: 'poll' },
1115
+ });
1116
+
1117
+ expect(result).toHaveProperty('jobHandle');
1118
+ expect(result.jobHandle).toHaveProperty('jobId');
1119
+ expect(result.jobHandle).toHaveProperty('pollUrl');
1120
+ });
1121
+
1122
+ it('should allow polling for job status', async () => {
1123
+ const { jobHandle } = await mcpClient.callTool('agents/spawn:async', {
1124
+ type: 'researcher',
1125
+ name: 'Test Agent',
1126
+ _async: { mode: 'poll' },
1127
+ });
1128
+
1129
+ const status = await mcpClient.callTool('jobs/status', {
1130
+ jobId: jobHandle.jobId,
1131
+ });
1132
+
1133
+ expect(status.job.status).toMatch(/queued|running|completed/);
1134
+ });
1135
+
1136
+ it('should support wait mode with timeout', async () => {
1137
+ const result = await mcpClient.callTool('agents/spawn:async', {
1138
+ type: 'researcher',
1139
+ name: 'Test Agent',
1140
+ _async: { mode: 'wait', timeout: 10000 },
1141
+ });
1142
+
1143
+ expect(result).toHaveProperty('completed');
1144
+ if (result.completed) {
1145
+ expect(result).toHaveProperty('result');
1146
+ }
1147
+ });
1148
+
1149
+ it('should support job cancellation', async () => {
1150
+ const { jobHandle } = await mcpClient.callTool('workflow/execute:async', {
1151
+ workflowId: 'long-running-workflow',
1152
+ _async: { mode: 'poll' },
1153
+ });
1154
+
1155
+ const cancelled = await mcpClient.callTool('jobs/cancel', {
1156
+ jobId: jobHandle.jobId,
1157
+ });
1158
+
1159
+ expect(cancelled.success).toBe(true);
1160
+
1161
+ const status = await mcpClient.callTool('jobs/status', {
1162
+ jobId: jobHandle.jobId,
1163
+ });
1164
+
1165
+ expect(status.job.status).toBe('cancelled');
1166
+ });
1167
+ });
1168
+
1169
+ describe('Registry Integration', () => {
1170
+ it('should be discoverable in MCP Registry', async () => {
1171
+ const servers = await registryClient.searchServers({
1172
+ tags: ['claude-flow'],
1173
+ });
1174
+
1175
+ expect(servers).toContainEqual(
1176
+ expect.objectContaining({
1177
+ name: 'claude-flow',
1178
+ capabilities: expect.objectContaining({
1179
+ async: true,
1180
+ }),
1181
+ })
1182
+ );
1183
+ });
1184
+
1185
+ it('should report health status', async () => {
1186
+ const health = await fetch('http://localhost:3000/health');
1187
+ const data = await health.json();
1188
+
1189
+ expect(data.status).toMatch(/healthy|degraded|unhealthy/);
1190
+ expect(data.metrics).toHaveProperty('activeJobs');
1191
+ });
1192
+ });
1193
+
1194
+ describe('Code Execution Pattern', () => {
1195
+ it('should process data in execution environment', async () => {
1196
+ // Create large dataset (10,000 rows)
1197
+ const largeDataset = Array.from({ length: 10000 }, (_, i) => ({
1198
+ id: i,
1199
+ value: Math.random() * 1000,
1200
+ category: ['A', 'B', 'C'][i % 3],
1201
+ }));
1202
+
1203
+ // Store in memory
1204
+ await memoryStore.store('test-dataset', JSON.stringify(largeDataset));
1205
+
1206
+ // Filter in execution environment
1207
+ const result = await mcpClient.callTool('data/filter', {
1208
+ dataSource: 'memory',
1209
+ source: 'test-dataset',
1210
+ filters: [
1211
+ { field: 'value', operator: 'gt', value: 500 },
1212
+ { field: 'category', operator: 'eq', value: 'A' },
1213
+ ],
1214
+ returnFormat: 'summary',
1215
+ });
1216
+
1217
+ // Result should be small (summary only)
1218
+ const resultSize = JSON.stringify(result).length;
1219
+ expect(resultSize).toBeLessThan(1000); // < 1KB
1220
+
1221
+ // Original dataset was ~500KB
1222
+ const originalSize = JSON.stringify(largeDataset).length;
1223
+ expect(originalSize).toBeGreaterThan(500000);
1224
+
1225
+ // Verify token savings
1226
+ const tokenReduction = ((originalSize - resultSize) / originalSize) * 100;
1227
+ expect(tokenReduction).toBeGreaterThan(98);
1228
+ });
1229
+ });
1230
+ });
1231
+ ```
1232
+
1233
+ ---
1234
+
1235
+ ## PHASE 2: Production Rollout Checklist
1236
+
1237
+ ### Pre-Rollout (Before Nov 25)
1238
+ - [ ] All async operation tests passing
1239
+ - [ ] Registry integration tested
1240
+ - [ ] Code execution pattern validated
1241
+ - [ ] Performance benchmarks meet targets
1242
+ - [ ] Security audit completed
1243
+ - [ ] Documentation updated
1244
+
1245
+ ### Rollout (Nov 25)
1246
+ - [ ] Deploy to staging
1247
+ - [ ] Smoke tests in staging
1248
+ - [ ] Monitor metrics for 24 hours
1249
+ - [ ] Deploy to production
1250
+ - [ ] Monitor production metrics
1251
+ - [ ] Update registry with production endpoint
1252
+
1253
+ ### Post-Rollout (After Nov 25)
1254
+ - [ ] Performance monitoring active
1255
+ - [ ] Token usage tracked
1256
+ - [ ] User feedback collected
1257
+ - [ ] Optimization iterations
1258
+
1259
+ ---
1260
+
1261
+ ## 📊 Success Metrics
1262
+
1263
+ ### Token Reduction
1264
+ - **Target**: 98% reduction (150k → 2k tokens)
1265
+ - **Measure**: Average tokens per workflow
1266
+ - **Baseline**: Measure before implementation
1267
+ - **Validation**: A/B test with old vs new pattern
1268
+
1269
+ ### Async Performance
1270
+ - **Target**: 95% of long-running tasks complete within timeout
1271
+ - **Measure**: Job completion rate, average duration
1272
+ - **Alert**: >5% failure rate
1273
+
1274
+ ### Registry Health
1275
+ - **Target**: 99% uptime reported to registry
1276
+ - **Measure**: Health check success rate
1277
+ - **Alert**: Status degraded for >5 minutes
1278
+
1279
+ ### User Adoption
1280
+ - **Target**: 80% of users switch to async pattern
1281
+ - **Measure**: Async tool usage vs sync tool usage
1282
+ - **Goal**: Deprecate sync versions of long-running tools
1283
+
1284
+ ---
1285
+
1286
+ ## 🚀 Quick Start Commands
1287
+
1288
+ ```bash
1289
+ # Install dependencies
1290
+ npm install
1291
+
1292
+ # Run async operation tests
1293
+ npm run test:async
1294
+
1295
+ # Run registry integration tests
1296
+ npm run test:registry
1297
+
1298
+ # Run full compliance suite
1299
+ npm run test:compliance
1300
+
1301
+ # Publish to registry
1302
+ npm run registry:publish
1303
+
1304
+ # Start server with async support
1305
+ npm run start:async
1306
+
1307
+ # Monitor job queue
1308
+ npm run jobs:monitor
1309
+ ```
1310
+
1311
+ ---
1312
+
1313
+ ## 📞 Escalation Path
1314
+
1315
+ - **Spec Questions**: mcp-spec@anthropic.com
1316
+ - **Registry Issues**: registry-support@anthropic.com
1317
+ - **Claude Flow Issues**: GitHub Issues
1318
+ - **Urgent**: Create issue with `[MCP-2025-URGENT]` prefix
1319
+
1320
+ ---
1321
+
1322
+ ## Next Steps
1323
+
1324
+ 1. **Immediate**: Review this plan with team
1325
+ 2. **This Week**: Implement Phase 0A (Async Operations)
1326
+ 3. **Next Week**: Implement Phase 0B (Registry Integration)
1327
+ 4. **Nov 14**: Begin RC validation
1328
+ 5. **Nov 25**: Production rollout
1329
+
1330
+ Would you like me to start implementing any specific phase?