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,228 @@
1
+ import { promises as fs } from 'fs';
2
+ import { join, dirname, extname, resolve } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ const __filename = fileURLToPath(import.meta.url);
5
+ const __dirname = dirname(__filename);
6
+ export class DynamicToolLoader {
7
+ toolsDir;
8
+ logger;
9
+ metadataCache = new Map();
10
+ toolCache = new Map();
11
+ scanComplete = false;
12
+ constructor(toolsDir = join(__dirname, '.'), logger){
13
+ this.toolsDir = toolsDir;
14
+ this.logger = logger;
15
+ }
16
+ async scanTools() {
17
+ if (this.scanComplete) {
18
+ return this.metadataCache;
19
+ }
20
+ this.logger.info('Scanning tools directory for metadata', {
21
+ toolsDir: this.toolsDir
22
+ });
23
+ const startTime = Date.now();
24
+ let scannedFiles = 0;
25
+ let loadedMetadata = 0;
26
+ try {
27
+ const resolvedToolsDir = resolve(this.toolsDir);
28
+ const entries = await fs.readdir(resolvedToolsDir, {
29
+ withFileTypes: true
30
+ });
31
+ const categories = entries.filter((e)=>e.isDirectory() && !e.name.startsWith('_'));
32
+ for (const categoryEntry of categories){
33
+ const category = categoryEntry.name;
34
+ const categoryPath = resolve(resolvedToolsDir, category);
35
+ if (!categoryPath.startsWith(resolvedToolsDir)) {
36
+ this.logger.warn('Skipping category outside tools directory', {
37
+ category,
38
+ categoryPath,
39
+ toolsDir: resolvedToolsDir
40
+ });
41
+ continue;
42
+ }
43
+ try {
44
+ const toolFiles = await fs.readdir(categoryPath);
45
+ const validToolFiles = toolFiles.filter((f)=>{
46
+ const ext = extname(f);
47
+ return (ext === '.ts' || ext === '.js') && !f.startsWith('_');
48
+ });
49
+ for (const toolFile of validToolFiles){
50
+ scannedFiles++;
51
+ const toolPath = resolve(categoryPath, toolFile);
52
+ if (!toolPath.startsWith(categoryPath)) {
53
+ this.logger.warn('Skipping tool file outside category directory', {
54
+ toolFile,
55
+ toolPath,
56
+ categoryPath
57
+ });
58
+ continue;
59
+ }
60
+ try {
61
+ const module = await import(toolPath);
62
+ if (module.toolMetadata) {
63
+ const metadata = {
64
+ ...module.toolMetadata,
65
+ category,
66
+ filePath: toolPath
67
+ };
68
+ this.metadataCache.set(metadata.name, metadata);
69
+ loadedMetadata++;
70
+ this.logger.debug('Loaded tool metadata', {
71
+ name: metadata.name,
72
+ category: metadata.category,
73
+ filePath: toolPath
74
+ });
75
+ } else {
76
+ this.logger.warn('Tool file missing toolMetadata export', {
77
+ filePath: toolPath
78
+ });
79
+ }
80
+ } catch (error) {
81
+ this.logger.error('Failed to load tool metadata', {
82
+ filePath: toolPath,
83
+ error: error instanceof Error ? error.message : String(error)
84
+ });
85
+ }
86
+ }
87
+ } catch (error) {
88
+ this.logger.error('Failed to scan category directory', {
89
+ category,
90
+ error: error instanceof Error ? error.message : String(error)
91
+ });
92
+ }
93
+ }
94
+ const scanTime = Date.now() - startTime;
95
+ this.scanComplete = true;
96
+ this.logger.info('Tool scan complete', {
97
+ scannedFiles,
98
+ loadedMetadata,
99
+ totalTools: this.metadataCache.size,
100
+ scanTimeMs: scanTime
101
+ });
102
+ return this.metadataCache;
103
+ } catch (error) {
104
+ this.logger.error('Failed to scan tools directory', {
105
+ error: error instanceof Error ? error.message : String(error)
106
+ });
107
+ throw error;
108
+ }
109
+ }
110
+ async loadTool(toolName, logger) {
111
+ if (this.toolCache.has(toolName)) {
112
+ this.logger.debug('Tool loaded from cache', {
113
+ toolName
114
+ });
115
+ return this.toolCache.get(toolName);
116
+ }
117
+ const metadata = this.metadataCache.get(toolName);
118
+ if (!metadata) {
119
+ this.logger.warn('Tool not found in metadata cache', {
120
+ toolName
121
+ });
122
+ return null;
123
+ }
124
+ try {
125
+ this.logger.debug('Loading full tool definition', {
126
+ toolName,
127
+ filePath: metadata.filePath
128
+ });
129
+ const module = await import(metadata.filePath);
130
+ const creatorFn = Object.values(module).find((exp)=>typeof exp === 'function' && exp.name.startsWith('create'));
131
+ if (!creatorFn) {
132
+ throw new Error(`No tool creator function found in ${metadata.filePath}. ` + `Expected function name starting with 'create'.`);
133
+ }
134
+ const tool = creatorFn(logger);
135
+ if (tool.name !== toolName) {
136
+ this.logger.warn('Tool name mismatch', {
137
+ expected: toolName,
138
+ actual: tool.name,
139
+ filePath: metadata.filePath
140
+ });
141
+ }
142
+ this.toolCache.set(toolName, tool);
143
+ this.logger.info('Tool loaded successfully', {
144
+ toolName,
145
+ category: metadata.category
146
+ });
147
+ return tool;
148
+ } catch (error) {
149
+ this.logger.error('Failed to load tool', {
150
+ toolName,
151
+ error: error instanceof Error ? error.message : String(error)
152
+ });
153
+ return null;
154
+ }
155
+ }
156
+ getToolMetadata(toolName) {
157
+ return this.metadataCache.get(toolName);
158
+ }
159
+ searchTools(query) {
160
+ const results = [];
161
+ for (const metadata of this.metadataCache.values()){
162
+ if (query.category && metadata.category !== query.category) {
163
+ continue;
164
+ }
165
+ if (query.detailLevel && metadata.detailLevel !== query.detailLevel) {
166
+ continue;
167
+ }
168
+ if (query.tags && query.tags.length > 0) {
169
+ const toolTags = metadata.tags || [];
170
+ const hasAllTags = query.tags.every((tag)=>toolTags.includes(tag));
171
+ if (!hasAllTags) {
172
+ continue;
173
+ }
174
+ }
175
+ if (query.namePattern) {
176
+ const pattern = query.namePattern.toLowerCase();
177
+ if (!metadata.name.toLowerCase().includes(pattern) && !metadata.description.toLowerCase().includes(pattern)) {
178
+ continue;
179
+ }
180
+ }
181
+ results.push(metadata);
182
+ }
183
+ results.sort((a, b)=>a.name.localeCompare(b.name));
184
+ return results;
185
+ }
186
+ getAllToolNames() {
187
+ return Array.from(this.metadataCache.keys()).sort();
188
+ }
189
+ getToolsByCategory() {
190
+ const byCategory = new Map();
191
+ for (const metadata of this.metadataCache.values()){
192
+ const category = metadata.category;
193
+ if (!byCategory.has(category)) {
194
+ byCategory.set(category, []);
195
+ }
196
+ byCategory.get(category).push(metadata);
197
+ }
198
+ return byCategory;
199
+ }
200
+ getStats() {
201
+ const byCategory = this.getToolsByCategory();
202
+ return {
203
+ totalTools: this.metadataCache.size,
204
+ cachedTools: this.toolCache.size,
205
+ categories: Array.from(byCategory.keys()).sort(),
206
+ toolsByCategory: Object.fromEntries(Array.from(byCategory.entries()).map(([cat, tools])=>[
207
+ cat,
208
+ tools.length
209
+ ])),
210
+ scanComplete: this.scanComplete
211
+ };
212
+ }
213
+ clearCache() {
214
+ this.toolCache.clear();
215
+ this.logger.info('Tool cache cleared', {
216
+ previouslyCached: this.toolCache.size
217
+ });
218
+ }
219
+ async reload() {
220
+ this.metadataCache.clear();
221
+ this.toolCache.clear();
222
+ this.scanComplete = false;
223
+ await this.scanTools();
224
+ this.logger.info('Tool loader reloaded');
225
+ }
226
+ }
227
+
228
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/mcp/tools/loader.ts"],"sourcesContent":["/**\n * Dynamic Tool Loader for Progressive Disclosure\n *\n * Implements filesystem-based tool discovery pattern recommended by Anthropic:\n * - Scans tool directories for metadata only (lightweight)\n * - Loads full tool definitions on-demand (lazy loading)\n * - Supports tiered detail levels for search\n * - Achieves 98.7% token reduction (150k → 2k tokens)\n */\n\nimport { promises as fs } from 'fs';\nimport { join, dirname, extname, resolve } from 'path';\nimport { fileURLToPath } from 'url';\nimport type { MCPTool } from '../types.js';\nimport type { ILogger } from '../../interfaces/logger.js';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Lightweight tool metadata for discovery\n * Loaded without executing full tool definition\n */\nexport interface ToolMetadata {\n name: string;\n description: string;\n category: string;\n detailLevel: 'basic' | 'standard' | 'full';\n filePath: string;\n tags?: string[];\n}\n\n/**\n * Tool search query interface\n */\nexport interface ToolSearchQuery {\n category?: string;\n tags?: string[];\n detailLevel?: 'basic' | 'standard' | 'full';\n namePattern?: string;\n}\n\n/**\n * Dynamic tool loader with progressive disclosure\n */\nexport class DynamicToolLoader {\n private metadataCache: Map<string, ToolMetadata> = new Map();\n private toolCache: Map<string, MCPTool> = new Map();\n private scanComplete = false;\n\n constructor(\n private toolsDir: string = join(__dirname, '.'),\n private logger: ILogger\n ) {}\n\n /**\n * Scan tool directory and build metadata index\n * Only reads metadata exports, not full tool definitions\n * This is the key to achieving 98.7% token reduction\n */\n async scanTools(): Promise<Map<string, ToolMetadata>> {\n if (this.scanComplete) {\n return this.metadataCache;\n }\n\n this.logger.info('Scanning tools directory for metadata', {\n toolsDir: this.toolsDir,\n });\n\n const startTime = Date.now();\n let scannedFiles = 0;\n let loadedMetadata = 0;\n\n try {\n // Resolve tools directory to absolute path\n const resolvedToolsDir = resolve(this.toolsDir);\n\n // Get all subdirectories (categories)\n const entries = await fs.readdir(resolvedToolsDir, { withFileTypes: true });\n const categories = entries.filter(e => e.isDirectory() && !e.name.startsWith('_'));\n\n // Scan each category\n for (const categoryEntry of categories) {\n const category = categoryEntry.name;\n const categoryPath = resolve(resolvedToolsDir, category);\n\n // Prevent path traversal - ensure category is within tools directory\n if (!categoryPath.startsWith(resolvedToolsDir)) {\n this.logger.warn('Skipping category outside tools directory', {\n category,\n categoryPath,\n toolsDir: resolvedToolsDir,\n });\n continue;\n }\n\n try {\n // Get tool files in category\n const toolFiles = await fs.readdir(categoryPath);\n const validToolFiles = toolFiles.filter(f => {\n const ext = extname(f);\n return (ext === '.ts' || ext === '.js') && !f.startsWith('_');\n });\n\n // Load metadata from each file\n for (const toolFile of validToolFiles) {\n scannedFiles++;\n const toolPath = resolve(categoryPath, toolFile);\n\n // Prevent path traversal - ensure tool file is within category\n if (!toolPath.startsWith(categoryPath)) {\n this.logger.warn('Skipping tool file outside category directory', {\n toolFile,\n toolPath,\n categoryPath,\n });\n continue;\n }\n\n try {\n // Dynamic import to load metadata only\n const module = await import(toolPath);\n\n if (module.toolMetadata) {\n const metadata: ToolMetadata = {\n ...module.toolMetadata,\n category, // Override with directory category\n filePath: toolPath,\n };\n\n this.metadataCache.set(metadata.name, metadata);\n loadedMetadata++;\n\n this.logger.debug('Loaded tool metadata', {\n name: metadata.name,\n category: metadata.category,\n filePath: toolPath,\n });\n } else {\n this.logger.warn('Tool file missing toolMetadata export', {\n filePath: toolPath,\n });\n }\n } catch (error) {\n this.logger.error('Failed to load tool metadata', {\n filePath: toolPath,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n } catch (error) {\n this.logger.error('Failed to scan category directory', {\n category,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n const scanTime = Date.now() - startTime;\n this.scanComplete = true;\n\n this.logger.info('Tool scan complete', {\n scannedFiles,\n loadedMetadata,\n totalTools: this.metadataCache.size,\n scanTimeMs: scanTime,\n });\n\n return this.metadataCache;\n } catch (error) {\n this.logger.error('Failed to scan tools directory', {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Lazy load a specific tool by name\n * Only loads when actually needed (on invocation)\n */\n async loadTool(toolName: string, logger: ILogger): Promise<MCPTool | null> {\n // Check cache first\n if (this.toolCache.has(toolName)) {\n this.logger.debug('Tool loaded from cache', { toolName });\n return this.toolCache.get(toolName)!;\n }\n\n // Get metadata\n const metadata = this.metadataCache.get(toolName);\n if (!metadata) {\n this.logger.warn('Tool not found in metadata cache', { toolName });\n return null;\n }\n\n // Load full tool definition\n try {\n this.logger.debug('Loading full tool definition', {\n toolName,\n filePath: metadata.filePath,\n });\n\n const module = await import(metadata.filePath);\n\n // Find tool creator function (convention: createXxxTool)\n const creatorFn = Object.values(module).find(\n (exp: any) => typeof exp === 'function' && exp.name.startsWith('create')\n ) as ((logger: ILogger) => MCPTool) | undefined;\n\n if (!creatorFn) {\n throw new Error(\n `No tool creator function found in ${metadata.filePath}. ` +\n `Expected function name starting with 'create'.`\n );\n }\n\n // Create tool instance\n const tool = creatorFn(logger);\n\n // Validate tool name matches metadata\n if (tool.name !== toolName) {\n this.logger.warn('Tool name mismatch', {\n expected: toolName,\n actual: tool.name,\n filePath: metadata.filePath,\n });\n }\n\n // Cache for future use\n this.toolCache.set(toolName, tool);\n\n this.logger.info('Tool loaded successfully', {\n toolName,\n category: metadata.category,\n });\n\n return tool;\n } catch (error) {\n this.logger.error('Failed to load tool', {\n toolName,\n error: error instanceof Error ? error.message : String(error),\n });\n return null;\n }\n }\n\n /**\n * Get tool metadata without loading full definition\n * Used for tool discovery with minimal token usage\n */\n getToolMetadata(toolName: string): ToolMetadata | undefined {\n return this.metadataCache.get(toolName);\n }\n\n /**\n * Search tools by query\n * Returns only metadata for matching tools (lightweight)\n */\n searchTools(query: ToolSearchQuery): ToolMetadata[] {\n const results: ToolMetadata[] = [];\n\n for (const metadata of this.metadataCache.values()) {\n // Filter by category\n if (query.category && metadata.category !== query.category) {\n continue;\n }\n\n // Filter by detail level\n if (query.detailLevel && metadata.detailLevel !== query.detailLevel) {\n continue;\n }\n\n // Filter by tags\n if (query.tags && query.tags.length > 0) {\n const toolTags = metadata.tags || [];\n const hasAllTags = query.tags.every(tag => toolTags.includes(tag));\n if (!hasAllTags) {\n continue;\n }\n }\n\n // Filter by name pattern\n if (query.namePattern) {\n const pattern = query.namePattern.toLowerCase();\n if (!metadata.name.toLowerCase().includes(pattern) &&\n !metadata.description.toLowerCase().includes(pattern)) {\n continue;\n }\n }\n\n results.push(metadata);\n }\n\n // Sort by name\n results.sort((a, b) => a.name.localeCompare(b.name));\n\n return results;\n }\n\n /**\n * Get all tool names (minimal metadata)\n * Used for quick tool listing\n */\n getAllToolNames(): string[] {\n return Array.from(this.metadataCache.keys()).sort();\n }\n\n /**\n * Get tools grouped by category\n */\n getToolsByCategory(): Map<string, ToolMetadata[]> {\n const byCategory = new Map<string, ToolMetadata[]>();\n\n for (const metadata of this.metadataCache.values()) {\n const category = metadata.category;\n if (!byCategory.has(category)) {\n byCategory.set(category, []);\n }\n byCategory.get(category)!.push(metadata);\n }\n\n return byCategory;\n }\n\n /**\n * Get statistics about loaded tools\n */\n getStats() {\n const byCategory = this.getToolsByCategory();\n\n return {\n totalTools: this.metadataCache.size,\n cachedTools: this.toolCache.size,\n categories: Array.from(byCategory.keys()).sort(),\n toolsByCategory: Object.fromEntries(\n Array.from(byCategory.entries()).map(([cat, tools]) => [cat, tools.length])\n ),\n scanComplete: this.scanComplete,\n };\n }\n\n /**\n * Clear tool cache (useful for hot reloading during development)\n */\n clearCache(): void {\n this.toolCache.clear();\n this.logger.info('Tool cache cleared', {\n previouslyCached: this.toolCache.size,\n });\n }\n\n /**\n * Reload metadata (useful for hot reloading during development)\n */\n async reload(): Promise<void> {\n this.metadataCache.clear();\n this.toolCache.clear();\n this.scanComplete = false;\n await this.scanTools();\n this.logger.info('Tool loader reloaded');\n }\n}\n"],"names":["promises","fs","join","dirname","extname","resolve","fileURLToPath","__filename","url","__dirname","DynamicToolLoader","metadataCache","Map","toolCache","scanComplete","toolsDir","logger","scanTools","info","startTime","Date","now","scannedFiles","loadedMetadata","resolvedToolsDir","entries","readdir","withFileTypes","categories","filter","e","isDirectory","name","startsWith","categoryEntry","category","categoryPath","warn","toolFiles","validToolFiles","f","ext","toolFile","toolPath","module","toolMetadata","metadata","filePath","set","debug","error","Error","message","String","scanTime","totalTools","size","scanTimeMs","loadTool","toolName","has","get","creatorFn","Object","values","find","exp","tool","expected","actual","getToolMetadata","searchTools","query","results","detailLevel","tags","length","toolTags","hasAllTags","every","tag","includes","namePattern","pattern","toLowerCase","description","push","sort","a","b","localeCompare","getAllToolNames","Array","from","keys","getToolsByCategory","byCategory","getStats","cachedTools","toolsByCategory","fromEntries","map","cat","tools","clearCache","clear","previouslyCached","reload"],"mappings":"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"}
@@ -0,0 +1,224 @@
1
+ export function createSearchToolsTool(loader, logger) {
2
+ return {
3
+ name: 'tools/search',
4
+ description: "Search for tools with configurable detail levels. Use names-only for quick discovery (saves 98%+ tokens), basic for descriptions, full for complete schemas. This is the primary tool discovery mechanism.",
5
+ inputSchema: {
6
+ type: 'object',
7
+ properties: {
8
+ query: {
9
+ type: 'string',
10
+ description: "Search query (searches tool names and descriptions)"
11
+ },
12
+ category: {
13
+ type: 'string',
14
+ description: 'Filter by category',
15
+ enum: [
16
+ 'agents',
17
+ 'tasks',
18
+ 'memory',
19
+ 'system',
20
+ 'config',
21
+ 'workflow',
22
+ 'terminal',
23
+ 'query',
24
+ 'swarm',
25
+ 'data',
26
+ 'jobs'
27
+ ]
28
+ },
29
+ tags: {
30
+ type: 'array',
31
+ items: {
32
+ type: 'string'
33
+ },
34
+ description: 'Filter by tags (all tags must match)'
35
+ },
36
+ detailLevel: {
37
+ type: 'string',
38
+ enum: [
39
+ 'names-only',
40
+ 'basic',
41
+ 'full'
42
+ ],
43
+ description: "Level of detail to return. names-only: just names (fastest, minimal tokens). basic: name + description + category (recommended for discovery). full: complete schemas with examples (use only when needed)",
44
+ default: 'basic'
45
+ },
46
+ limit: {
47
+ type: 'number',
48
+ description: 'Maximum number of results (default: 20)',
49
+ minimum: 1,
50
+ maximum: 100,
51
+ default: 20
52
+ }
53
+ },
54
+ required: []
55
+ },
56
+ metadata: {
57
+ category: 'system',
58
+ tags: [
59
+ 'discovery',
60
+ 'search',
61
+ 'progressive-disclosure',
62
+ 'tools'
63
+ ],
64
+ examples: [
65
+ {
66
+ description: 'Quick search for agent-related tools (minimal tokens)',
67
+ input: {
68
+ query: 'agent',
69
+ detailLevel: 'names-only',
70
+ limit: 10
71
+ },
72
+ expectedOutput: {
73
+ tools: [
74
+ {
75
+ name: 'agents/spawn'
76
+ },
77
+ {
78
+ name: 'agents/list'
79
+ },
80
+ {
81
+ name: 'agents/terminate'
82
+ }
83
+ ],
84
+ totalMatches: 5,
85
+ detailLevel: 'names-only'
86
+ }
87
+ },
88
+ {
89
+ description: 'Get basic info about system tools',
90
+ input: {
91
+ category: 'system',
92
+ detailLevel: 'basic'
93
+ },
94
+ expectedOutput: {
95
+ tools: [
96
+ {
97
+ name: 'system/status',
98
+ description: 'Get system health status',
99
+ category: 'system'
100
+ }
101
+ ],
102
+ totalMatches: 3,
103
+ detailLevel: 'basic'
104
+ }
105
+ },
106
+ {
107
+ description: 'Get full schema for specific tool',
108
+ input: {
109
+ query: 'agents/spawn',
110
+ detailLevel: 'full',
111
+ limit: 1
112
+ },
113
+ expectedOutput: {
114
+ tools: [
115
+ {
116
+ name: 'agents/spawn',
117
+ description: 'Spawn a new agent',
118
+ category: 'agents',
119
+ inputSchema: {
120
+ type: 'object',
121
+ properties: {}
122
+ },
123
+ examples: []
124
+ }
125
+ ],
126
+ totalMatches: 1,
127
+ detailLevel: 'full'
128
+ }
129
+ }
130
+ ],
131
+ detailLevel: 'standard'
132
+ },
133
+ handler: async (input, context)=>{
134
+ const validatedInput = input;
135
+ const detailLevel = validatedInput.detailLevel || 'basic';
136
+ const limit = validatedInput.limit || 20;
137
+ logger.info('tools/search invoked', {
138
+ query: validatedInput.query,
139
+ category: validatedInput.category,
140
+ detailLevel,
141
+ limit
142
+ });
143
+ try {
144
+ const metadata = loader.searchTools({
145
+ category: validatedInput.category,
146
+ tags: validatedInput.tags,
147
+ namePattern: validatedInput.query
148
+ });
149
+ logger.debug('Tool search results', {
150
+ totalMatches: metadata.length,
151
+ detailLevel
152
+ });
153
+ const results = [];
154
+ const limitedMetadata = metadata.slice(0, limit);
155
+ for (const meta of limitedMetadata){
156
+ if (detailLevel === 'names-only') {
157
+ results.push({
158
+ name: meta.name
159
+ });
160
+ } else if (detailLevel === 'basic') {
161
+ results.push({
162
+ name: meta.name,
163
+ description: meta.description,
164
+ category: meta.category,
165
+ tags: meta.tags
166
+ });
167
+ } else if (detailLevel === 'full') {
168
+ const tool = await loader.loadTool(meta.name, logger);
169
+ if (tool) {
170
+ results.push({
171
+ name: tool.name,
172
+ description: tool.description,
173
+ category: meta.category,
174
+ tags: meta.tags,
175
+ inputSchema: tool.inputSchema,
176
+ examples: tool.metadata?.examples || []
177
+ });
178
+ }
179
+ }
180
+ }
181
+ const actualSize = JSON.stringify(results).length;
182
+ const estimatedFullSize = limitedMetadata.length * 2000;
183
+ const reductionPercent = detailLevel === 'full' ? 0 : (estimatedFullSize - actualSize) / estimatedFullSize * 100;
184
+ logger.info('tools/search completed successfully', {
185
+ resultsCount: results.length,
186
+ totalMatches: metadata.length,
187
+ detailLevel,
188
+ actualSizeBytes: actualSize,
189
+ reductionPercent: reductionPercent.toFixed(2)
190
+ });
191
+ return {
192
+ success: true,
193
+ tools: results,
194
+ totalMatches: metadata.length,
195
+ detailLevel,
196
+ tokenSavings: detailLevel !== 'full' ? {
197
+ estimatedFullSize,
198
+ actualSize,
199
+ reductionPercent: Math.round(reductionPercent * 100) / 100
200
+ } : undefined
201
+ };
202
+ } catch (error) {
203
+ logger.error('tools/search failed', {
204
+ error,
205
+ input: validatedInput
206
+ });
207
+ throw error;
208
+ }
209
+ }
210
+ };
211
+ }
212
+ export const toolMetadata = {
213
+ name: 'tools/search',
214
+ description: 'Search and discover tools with progressive disclosure',
215
+ category: 'system',
216
+ detailLevel: 'standard',
217
+ tags: [
218
+ 'discovery',
219
+ 'search',
220
+ 'tools'
221
+ ]
222
+ };
223
+
224
+ //# sourceMappingURL=search.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../../src/mcp/tools/system/search.ts"],"sourcesContent":["/**\n * Tool Search Capability (tools/search)\n *\n * Implements progressive disclosure pattern with tiered detail levels:\n * - names-only: Just tool names (minimal tokens)\n * - basic: Name + description + category\n * - full: Complete schemas with examples\n *\n * This is the key to achieving 98.7% token reduction.\n */\n\nimport type { MCPTool, ClaudeFlowToolContext } from '../../types.js';\nimport type { ILogger } from '../../../interfaces/logger.js';\nimport type { DynamicToolLoader, ToolMetadata } from '../loader.js';\n\ninterface SearchToolsInput {\n query?: string;\n category?: string;\n tags?: string[];\n detailLevel?: 'names-only' | 'basic' | 'full';\n limit?: number;\n}\n\ninterface ToolSearchResult {\n name: string;\n description?: string;\n category?: string;\n tags?: string[];\n inputSchema?: any;\n examples?: any[];\n}\n\ninterface SearchToolsResult {\n success: boolean;\n tools: ToolSearchResult[];\n totalMatches: number;\n detailLevel: string;\n tokenSavings?: {\n estimatedFullSize: number;\n actualSize: number;\n reductionPercent: number;\n };\n}\n\n/**\n * Create tool search capability\n *\n * @param loader - Dynamic tool loader instance\n * @param logger - Logger instance\n * @returns MCPTool definition\n */\nexport function createSearchToolsTool(\n loader: DynamicToolLoader,\n logger: ILogger\n): MCPTool {\n return {\n name: 'tools/search',\n description: 'Search for tools with configurable detail levels. Use names-only for quick discovery (saves 98%+ tokens), basic for descriptions, full for complete schemas. This is the primary tool discovery mechanism.',\n\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'Search query (searches tool names and descriptions)',\n },\n category: {\n type: 'string',\n description: 'Filter by category',\n enum: [\n 'agents',\n 'tasks',\n 'memory',\n 'system',\n 'config',\n 'workflow',\n 'terminal',\n 'query',\n 'swarm',\n 'data',\n 'jobs',\n ],\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Filter by tags (all tags must match)',\n },\n detailLevel: {\n type: 'string',\n enum: ['names-only', 'basic', 'full'],\n description: 'Level of detail to return. names-only: just names (fastest, minimal tokens). basic: name + description + category (recommended for discovery). full: complete schemas with examples (use only when needed)',\n default: 'basic',\n },\n limit: {\n type: 'number',\n description: 'Maximum number of results (default: 20)',\n minimum: 1,\n maximum: 100,\n default: 20,\n },\n },\n required: [],\n },\n\n metadata: {\n category: 'system',\n tags: ['discovery', 'search', 'progressive-disclosure', 'tools'],\n examples: [\n {\n description: 'Quick search for agent-related tools (minimal tokens)',\n input: {\n query: 'agent',\n detailLevel: 'names-only',\n limit: 10,\n },\n expectedOutput: {\n tools: [\n { name: 'agents/spawn' },\n { name: 'agents/list' },\n { name: 'agents/terminate' },\n ],\n totalMatches: 5,\n detailLevel: 'names-only',\n },\n },\n {\n description: 'Get basic info about system tools',\n input: {\n category: 'system',\n detailLevel: 'basic',\n },\n expectedOutput: {\n tools: [\n {\n name: 'system/status',\n description: 'Get system health status',\n category: 'system',\n },\n ],\n totalMatches: 3,\n detailLevel: 'basic',\n },\n },\n {\n description: 'Get full schema for specific tool',\n input: {\n query: 'agents/spawn',\n detailLevel: 'full',\n limit: 1,\n },\n expectedOutput: {\n tools: [\n {\n name: 'agents/spawn',\n description: 'Spawn a new agent',\n category: 'agents',\n inputSchema: { type: 'object', properties: {} },\n examples: [],\n },\n ],\n totalMatches: 1,\n detailLevel: 'full',\n },\n },\n ],\n detailLevel: 'standard',\n },\n\n handler: async (\n input: any,\n context?: ClaudeFlowToolContext\n ): Promise<SearchToolsResult> => {\n const validatedInput = input as SearchToolsInput;\n const detailLevel = validatedInput.detailLevel || 'basic';\n const limit = validatedInput.limit || 20;\n\n logger.info('tools/search invoked', {\n query: validatedInput.query,\n category: validatedInput.category,\n detailLevel,\n limit,\n });\n\n try {\n // Search tool metadata (lightweight operation)\n const metadata = loader.searchTools({\n category: validatedInput.category,\n tags: validatedInput.tags,\n namePattern: validatedInput.query,\n });\n\n logger.debug('Tool search results', {\n totalMatches: metadata.length,\n detailLevel,\n });\n\n // Process results based on detail level\n const results: ToolSearchResult[] = [];\n const limitedMetadata = metadata.slice(0, limit);\n\n for (const meta of limitedMetadata) {\n if (detailLevel === 'names-only') {\n // Minimal: Just name (saves most tokens)\n results.push({ name: meta.name });\n } else if (detailLevel === 'basic') {\n // Basic: Name + description + category + tags\n results.push({\n name: meta.name,\n description: meta.description,\n category: meta.category,\n tags: meta.tags,\n });\n } else if (detailLevel === 'full') {\n // Full: Load complete tool definition including schema\n const tool = await loader.loadTool(meta.name, logger);\n if (tool) {\n results.push({\n name: tool.name,\n description: tool.description,\n category: meta.category,\n tags: meta.tags,\n inputSchema: tool.inputSchema,\n examples: tool.metadata?.examples || [],\n });\n }\n }\n }\n\n // Calculate token savings for demonstration\n const actualSize = JSON.stringify(results).length;\n const estimatedFullSize = limitedMetadata.length * 2000; // Estimate 2KB per full tool\n const reductionPercent = detailLevel === 'full'\n ? 0\n : ((estimatedFullSize - actualSize) / estimatedFullSize) * 100;\n\n logger.info('tools/search completed successfully', {\n resultsCount: results.length,\n totalMatches: metadata.length,\n detailLevel,\n actualSizeBytes: actualSize,\n reductionPercent: reductionPercent.toFixed(2),\n });\n\n return {\n success: true,\n tools: results,\n totalMatches: metadata.length,\n detailLevel,\n tokenSavings:\n detailLevel !== 'full'\n ? {\n estimatedFullSize,\n actualSize,\n reductionPercent: Math.round(reductionPercent * 100) / 100,\n }\n : undefined,\n };\n } catch (error) {\n logger.error('tools/search failed', {\n error,\n input: validatedInput,\n });\n throw error;\n }\n },\n };\n}\n\nexport const toolMetadata = {\n name: 'tools/search',\n description: 'Search and discover tools with progressive disclosure',\n category: 'system',\n detailLevel: 'standard' as const,\n tags: ['discovery', 'search', 'tools'],\n};\n"],"names":["createSearchToolsTool","loader","logger","name","description","inputSchema","type","properties","query","category","enum","tags","items","detailLevel","default","limit","minimum","maximum","required","metadata","examples","input","expectedOutput","tools","totalMatches","handler","context","validatedInput","info","searchTools","namePattern","debug","length","results","limitedMetadata","slice","meta","push","tool","loadTool","actualSize","JSON","stringify","estimatedFullSize","reductionPercent","resultsCount","actualSizeBytes","toFixed","success","tokenSavings","Math","round","undefined","error","toolMetadata"],"mappings":"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"}