claude-flow 2.7.32 → 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.
- package/.claude/settings.local.json +9 -2
- package/.claude/skills/agentic-jujutsu/SKILL.md +645 -0
- package/CHANGELOG.md +75 -0
- package/bin/claude-flow +1 -1
- package/dist/src/cli/commands/mcp.js +61 -7
- package/dist/src/cli/commands/mcp.js.map +1 -1
- package/dist/src/cli/help-formatter.js +5 -3
- package/dist/src/cli/help-formatter.js.map +1 -1
- package/dist/src/cli/simple-cli.js +173 -79
- package/dist/src/cli/simple-cli.js.map +1 -1
- package/dist/src/cli/validation-helper.js.map +1 -1
- package/dist/src/core/version.js +2 -2
- package/dist/src/core/version.js.map +1 -1
- package/dist/src/mcp/async/job-manager-mcp25.js +240 -0
- package/dist/src/mcp/async/job-manager-mcp25.js.map +1 -0
- package/dist/src/mcp/index.js +8 -0
- package/dist/src/mcp/index.js.map +1 -1
- package/dist/src/mcp/protocol/version-negotiation.js +182 -0
- package/dist/src/mcp/protocol/version-negotiation.js.map +1 -0
- package/dist/src/mcp/registry/mcp-registry-client-2025.js +210 -0
- package/dist/src/mcp/registry/mcp-registry-client-2025.js.map +1 -0
- package/dist/src/mcp/server-factory.js +189 -0
- package/dist/src/mcp/server-factory.js.map +1 -0
- package/dist/src/mcp/server-mcp-2025.js +283 -0
- package/dist/src/mcp/server-mcp-2025.js.map +1 -0
- package/dist/src/mcp/tool-registry-progressive.js +319 -0
- package/dist/src/mcp/tool-registry-progressive.js.map +1 -0
- package/dist/src/mcp/tools/_template.js +62 -0
- package/dist/src/mcp/tools/_template.js.map +1 -0
- package/dist/src/mcp/tools/loader.js +228 -0
- package/dist/src/mcp/tools/loader.js.map +1 -0
- package/dist/src/mcp/tools/system/search.js +224 -0
- package/dist/src/mcp/tools/system/search.js.map +1 -0
- package/dist/src/mcp/tools/system/status.js +168 -0
- package/dist/src/mcp/tools/system/status.js.map +1 -0
- package/dist/src/mcp/validation/schema-validator-2025.js +198 -0
- package/dist/src/mcp/validation/schema-validator-2025.js.map +1 -0
- package/dist/src/memory/swarm-memory.js +340 -421
- package/dist/src/memory/swarm-memory.js.map +1 -1
- package/docs/.claude-flow/metrics/performance.json +3 -3
- package/docs/.claude-flow/metrics/task-metrics.json +3 -3
- package/docs/.github-release-issue-v2.7.33.md +488 -0
- package/docs/AGENTDB_BRANCH_MERGE_VERIFICATION.md +436 -0
- package/docs/BRANCH_REVIEW_SUMMARY.md +439 -0
- package/docs/DEEP_CODE_REVIEW_v2.7.33.md +1159 -0
- package/docs/MCP_2025_FEATURE_CONFIRMATION.md +698 -0
- package/docs/NPM_PUBLISH_GUIDE_v2.7.33.md +628 -0
- package/docs/REGRESSION_TEST_REPORT_v2.7.33.md +397 -0
- package/docs/RELEASE_NOTES_v2.7.33.md +618 -0
- package/docs/RELEASE_READINESS_SUMMARY.md +377 -0
- package/docs/RELEASE_SUMMARY_v2.7.33.md +456 -0
- package/docs/agentic-flow-agentdb-mcp-integration.md +1198 -0
- package/docs/mcp-2025-implementation-summary.md +459 -0
- package/docs/mcp-spec-2025-implementation-plan.md +1330 -0
- package/docs/phase-1-2-implementation-summary.md +676 -0
- package/docs/regression-analysis-phase-1-2.md +555 -0
- package/package.json +5 -1
- package/src/cli/commands/mcp.ts +86 -9
- package/src/mcp/async/job-manager-mcp25.ts +456 -0
- package/src/mcp/index.ts +60 -0
- package/src/mcp/protocol/version-negotiation.ts +329 -0
- package/src/mcp/registry/mcp-registry-client-2025.ts +334 -0
- package/src/mcp/server-factory.ts +426 -0
- package/src/mcp/server-mcp-2025.ts +507 -0
- package/src/mcp/tool-registry-progressive.ts +539 -0
- package/src/mcp/tools/_template.ts +174 -0
- package/src/mcp/tools/loader.ts +362 -0
- package/src/mcp/tools/system/search.ts +276 -0
- package/src/mcp/tools/system/status.ts +206 -0
- package/src/mcp/validation/schema-validator-2025.ts +294 -0
- package/docs/AGENTDB_V1.6.1_DEEP_REVIEW.md +0 -386
- package/docs/RECENT_RELEASES_SUMMARY.md +0 -375
- package/docs/V2.7.31_RELEASE_NOTES.md +0 -375
|
@@ -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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"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
export function createSystemStatusTool(logger) {
|
|
2
|
+
return {
|
|
3
|
+
name: 'system/status',
|
|
4
|
+
description: 'Get comprehensive system status including uptime, active agents, tasks, and performance metrics. Use this to check system health.',
|
|
5
|
+
inputSchema: {
|
|
6
|
+
type: 'object',
|
|
7
|
+
properties: {
|
|
8
|
+
includeMetrics: {
|
|
9
|
+
type: 'boolean',
|
|
10
|
+
description: 'Include performance metrics',
|
|
11
|
+
default: false
|
|
12
|
+
},
|
|
13
|
+
includeAgents: {
|
|
14
|
+
type: 'boolean',
|
|
15
|
+
description: 'Include agent statistics',
|
|
16
|
+
default: true
|
|
17
|
+
},
|
|
18
|
+
includeTasks: {
|
|
19
|
+
type: 'boolean',
|
|
20
|
+
description: 'Include task statistics',
|
|
21
|
+
default: true
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
required: []
|
|
25
|
+
},
|
|
26
|
+
metadata: {
|
|
27
|
+
category: 'system',
|
|
28
|
+
tags: [
|
|
29
|
+
'status',
|
|
30
|
+
'health',
|
|
31
|
+
'monitoring',
|
|
32
|
+
'metrics'
|
|
33
|
+
],
|
|
34
|
+
examples: [
|
|
35
|
+
{
|
|
36
|
+
description: 'Get basic system status',
|
|
37
|
+
input: {},
|
|
38
|
+
expectedOutput: {
|
|
39
|
+
success: true,
|
|
40
|
+
status: 'healthy',
|
|
41
|
+
uptime: 3600000,
|
|
42
|
+
version: '2.7.32'
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
description: 'Get full system status with metrics',
|
|
47
|
+
input: {
|
|
48
|
+
includeMetrics: true,
|
|
49
|
+
includeAgents: true,
|
|
50
|
+
includeTasks: true
|
|
51
|
+
},
|
|
52
|
+
expectedOutput: {
|
|
53
|
+
success: true,
|
|
54
|
+
status: 'healthy',
|
|
55
|
+
agents: {
|
|
56
|
+
total: 5,
|
|
57
|
+
active: 3,
|
|
58
|
+
idle: 2
|
|
59
|
+
},
|
|
60
|
+
tasks: {
|
|
61
|
+
total: 20,
|
|
62
|
+
running: 5,
|
|
63
|
+
completed: 12,
|
|
64
|
+
failed: 3
|
|
65
|
+
},
|
|
66
|
+
metrics: {
|
|
67
|
+
memoryUsage: 250,
|
|
68
|
+
cpuUsage: 45,
|
|
69
|
+
avgResponseTime: 150
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
],
|
|
74
|
+
detailLevel: 'standard'
|
|
75
|
+
},
|
|
76
|
+
handler: async (input, context)=>{
|
|
77
|
+
if (!context?.orchestrator) {
|
|
78
|
+
throw new Error('Orchestrator not available in tool context');
|
|
79
|
+
}
|
|
80
|
+
const validatedInput = input;
|
|
81
|
+
logger.info('system/status invoked', {
|
|
82
|
+
input: validatedInput,
|
|
83
|
+
sessionId: context.sessionId
|
|
84
|
+
});
|
|
85
|
+
try {
|
|
86
|
+
const result = {
|
|
87
|
+
success: true,
|
|
88
|
+
status: 'healthy',
|
|
89
|
+
uptime: process.uptime() * 1000,
|
|
90
|
+
version: process.env.npm_package_version || '2.7.32',
|
|
91
|
+
timestamp: new Date().toISOString()
|
|
92
|
+
};
|
|
93
|
+
if (validatedInput.includeAgents !== false) {
|
|
94
|
+
try {
|
|
95
|
+
const agentStats = await context.orchestrator.getAgentStats?.();
|
|
96
|
+
if (agentStats) {
|
|
97
|
+
result.agents = {
|
|
98
|
+
total: agentStats.total || 0,
|
|
99
|
+
active: agentStats.active || 0,
|
|
100
|
+
idle: agentStats.idle || 0
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
} catch (error) {
|
|
104
|
+
logger.warn('Failed to get agent statistics', {
|
|
105
|
+
error
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
if (validatedInput.includeTasks !== false) {
|
|
110
|
+
try {
|
|
111
|
+
const taskStats = await context.orchestrator.getTaskStats?.();
|
|
112
|
+
if (taskStats) {
|
|
113
|
+
result.tasks = {
|
|
114
|
+
total: taskStats.total || 0,
|
|
115
|
+
running: taskStats.running || 0,
|
|
116
|
+
completed: taskStats.completed || 0,
|
|
117
|
+
failed: taskStats.failed || 0
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
} catch (error) {
|
|
121
|
+
logger.warn('Failed to get task statistics', {
|
|
122
|
+
error
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (validatedInput.includeMetrics) {
|
|
127
|
+
try {
|
|
128
|
+
const memUsage = process.memoryUsage();
|
|
129
|
+
result.metrics = {
|
|
130
|
+
memoryUsage: Math.round(memUsage.heapUsed / 1024 / 1024),
|
|
131
|
+
cpuUsage: Math.round(process.cpuUsage().user / 1000),
|
|
132
|
+
avgResponseTime: 0
|
|
133
|
+
};
|
|
134
|
+
} catch (error) {
|
|
135
|
+
logger.warn('Failed to get performance metrics', {
|
|
136
|
+
error
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (result.agents && result.agents.active === 0 && result.agents.total > 0) {
|
|
141
|
+
result.status = 'degraded';
|
|
142
|
+
}
|
|
143
|
+
if (result.tasks && result.tasks.failed > result.tasks.completed / 2) {
|
|
144
|
+
result.status = 'unhealthy';
|
|
145
|
+
}
|
|
146
|
+
logger.info('system/status completed successfully', {
|
|
147
|
+
status: result.status,
|
|
148
|
+
uptime: result.uptime
|
|
149
|
+
});
|
|
150
|
+
return result;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
logger.error('system/status failed', {
|
|
153
|
+
error,
|
|
154
|
+
input: validatedInput
|
|
155
|
+
});
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
export const toolMetadata = {
|
|
162
|
+
name: 'system/status',
|
|
163
|
+
description: 'Get system health status and metrics',
|
|
164
|
+
category: 'system',
|
|
165
|
+
detailLevel: 'standard'
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../src/mcp/tools/system/status.ts"],"sourcesContent":["/**\n * System Status Tool\n *\n * Returns comprehensive system status including:\n * - Uptime and version information\n * - Active agents and tasks\n * - Memory usage\n * - Performance metrics\n */\n\nimport type { MCPTool, ClaudeFlowToolContext } from '../../types.js';\nimport type { ILogger } from '../../../interfaces/logger.js';\n\ninterface SystemStatusInput {\n includeMetrics?: boolean;\n includeAgents?: boolean;\n includeTasks?: boolean;\n}\n\ninterface SystemStatusResult {\n success: boolean;\n status: 'healthy' | 'degraded' | 'unhealthy';\n uptime: number;\n version: string;\n timestamp: string;\n agents?: {\n total: number;\n active: number;\n idle: number;\n };\n tasks?: {\n total: number;\n running: number;\n completed: number;\n failed: number;\n };\n metrics?: {\n memoryUsage: number;\n cpuUsage: number;\n avgResponseTime: number;\n };\n}\n\nexport function createSystemStatusTool(logger: ILogger): MCPTool {\n return {\n name: 'system/status',\n description: 'Get comprehensive system status including uptime, active agents, tasks, and performance metrics. Use this to check system health.',\n\n inputSchema: {\n type: 'object',\n properties: {\n includeMetrics: {\n type: 'boolean',\n description: 'Include performance metrics',\n default: false,\n },\n includeAgents: {\n type: 'boolean',\n description: 'Include agent statistics',\n default: true,\n },\n includeTasks: {\n type: 'boolean',\n description: 'Include task statistics',\n default: true,\n },\n },\n required: [],\n },\n\n metadata: {\n category: 'system',\n tags: ['status', 'health', 'monitoring', 'metrics'],\n examples: [\n {\n description: 'Get basic system status',\n input: {},\n expectedOutput: {\n success: true,\n status: 'healthy',\n uptime: 3600000,\n version: '2.7.32',\n },\n },\n {\n description: 'Get full system status with metrics',\n input: {\n includeMetrics: true,\n includeAgents: true,\n includeTasks: true,\n },\n expectedOutput: {\n success: true,\n status: 'healthy',\n agents: { total: 5, active: 3, idle: 2 },\n tasks: { total: 20, running: 5, completed: 12, failed: 3 },\n metrics: { memoryUsage: 250, cpuUsage: 45, avgResponseTime: 150 },\n },\n },\n ],\n detailLevel: 'standard',\n },\n\n handler: async (\n input: any,\n context?: ClaudeFlowToolContext\n ): Promise<SystemStatusResult> => {\n if (!context?.orchestrator) {\n throw new Error('Orchestrator not available in tool context');\n }\n\n const validatedInput = input as SystemStatusInput;\n\n logger.info('system/status invoked', {\n input: validatedInput,\n sessionId: context.sessionId,\n });\n\n try {\n // Get base status\n const result: SystemStatusResult = {\n success: true,\n status: 'healthy',\n uptime: process.uptime() * 1000, // Convert to milliseconds\n version: process.env.npm_package_version || '2.7.32',\n timestamp: new Date().toISOString(),\n };\n\n // Get agent statistics if requested\n if (validatedInput.includeAgents !== false) {\n try {\n const agentStats = await context.orchestrator.getAgentStats?.();\n if (agentStats) {\n result.agents = {\n total: agentStats.total || 0,\n active: agentStats.active || 0,\n idle: agentStats.idle || 0,\n };\n }\n } catch (error) {\n logger.warn('Failed to get agent statistics', { error });\n }\n }\n\n // Get task statistics if requested\n if (validatedInput.includeTasks !== false) {\n try {\n const taskStats = await context.orchestrator.getTaskStats?.();\n if (taskStats) {\n result.tasks = {\n total: taskStats.total || 0,\n running: taskStats.running || 0,\n completed: taskStats.completed || 0,\n failed: taskStats.failed || 0,\n };\n }\n } catch (error) {\n logger.warn('Failed to get task statistics', { error });\n }\n }\n\n // Get performance metrics if requested\n if (validatedInput.includeMetrics) {\n try {\n const memUsage = process.memoryUsage();\n result.metrics = {\n memoryUsage: Math.round(memUsage.heapUsed / 1024 / 1024), // MB\n cpuUsage: Math.round(process.cpuUsage().user / 1000), // Approximate %\n avgResponseTime: 0, // TODO: Get from metrics store\n };\n } catch (error) {\n logger.warn('Failed to get performance metrics', { error });\n }\n }\n\n // Determine overall health status\n if (result.agents && result.agents.active === 0 && result.agents.total > 0) {\n result.status = 'degraded';\n }\n if (result.tasks && result.tasks.failed > result.tasks.completed / 2) {\n result.status = 'unhealthy';\n }\n\n logger.info('system/status completed successfully', {\n status: result.status,\n uptime: result.uptime,\n });\n\n return result;\n } catch (error) {\n logger.error('system/status failed', {\n error,\n input: validatedInput,\n });\n throw error;\n }\n },\n };\n}\n\nexport const toolMetadata = {\n name: 'system/status',\n description: 'Get system health status and metrics',\n category: 'system',\n detailLevel: 'standard' as const,\n};\n"],"names":["createSystemStatusTool","logger","name","description","inputSchema","type","properties","includeMetrics","default","includeAgents","includeTasks","required","metadata","category","tags","examples","input","expectedOutput","success","status","uptime","version","agents","total","active","idle","tasks","running","completed","failed","metrics","memoryUsage","cpuUsage","avgResponseTime","detailLevel","handler","context","orchestrator","Error","validatedInput","info","sessionId","result","process","env","npm_package_version","timestamp","Date","toISOString","agentStats","getAgentStats","error","warn","taskStats","getTaskStats","memUsage","Math","round","heapUsed","user","toolMetadata"],"mappings":"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"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import Ajv from 'ajv';
|
|
2
|
+
import addFormats from 'ajv-formats';
|
|
3
|
+
import addErrors from 'ajv-errors';
|
|
4
|
+
export class SchemaValidator {
|
|
5
|
+
logger;
|
|
6
|
+
ajv;
|
|
7
|
+
schemaCache = new Map();
|
|
8
|
+
cacheTTL = 3600000;
|
|
9
|
+
MAX_CACHE_SIZE = 1000;
|
|
10
|
+
constructor(logger){
|
|
11
|
+
this.logger = logger;
|
|
12
|
+
this.ajv = new Ajv({
|
|
13
|
+
allErrors: true,
|
|
14
|
+
strict: true,
|
|
15
|
+
validateFormats: true,
|
|
16
|
+
allowUnionTypes: true,
|
|
17
|
+
schemaId: 'auto'
|
|
18
|
+
});
|
|
19
|
+
addFormats(this.ajv);
|
|
20
|
+
addErrors(this.ajv);
|
|
21
|
+
this.logger.info('Schema validator initialized', {
|
|
22
|
+
draft: '2020-12',
|
|
23
|
+
formats: 'enabled'
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
validateInput(schema, input) {
|
|
27
|
+
try {
|
|
28
|
+
const validate = this.getValidator(schema);
|
|
29
|
+
const valid = validate(input);
|
|
30
|
+
if (!valid && validate.errors) {
|
|
31
|
+
return {
|
|
32
|
+
valid: false,
|
|
33
|
+
errors: this.formatErrors(validate.errors)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
valid: true
|
|
38
|
+
};
|
|
39
|
+
} catch (error) {
|
|
40
|
+
this.logger.error('Schema validation error', {
|
|
41
|
+
error: error instanceof Error ? error.message : String(error)
|
|
42
|
+
});
|
|
43
|
+
return {
|
|
44
|
+
valid: false,
|
|
45
|
+
errors: [
|
|
46
|
+
{
|
|
47
|
+
path: '',
|
|
48
|
+
message: 'Schema validation failed'
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
validateOutput(schema, output) {
|
|
55
|
+
return this.validateInput(schema, output);
|
|
56
|
+
}
|
|
57
|
+
validateToolSchema(toolSchema) {
|
|
58
|
+
const requiredFields = [
|
|
59
|
+
'$schema',
|
|
60
|
+
'type',
|
|
61
|
+
'properties'
|
|
62
|
+
];
|
|
63
|
+
const schemaObj = toolSchema;
|
|
64
|
+
const missing = requiredFields.filter((field)=>!(field in schemaObj));
|
|
65
|
+
if (missing.length > 0) {
|
|
66
|
+
return {
|
|
67
|
+
valid: false,
|
|
68
|
+
errors: missing.map((field)=>({
|
|
69
|
+
path: '/',
|
|
70
|
+
message: `Missing required field: ${field}`
|
|
71
|
+
}))
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
this.ajv.compile(toolSchema);
|
|
76
|
+
return {
|
|
77
|
+
valid: true
|
|
78
|
+
};
|
|
79
|
+
} catch (error) {
|
|
80
|
+
return {
|
|
81
|
+
valid: false,
|
|
82
|
+
errors: [
|
|
83
|
+
{
|
|
84
|
+
path: '/',
|
|
85
|
+
message: error instanceof Error ? error.message : 'Invalid schema'
|
|
86
|
+
}
|
|
87
|
+
]
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
getValidator(schema) {
|
|
92
|
+
const schemaKey = JSON.stringify(schema);
|
|
93
|
+
const cached = this.schemaCache.get(schemaKey);
|
|
94
|
+
if (cached && Date.now() - cached.timestamp < this.cacheTTL) {
|
|
95
|
+
return cached.validate;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const validate = this.ajv.compile(schema);
|
|
99
|
+
if (this.schemaCache.size >= this.MAX_CACHE_SIZE) {
|
|
100
|
+
const oldest = Array.from(this.schemaCache.entries()).sort((a, b)=>a[1].timestamp - b[1].timestamp)[0];
|
|
101
|
+
if (oldest) {
|
|
102
|
+
this.schemaCache.delete(oldest[0]);
|
|
103
|
+
this.logger.debug('Evicted oldest schema from cache', {
|
|
104
|
+
cacheSize: this.schemaCache.size,
|
|
105
|
+
maxSize: this.MAX_CACHE_SIZE
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
this.schemaCache.set(schemaKey, {
|
|
110
|
+
schema,
|
|
111
|
+
validate,
|
|
112
|
+
timestamp: Date.now()
|
|
113
|
+
});
|
|
114
|
+
return validate;
|
|
115
|
+
} catch (error) {
|
|
116
|
+
this.logger.error('Failed to compile schema', {
|
|
117
|
+
error: error instanceof Error ? error.message : String(error)
|
|
118
|
+
});
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
formatErrors(errors) {
|
|
123
|
+
return errors.map((err)=>({
|
|
124
|
+
path: err.instancePath || '/',
|
|
125
|
+
message: this.getErrorMessage(err),
|
|
126
|
+
params: err.params
|
|
127
|
+
}));
|
|
128
|
+
}
|
|
129
|
+
getErrorMessage(error) {
|
|
130
|
+
const { keyword, message, params } = error;
|
|
131
|
+
switch(keyword){
|
|
132
|
+
case 'required':
|
|
133
|
+
return `Missing required property: ${params.missingProperty}`;
|
|
134
|
+
case 'type':
|
|
135
|
+
return `Expected ${params.type} but got ${typeof params.data}`;
|
|
136
|
+
case 'format':
|
|
137
|
+
return `Invalid format for ${params.format}`;
|
|
138
|
+
case 'minimum':
|
|
139
|
+
return `Value must be >= ${params.limit}`;
|
|
140
|
+
case 'maximum':
|
|
141
|
+
return `Value must be <= ${params.limit}`;
|
|
142
|
+
case 'minLength':
|
|
143
|
+
return `String must be at least ${params.limit} characters`;
|
|
144
|
+
case 'maxLength':
|
|
145
|
+
return `String must be at most ${params.limit} characters`;
|
|
146
|
+
case 'pattern':
|
|
147
|
+
return `String must match pattern: ${params.pattern}`;
|
|
148
|
+
case 'enum':
|
|
149
|
+
return `Value must be one of: ${params.allowedValues?.join(', ')}`;
|
|
150
|
+
default:
|
|
151
|
+
return message || `Validation failed: ${keyword}`;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
clearCache() {
|
|
155
|
+
this.schemaCache.clear();
|
|
156
|
+
this.logger.info('Schema cache cleared');
|
|
157
|
+
}
|
|
158
|
+
getCacheStats() {
|
|
159
|
+
return {
|
|
160
|
+
size: this.schemaCache.size,
|
|
161
|
+
entries: Array.from(this.schemaCache.values()).map((entry)=>({
|
|
162
|
+
age: Date.now() - entry.timestamp,
|
|
163
|
+
expired: Date.now() - entry.timestamp > this.cacheTTL
|
|
164
|
+
}))
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
cleanupCache() {
|
|
168
|
+
const now = Date.now();
|
|
169
|
+
let cleaned = 0;
|
|
170
|
+
for (const [key, entry] of this.schemaCache.entries()){
|
|
171
|
+
if (now - entry.timestamp > this.cacheTTL) {
|
|
172
|
+
this.schemaCache.delete(key);
|
|
173
|
+
cleaned++;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (cleaned > 0) {
|
|
177
|
+
this.logger.info('Cleaned up expired schema cache entries', {
|
|
178
|
+
count: cleaned
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
return cleaned;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
export function upgradeToolSchema(legacySchema) {
|
|
185
|
+
if (legacySchema.$schema && legacySchema.$schema.includes('2020-12')) {
|
|
186
|
+
return legacySchema;
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
190
|
+
type: legacySchema.type || 'object',
|
|
191
|
+
properties: legacySchema.properties || {},
|
|
192
|
+
required: legacySchema.required || [],
|
|
193
|
+
additionalProperties: legacySchema.additionalProperties !== undefined ? legacySchema.additionalProperties : false,
|
|
194
|
+
description: legacySchema.description
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
//# sourceMappingURL=schema-validator-2025.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/mcp/validation/schema-validator-2025.ts"],"sourcesContent":["/**\n * JSON Schema 1.1 Validator for MCP 2025-11\n *\n * Implements comprehensive schema validation per MCP 2025-11 specification\n * using JSON Schema Draft 2020-12\n */\n\nimport Ajv, { type ErrorObject } from 'ajv';\nimport addFormats from 'ajv-formats';\nimport addErrors from 'ajv-errors';\nimport type { ILogger } from '../../interfaces/logger.js';\n\n/**\n * Validation result\n */\nexport interface ValidationResult {\n valid: boolean;\n errors?: Array<{\n path: string;\n message: string;\n params?: any;\n }>;\n}\n\n/**\n * Schema cache entry\n */\ninterface CachedSchema {\n schema: object;\n validate: any;\n timestamp: number;\n}\n\n/**\n * MCP 2025-11 JSON Schema Validator\n *\n * Features:\n * - JSON Schema Draft 2020-12 support\n * - Format validation (uri, email, date-time, etc.)\n * - Schema caching for performance\n * - Custom error messages\n * - $ref support\n */\nexport class SchemaValidator {\n private ajv: Ajv;\n private schemaCache: Map<string, CachedSchema> = new Map();\n private cacheTTL = 3600000; // 1 hour\n private readonly MAX_CACHE_SIZE = 1000; // Maximum cached schemas\n\n constructor(private logger: ILogger) {\n this.ajv = new Ajv({\n allErrors: true,\n strict: true,\n validateFormats: true,\n allowUnionTypes: true,\n // Support JSON Schema Draft 2020-12\n schemaId: 'auto',\n });\n\n // Add format validators (email, uri, date-time, etc.)\n addFormats(this.ajv);\n\n // Add custom error messages support\n addErrors(this.ajv);\n\n this.logger.info('Schema validator initialized', {\n draft: '2020-12',\n formats: 'enabled',\n });\n }\n\n /**\n * Validate input against JSON Schema 1.1\n */\n validateInput(schema: object, input: unknown): ValidationResult {\n try {\n const validate = this.getValidator(schema);\n const valid = validate(input);\n\n if (!valid && validate.errors) {\n return {\n valid: false,\n errors: this.formatErrors(validate.errors),\n };\n }\n\n return { valid: true };\n } catch (error) {\n this.logger.error('Schema validation error', {\n error: error instanceof Error ? error.message : String(error),\n });\n\n return {\n valid: false,\n errors: [{\n path: '',\n message: 'Schema validation failed',\n }],\n };\n }\n }\n\n /**\n * Validate output against schema\n */\n validateOutput(schema: object, output: unknown): ValidationResult {\n return this.validateInput(schema, output);\n }\n\n /**\n * Validate tool schema itself\n */\n validateToolSchema(toolSchema: object): ValidationResult {\n // Ensure schema has required fields\n const requiredFields = ['$schema', 'type', 'properties'];\n const schemaObj = toolSchema as any;\n\n const missing = requiredFields.filter(field => !(field in schemaObj));\n if (missing.length > 0) {\n return {\n valid: false,\n errors: missing.map(field => ({\n path: '/',\n message: `Missing required field: ${field}`,\n })),\n };\n }\n\n // Validate schema is valid JSON Schema\n try {\n this.ajv.compile(toolSchema);\n return { valid: true };\n } catch (error) {\n return {\n valid: false,\n errors: [{\n path: '/',\n message: error instanceof Error ? error.message : 'Invalid schema',\n }],\n };\n }\n }\n\n /**\n * Get or create validator for schema\n */\n private getValidator(schema: object): any {\n const schemaKey = JSON.stringify(schema);\n const cached = this.schemaCache.get(schemaKey);\n\n // Return cached validator if still valid\n if (cached && Date.now() - cached.timestamp < this.cacheTTL) {\n return cached.validate;\n }\n\n // Compile new validator\n try {\n const validate = this.ajv.compile(schema);\n\n // Enforce cache size limit (LRU eviction - remove oldest entry)\n if (this.schemaCache.size >= this.MAX_CACHE_SIZE) {\n const oldest = Array.from(this.schemaCache.entries())\n .sort((a, b) => a[1].timestamp - b[1].timestamp)[0];\n\n if (oldest) {\n this.schemaCache.delete(oldest[0]);\n this.logger.debug('Evicted oldest schema from cache', {\n cacheSize: this.schemaCache.size,\n maxSize: this.MAX_CACHE_SIZE,\n });\n }\n }\n\n // Cache for future use\n this.schemaCache.set(schemaKey, {\n schema,\n validate,\n timestamp: Date.now(),\n });\n\n return validate;\n } catch (error) {\n this.logger.error('Failed to compile schema', {\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }\n }\n\n /**\n * Format ajv errors to user-friendly format\n */\n private formatErrors(errors: ErrorObject[]): ValidationResult['errors'] {\n return errors.map(err => ({\n path: err.instancePath || '/',\n message: this.getErrorMessage(err),\n params: err.params,\n }));\n }\n\n /**\n * Get user-friendly error message\n */\n private getErrorMessage(error: ErrorObject): string {\n const { keyword, message, params } = error;\n\n switch (keyword) {\n case 'required':\n return `Missing required property: ${params.missingProperty}`;\n case 'type':\n return `Expected ${params.type} but got ${typeof params.data}`;\n case 'format':\n return `Invalid format for ${params.format}`;\n case 'minimum':\n return `Value must be >= ${params.limit}`;\n case 'maximum':\n return `Value must be <= ${params.limit}`;\n case 'minLength':\n return `String must be at least ${params.limit} characters`;\n case 'maxLength':\n return `String must be at most ${params.limit} characters`;\n case 'pattern':\n return `String must match pattern: ${params.pattern}`;\n case 'enum':\n return `Value must be one of: ${params.allowedValues?.join(', ')}`;\n default:\n return message || `Validation failed: ${keyword}`;\n }\n }\n\n /**\n * Clear schema cache\n */\n clearCache(): void {\n this.schemaCache.clear();\n this.logger.info('Schema cache cleared');\n }\n\n /**\n * Get cache statistics\n */\n getCacheStats() {\n return {\n size: this.schemaCache.size,\n entries: Array.from(this.schemaCache.values()).map(entry => ({\n age: Date.now() - entry.timestamp,\n expired: Date.now() - entry.timestamp > this.cacheTTL,\n })),\n };\n }\n\n /**\n * Cleanup expired cache entries\n */\n cleanupCache(): number {\n const now = Date.now();\n let cleaned = 0;\n\n for (const [key, entry] of this.schemaCache.entries()) {\n if (now - entry.timestamp > this.cacheTTL) {\n this.schemaCache.delete(key);\n cleaned++;\n }\n }\n\n if (cleaned > 0) {\n this.logger.info('Cleaned up expired schema cache entries', { count: cleaned });\n }\n\n return cleaned;\n }\n}\n\n/**\n * Convert legacy tool schema to MCP 2025-11 format\n */\nexport function upgradeToolSchema(legacySchema: any): object {\n // If already in 2025-11 format, return as-is\n if (legacySchema.$schema && legacySchema.$schema.includes('2020-12')) {\n return legacySchema;\n }\n\n // Convert to 2025-11 format\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n type: legacySchema.type || 'object',\n properties: legacySchema.properties || {},\n required: legacySchema.required || [],\n additionalProperties: legacySchema.additionalProperties !== undefined\n ? legacySchema.additionalProperties\n : false,\n description: legacySchema.description,\n };\n}\n"],"names":["Ajv","addFormats","addErrors","SchemaValidator","ajv","schemaCache","Map","cacheTTL","MAX_CACHE_SIZE","logger","allErrors","strict","validateFormats","allowUnionTypes","schemaId","info","draft","formats","validateInput","schema","input","validate","getValidator","valid","errors","formatErrors","error","Error","message","String","path","validateOutput","output","validateToolSchema","toolSchema","requiredFields","schemaObj","missing","filter","field","length","map","compile","schemaKey","JSON","stringify","cached","get","Date","now","timestamp","size","oldest","Array","from","entries","sort","a","b","delete","debug","cacheSize","maxSize","set","err","instancePath","getErrorMessage","params","keyword","missingProperty","type","data","format","limit","pattern","allowedValues","join","clearCache","clear","getCacheStats","values","entry","age","expired","cleanupCache","cleaned","key","count","upgradeToolSchema","legacySchema","$schema","includes","properties","required","additionalProperties","undefined","description"],"mappings":"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"}
|