claude-flow-novice 2.14.34 → 2.14.36
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/commands/CFN_LOOP_TASK_MODE.md +1 -1
- package/.claude/commands/switch-api.md +1 -1
- package/.claude/skills/cfn-agent-discovery/agents-registry.json +1 -1
- package/.claude/skills/cfn-loop-orchestration/orchestrate.sh +2 -1
- package/.claude/skills/cfn-loop-validation/config.json +2 -2
- package/.claude/skills/cfn-redis-coordination/invoke-waiting-mode.sh +221 -0
- package/claude-assets/agents/README-AGENT_LIFECYCLE.md +37 -10
- package/claude-assets/agents/README-VALIDATION.md +0 -8
- package/claude-assets/agents/cfn-dev-team/README.md +0 -8
- package/claude-assets/agents/cfn-dev-team/coordinators/README.md +1 -9
- package/claude-assets/agents/cfn-dev-team/coordinators/cfn-v3-coordinator.md +565 -565
- package/claude-assets/agents/cfn-dev-team/developers/README.md +1 -9
- package/claude-assets/agents/cfn-dev-team/documentation/README-VALIDATION.md +0 -8
- package/claude-assets/agents/cfn-dev-team/documentation/agent-type-guidelines.md +0 -10
- package/claude-assets/agents/cfn-dev-team/reviewers/README.md +1 -9
- package/claude-assets/agents/cfn-dev-team/reviewers/quality/quality-metrics.md +0 -10
- package/claude-assets/agents/cfn-dev-team/test-agent.md +0 -10
- package/claude-assets/agents/cfn-dev-team/testers/README.md +1 -9
- package/claude-assets/agents/csuite/cto-agent.md +0 -10
- package/claude-assets/agents/custom/cfn-system-expert.md +1 -128
- package/claude-assets/agents/docker-coordinators/cfn-docker-v3-coordinator.md +1 -5
- package/claude-assets/agents/docker-team/csuite/c-suite-template.md +1 -5
- package/claude-assets/agents/docker-team/infrastructure/team-coordinator-template.md +1 -5
- package/claude-assets/agents/marketing_hybrid/cost_tracker.md +0 -10
- package/claude-assets/agents/marketing_hybrid/docker_deployer.md +0 -10
- package/claude-assets/agents/marketing_hybrid/zai_worker_spawner.md +0 -10
- package/claude-assets/commands/CFN_LOOP_TASK_MODE.md +1 -1
- package/claude-assets/commands/switch-api.md +1 -1
- package/claude-assets/skills/cfn-agent-discovery/agents-registry.json +1 -1
- package/claude-assets/skills/cfn-loop-orchestration/orchestrate.sh +2 -1
- package/claude-assets/skills/cfn-loop-validation/config.json +2 -2
- package/claude-assets/skills/cfn-process-instrumentation/instrument-process.sh +324 -322
- package/claude-assets/skills/cfn-redis-coordination/invoke-waiting-mode.sh +221 -0
- package/claude-assets/skills/cfn-task-config-init/initialize-config.sh +2 -2
- package/claude-assets/skills/cfn-task-mode-sanitize/task-mode-env-sanitizer.sh +213 -182
- package/claude-assets/skills/cfn-validation-runner-instrumentation/wrapped-executor.sh +233 -271
- package/dist/cli/agent-definition-parser.js.map +1 -1
- package/dist/cli/config-manager.js +109 -91
- package/package.json +1 -1
- package/scripts/docker-build-mcp.sh +155 -0
- package/scripts/docker-test-mcp.sh +260 -0
- package/scripts/mcp-health-check.sh +123 -0
|
@@ -1,100 +1,118 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
configPath;
|
|
8
|
-
schemaPath;
|
|
9
|
-
ajv;
|
|
10
|
-
constructor(){
|
|
11
|
-
this.configPath = path.join(process.env.HOME || "", ".claude-flow-config.json");
|
|
12
|
-
this.schemaPath = path.join(__dirname, "../../.claude/skills/config-management/config.json");
|
|
13
|
-
this.ajv = new Ajv();
|
|
14
|
-
}
|
|
15
|
-
static getInstance() {
|
|
16
|
-
if (!ConfigManager._instance) {
|
|
17
|
-
ConfigManager._instance = new ConfigManager();
|
|
18
|
-
}
|
|
19
|
-
return ConfigManager._instance;
|
|
20
|
-
}
|
|
21
|
-
async readConfig() {
|
|
22
|
-
try {
|
|
23
|
-
const configContent = await fs.readFile(this.configPath, "utf-8");
|
|
24
|
-
return JSON.parse(configContent);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
// If config doesn't exist, create from schema
|
|
27
|
-
return this.resetToDefaults();
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
async writeConfig(config) {
|
|
31
|
-
const schemaContent = await fs.readFile(this.schemaPath, "utf-8");
|
|
32
|
-
const schema = JSON.parse(schemaContent);
|
|
33
|
-
const validate = this.ajv.compile(schema);
|
|
34
|
-
if (!validate(config)) {
|
|
35
|
-
throw new Error("Invalid configuration: " + this.ajv.errorsText(validate.errors));
|
|
36
|
-
}
|
|
37
|
-
await fs.writeFile(this.configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = this && this.__awaiter || function(thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) {
|
|
4
|
+
return value instanceof P ? value : new P(function(resolve) {
|
|
5
|
+
resolve(value);
|
|
6
|
+
});
|
|
38
7
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
8
|
+
return new (P || (P = Promise))(function(resolve, reject) {
|
|
9
|
+
function fulfilled(value) {
|
|
10
|
+
try {
|
|
11
|
+
step(generator.next(value));
|
|
12
|
+
} catch (e) {
|
|
13
|
+
reject(e);
|
|
14
|
+
}
|
|
46
15
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return JSON.parse(customConfigContent);
|
|
54
|
-
} catch (error) {
|
|
55
|
-
// If custom config doesn't exist or can't be read, return empty object
|
|
56
|
-
return {};
|
|
16
|
+
function rejected(value) {
|
|
17
|
+
try {
|
|
18
|
+
step(generator["throw"](value));
|
|
19
|
+
} catch (e) {
|
|
20
|
+
reject(e);
|
|
21
|
+
}
|
|
57
22
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const config = await this.readConfig();
|
|
61
|
-
// Type assertion to handle full object
|
|
62
|
-
if (typeof value === "object" && value !== null) {
|
|
63
|
-
config[key] = value;
|
|
64
|
-
} else {
|
|
65
|
-
throw new Error("Invalid configuration value");
|
|
23
|
+
function step(result) {
|
|
24
|
+
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
|
|
66
25
|
}
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
26
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
var __generator = this && this.__generator || function(thisArg, body) {
|
|
30
|
+
var _ = {
|
|
31
|
+
label: 0,
|
|
32
|
+
sent: function() {
|
|
33
|
+
if (t[0] & 1) throw t[1];
|
|
34
|
+
return t[1];
|
|
35
|
+
},
|
|
36
|
+
trys: [],
|
|
37
|
+
ops: []
|
|
38
|
+
}, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
|
|
39
|
+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
|
|
40
|
+
return this;
|
|
41
|
+
}), g;
|
|
42
|
+
function verb(n) {
|
|
43
|
+
return function(v) {
|
|
44
|
+
return step([
|
|
45
|
+
n,
|
|
46
|
+
v
|
|
47
|
+
]);
|
|
90
48
|
};
|
|
91
|
-
await this.writeConfig(defaultConfig);
|
|
92
|
-
return defaultConfig;
|
|
93
49
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
50
|
+
function step(op) {
|
|
51
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
52
|
+
while(g && (g = 0, op[0] && (_ = 0)), _)try {
|
|
53
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
54
|
+
if (y = 0, t) op = [
|
|
55
|
+
op[0] & 2,
|
|
56
|
+
t.value
|
|
57
|
+
];
|
|
58
|
+
switch(op[0]){
|
|
59
|
+
case 0:
|
|
60
|
+
case 1:
|
|
61
|
+
t = op;
|
|
62
|
+
break;
|
|
63
|
+
case 4:
|
|
64
|
+
_.label++;
|
|
65
|
+
return {
|
|
66
|
+
value: op[1],
|
|
67
|
+
done: false
|
|
68
|
+
};
|
|
69
|
+
case 5:
|
|
70
|
+
_.label++;
|
|
71
|
+
y = op[1];
|
|
72
|
+
op = [
|
|
73
|
+
0
|
|
74
|
+
];
|
|
75
|
+
continue;
|
|
76
|
+
case 7:
|
|
77
|
+
op = _.ops.pop();
|
|
78
|
+
_.trys.pop();
|
|
79
|
+
continue;
|
|
80
|
+
default:
|
|
81
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
|
|
82
|
+
_ = 0;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
|
|
86
|
+
_.label = op[1];
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
if (op[0] === 6 && _.label < t[1]) {
|
|
90
|
+
_.label = t[1];
|
|
91
|
+
t = op;
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
if (t && _.label < t[2]) {
|
|
95
|
+
_.label = t[2];
|
|
96
|
+
_.ops.push(op);
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
if (t[2]) _.ops.pop();
|
|
100
|
+
_.trys.pop();
|
|
101
|
+
continue;
|
|
102
|
+
}
|
|
103
|
+
op = body.call(thisArg, _);
|
|
104
|
+
} catch (e) {
|
|
105
|
+
op = [
|
|
106
|
+
6,
|
|
107
|
+
e
|
|
108
|
+
];
|
|
109
|
+
y = 0;
|
|
110
|
+
} finally{
|
|
111
|
+
f = t = 0;
|
|
112
|
+
}
|
|
113
|
+
if (op[0] & 5) throw op[1];
|
|
114
|
+
return {
|
|
115
|
+
value: op[0] ? op[1] : void 0,
|
|
98
116
|
done: true
|
|
99
117
|
};
|
|
100
118
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow-novice",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.36",
|
|
4
4
|
"description": "AI agent orchestration framework with namespace-isolated skills, agents, and CFN Loop validation. Safe installation with ~0.01% collision risk.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Docker MCP Build Script
|
|
5
|
+
# Builds all MCP server images and enhanced agent image with MCP clients
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
+
|
|
10
|
+
# Colors for output
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
YELLOW='\033[1;33m'
|
|
14
|
+
NC='\033[0m' # No Color
|
|
15
|
+
|
|
16
|
+
echo "========================================="
|
|
17
|
+
echo " Docker MCP Build Script"
|
|
18
|
+
echo "========================================="
|
|
19
|
+
echo ""
|
|
20
|
+
|
|
21
|
+
# Function to print colored output
|
|
22
|
+
print_status() {
|
|
23
|
+
local status=$1
|
|
24
|
+
local message=$2
|
|
25
|
+
case $status in
|
|
26
|
+
"success")
|
|
27
|
+
echo -e "${GREEN}✓${NC} $message"
|
|
28
|
+
;;
|
|
29
|
+
"error")
|
|
30
|
+
echo -e "${RED}✗${NC} $message"
|
|
31
|
+
;;
|
|
32
|
+
"info")
|
|
33
|
+
echo -e "${YELLOW}→${NC} $message"
|
|
34
|
+
;;
|
|
35
|
+
esac
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
# Check if Docker is available
|
|
39
|
+
if ! command -v docker &> /dev/null; then
|
|
40
|
+
print_status "error" "Docker is not installed or not in PATH"
|
|
41
|
+
exit 1
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# Check if docker-compose is available
|
|
45
|
+
if ! command -v docker-compose &> /dev/null; then
|
|
46
|
+
print_status "error" "docker-compose is not installed or not in PATH"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# Navigate to project root
|
|
51
|
+
cd "$PROJECT_ROOT"
|
|
52
|
+
|
|
53
|
+
# Validate MCP configuration exists
|
|
54
|
+
if [ ! -f "config/mcp-servers.json" ]; then
|
|
55
|
+
print_status "error" "MCP configuration not found: config/mcp-servers.json"
|
|
56
|
+
exit 1
|
|
57
|
+
fi
|
|
58
|
+
|
|
59
|
+
print_status "success" "Found MCP configuration"
|
|
60
|
+
|
|
61
|
+
# Build enhanced production Dockerfile with MCP clients
|
|
62
|
+
print_status "info" "Building enhanced agent image with MCP clients..."
|
|
63
|
+
if docker build -f Dockerfile.production \
|
|
64
|
+
--target production \
|
|
65
|
+
--tag cfn-agent-mcp:latest \
|
|
66
|
+
--tag cfn-agent-mcp:$(date +%Y%m%d) \
|
|
67
|
+
--build-arg BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
68
|
+
--build-arg VCS_REF="$(git rev-parse --short HEAD 2>/dev/null || echo 'unknown')" \
|
|
69
|
+
--build-arg VERSION="4.1.0-mcp" \
|
|
70
|
+
. 2>&1 | tee /tmp/docker-build-agent.log; then
|
|
71
|
+
print_status "success" "Agent image built successfully"
|
|
72
|
+
else
|
|
73
|
+
print_status "error" "Failed to build agent image"
|
|
74
|
+
exit 1
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# Build MCP server images from docker-compose
|
|
78
|
+
print_status "info" "Building MCP server containers..."
|
|
79
|
+
if docker-compose -f docker-compose.production.yml build \
|
|
80
|
+
mcp-playwright \
|
|
81
|
+
mcp-redis-tools \
|
|
82
|
+
mcp-n8n \
|
|
83
|
+
mcp-security-scanner 2>&1 | tee /tmp/docker-build-mcp.log; then
|
|
84
|
+
print_status "success" "MCP server images built successfully"
|
|
85
|
+
else
|
|
86
|
+
print_status "error" "Failed to build MCP server images"
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
|
|
90
|
+
# Pull base images that we reference directly
|
|
91
|
+
print_status "info" "Pulling base MCP images..."
|
|
92
|
+
docker pull mcr.microsoft.com/playwright:v1.40.0-jammy
|
|
93
|
+
docker pull redis:7-alpine
|
|
94
|
+
docker pull n8nio/n8n:latest
|
|
95
|
+
docker pull aquasec/trivy:latest
|
|
96
|
+
print_status "success" "Base images pulled"
|
|
97
|
+
|
|
98
|
+
# Run security scans if Trivy is available
|
|
99
|
+
if command -v trivy &> /dev/null; then
|
|
100
|
+
print_status "info" "Running security scans with Trivy..."
|
|
101
|
+
|
|
102
|
+
# Scan agent image
|
|
103
|
+
print_status "info" "Scanning cfn-agent-mcp:latest..."
|
|
104
|
+
if trivy image --severity HIGH,CRITICAL \
|
|
105
|
+
--exit-code 0 \
|
|
106
|
+
--no-progress \
|
|
107
|
+
cfn-agent-mcp:latest > /tmp/trivy-scan-agent.txt 2>&1; then
|
|
108
|
+
print_status "success" "Agent image scan complete"
|
|
109
|
+
else
|
|
110
|
+
print_status "error" "Agent image has vulnerabilities (see /tmp/trivy-scan-agent.txt)"
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Scan MCP server images
|
|
114
|
+
for image in mcr.microsoft.com/playwright:v1.40.0-jammy \
|
|
115
|
+
redis:7-alpine \
|
|
116
|
+
n8nio/n8n:latest \
|
|
117
|
+
aquasec/trivy:latest; do
|
|
118
|
+
print_status "info" "Scanning $image..."
|
|
119
|
+
trivy image --severity HIGH,CRITICAL \
|
|
120
|
+
--exit-code 0 \
|
|
121
|
+
--no-progress \
|
|
122
|
+
"$image" > /tmp/trivy-scan-$(echo $image | sed 's/[^a-zA-Z0-9]/-/g').txt 2>&1 || true
|
|
123
|
+
done
|
|
124
|
+
|
|
125
|
+
print_status "success" "Security scans complete (results in /tmp/trivy-scan-*.txt)"
|
|
126
|
+
else
|
|
127
|
+
print_status "info" "Trivy not found - skipping security scans"
|
|
128
|
+
fi
|
|
129
|
+
|
|
130
|
+
# Summary
|
|
131
|
+
echo ""
|
|
132
|
+
echo "========================================="
|
|
133
|
+
echo " Build Summary"
|
|
134
|
+
echo "========================================="
|
|
135
|
+
echo ""
|
|
136
|
+
|
|
137
|
+
docker images | grep -E "(cfn-agent-mcp|mcp-playwright|mcp-redis-tools|mcp-n8n|mcp-security|playwright|n8n|trivy)" | head -20
|
|
138
|
+
|
|
139
|
+
echo ""
|
|
140
|
+
print_status "success" "Build complete!"
|
|
141
|
+
echo ""
|
|
142
|
+
echo "Tagged images:"
|
|
143
|
+
echo " - cfn-agent-mcp:latest"
|
|
144
|
+
echo " - cfn-agent-mcp:$(date +%Y%m%d)"
|
|
145
|
+
echo ""
|
|
146
|
+
echo "MCP Server images ready:"
|
|
147
|
+
echo " - mcp-playwright (mcr.microsoft.com/playwright:v1.40.0-jammy)"
|
|
148
|
+
echo " - mcp-redis-tools (redis:7-alpine)"
|
|
149
|
+
echo " - mcp-n8n (n8nio/n8n:latest)"
|
|
150
|
+
echo " - mcp-security-scanner (aquasec/trivy:latest)"
|
|
151
|
+
echo ""
|
|
152
|
+
echo "Next steps:"
|
|
153
|
+
echo " 1. Run tests: ./scripts/docker-test-mcp.sh"
|
|
154
|
+
echo " 2. Deploy: docker-compose -f docker-compose.production.yml up -d"
|
|
155
|
+
echo ""
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# Docker MCP Test Script
|
|
5
|
+
# Tests MCP server containers and agent connectivity
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
9
|
+
|
|
10
|
+
# Colors for output
|
|
11
|
+
RED='\033[0;31m'
|
|
12
|
+
GREEN='\033[0;32m'
|
|
13
|
+
YELLOW='\033[1;33m'
|
|
14
|
+
BLUE='\033[0;34m'
|
|
15
|
+
NC='\033[0m' # No Color
|
|
16
|
+
|
|
17
|
+
# Test results tracking
|
|
18
|
+
TESTS_PASSED=0
|
|
19
|
+
TESTS_FAILED=0
|
|
20
|
+
TEST_RESULTS=()
|
|
21
|
+
|
|
22
|
+
echo "========================================="
|
|
23
|
+
echo " Docker MCP Test Suite"
|
|
24
|
+
echo "========================================="
|
|
25
|
+
echo ""
|
|
26
|
+
|
|
27
|
+
# Function to print colored output
|
|
28
|
+
print_status() {
|
|
29
|
+
local status=$1
|
|
30
|
+
local message=$2
|
|
31
|
+
case $status in
|
|
32
|
+
"success")
|
|
33
|
+
echo -e "${GREEN}✓${NC} $message"
|
|
34
|
+
;;
|
|
35
|
+
"error")
|
|
36
|
+
echo -e "${RED}✗${NC} $message"
|
|
37
|
+
;;
|
|
38
|
+
"info")
|
|
39
|
+
echo -e "${BLUE}→${NC} $message"
|
|
40
|
+
;;
|
|
41
|
+
"warning")
|
|
42
|
+
echo -e "${YELLOW}⚠${NC} $message"
|
|
43
|
+
;;
|
|
44
|
+
esac
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# Function to record test result
|
|
48
|
+
record_test() {
|
|
49
|
+
local test_name=$1
|
|
50
|
+
local passed=$2
|
|
51
|
+
local message=$3
|
|
52
|
+
|
|
53
|
+
if [ "$passed" = "true" ]; then
|
|
54
|
+
((TESTS_PASSED++))
|
|
55
|
+
TEST_RESULTS+=("PASS: $test_name - $message")
|
|
56
|
+
print_status "success" "$test_name"
|
|
57
|
+
else
|
|
58
|
+
((TESTS_FAILED++))
|
|
59
|
+
TEST_RESULTS+=("FAIL: $test_name - $message")
|
|
60
|
+
print_status "error" "$test_name - $message"
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Cleanup function
|
|
65
|
+
cleanup() {
|
|
66
|
+
print_status "info" "Cleaning up test containers..."
|
|
67
|
+
docker-compose -f "$PROJECT_ROOT/docker-compose.production.yml" down \
|
|
68
|
+
mcp-playwright mcp-redis-tools mcp-n8n mcp-security-scanner 2>/dev/null || true
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# Trap cleanup on exit
|
|
72
|
+
trap cleanup EXIT
|
|
73
|
+
|
|
74
|
+
# Navigate to project root
|
|
75
|
+
cd "$PROJECT_ROOT"
|
|
76
|
+
|
|
77
|
+
# Test 1: MCP Configuration Validation
|
|
78
|
+
print_status "info" "Test 1: Validating MCP configuration..."
|
|
79
|
+
if [ -f "config/mcp-servers.json" ]; then
|
|
80
|
+
if command -v jq &> /dev/null; then
|
|
81
|
+
if jq empty config/mcp-servers.json 2>/dev/null; then
|
|
82
|
+
record_test "MCP Config Validation" "true" "Valid JSON configuration"
|
|
83
|
+
else
|
|
84
|
+
record_test "MCP Config Validation" "false" "Invalid JSON"
|
|
85
|
+
fi
|
|
86
|
+
else
|
|
87
|
+
record_test "MCP Config Validation" "true" "File exists (jq not available for validation)"
|
|
88
|
+
fi
|
|
89
|
+
else
|
|
90
|
+
record_test "MCP Config Validation" "false" "config/mcp-servers.json not found"
|
|
91
|
+
fi
|
|
92
|
+
|
|
93
|
+
# Test 2: Docker Compose Syntax Validation
|
|
94
|
+
print_status "info" "Test 2: Validating Docker Compose syntax..."
|
|
95
|
+
if docker-compose -f docker-compose.production.yml config > /dev/null 2>&1; then
|
|
96
|
+
record_test "Docker Compose Syntax" "true" "Valid syntax"
|
|
97
|
+
else
|
|
98
|
+
record_test "Docker Compose Syntax" "false" "Syntax errors detected"
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Test 3: Start MCP containers
|
|
102
|
+
print_status "info" "Test 3: Starting MCP containers..."
|
|
103
|
+
if docker-compose -f docker-compose.production.yml up -d \
|
|
104
|
+
redis-coordinator \
|
|
105
|
+
mcp-playwright \
|
|
106
|
+
mcp-redis-tools \
|
|
107
|
+
mcp-n8n \
|
|
108
|
+
mcp-security-scanner 2>&1 | tee /tmp/docker-test-mcp-start.log; then
|
|
109
|
+
record_test "MCP Container Startup" "true" "All containers started"
|
|
110
|
+
else
|
|
111
|
+
record_test "MCP Container Startup" "false" "Failed to start containers"
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Wait for containers to initialize
|
|
116
|
+
print_status "info" "Waiting for containers to initialize (30s)..."
|
|
117
|
+
sleep 30
|
|
118
|
+
|
|
119
|
+
# Test 4: Health Check - Playwright
|
|
120
|
+
print_status "info" "Test 4: Testing Playwright MCP server health..."
|
|
121
|
+
if timeout 10 docker exec cfn-mcp-playwright curl -f http://localhost:8081/health 2>/dev/null; then
|
|
122
|
+
record_test "Playwright Health Check" "true" "Responding"
|
|
123
|
+
else
|
|
124
|
+
record_test "Playwright Health Check" "false" "Not responding or health endpoint unavailable"
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# Test 5: Health Check - Redis Tools
|
|
128
|
+
print_status "info" "Test 5: Testing Redis Tools MCP server health..."
|
|
129
|
+
if timeout 10 docker exec cfn-mcp-redis-tools wget --quiet --tries=1 --spider http://localhost:8082/health 2>/dev/null; then
|
|
130
|
+
record_test "Redis Tools Health Check" "true" "Responding"
|
|
131
|
+
else
|
|
132
|
+
record_test "Redis Tools Health Check" "false" "Not responding or health endpoint unavailable"
|
|
133
|
+
fi
|
|
134
|
+
|
|
135
|
+
# Test 6: Health Check - N8N
|
|
136
|
+
print_status "info" "Test 6: Testing N8N MCP server health..."
|
|
137
|
+
if timeout 15 docker exec cfn-mcp-n8n wget --quiet --tries=1 --spider http://localhost:5678/healthz 2>/dev/null; then
|
|
138
|
+
record_test "N8N Health Check" "true" "Responding"
|
|
139
|
+
else
|
|
140
|
+
record_test "N8N Health Check" "false" "Not responding or health endpoint unavailable"
|
|
141
|
+
fi
|
|
142
|
+
|
|
143
|
+
# Test 7: Health Check - Security Scanner
|
|
144
|
+
print_status "info" "Test 7: Testing Security Scanner MCP server health..."
|
|
145
|
+
if timeout 10 docker exec cfn-mcp-security-scanner wget --quiet --tries=1 --spider http://localhost:8084/health 2>/dev/null; then
|
|
146
|
+
record_test "Security Scanner Health Check" "true" "Responding"
|
|
147
|
+
else
|
|
148
|
+
record_test "Security Scanner Health Check" "false" "Not responding or health endpoint unavailable"
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Test 8: Network Connectivity - MCP Network
|
|
152
|
+
print_status "info" "Test 8: Testing MCP network isolation..."
|
|
153
|
+
if docker network inspect mcp-isolated > /dev/null 2>&1; then
|
|
154
|
+
record_test "MCP Network Creation" "true" "Network exists"
|
|
155
|
+
else
|
|
156
|
+
record_test "MCP Network Creation" "false" "Network not found"
|
|
157
|
+
fi
|
|
158
|
+
|
|
159
|
+
# Test 9: Volume Mounts
|
|
160
|
+
print_status "info" "Test 9: Testing MCP configuration volume mounts..."
|
|
161
|
+
MOUNT_ERRORS=0
|
|
162
|
+
for container in cfn-mcp-playwright cfn-mcp-redis-tools cfn-mcp-n8n cfn-mcp-security-scanner; do
|
|
163
|
+
if docker exec "$container" test -f /app/config/mcp-servers.json 2>/dev/null; then
|
|
164
|
+
: # Success
|
|
165
|
+
else
|
|
166
|
+
((MOUNT_ERRORS++))
|
|
167
|
+
fi
|
|
168
|
+
done
|
|
169
|
+
|
|
170
|
+
if [ $MOUNT_ERRORS -eq 0 ]; then
|
|
171
|
+
record_test "MCP Config Volume Mounts" "true" "All containers have config mounted"
|
|
172
|
+
else
|
|
173
|
+
record_test "MCP Config Volume Mounts" "false" "$MOUNT_ERRORS containers missing config"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
# Test 10: Redis Coordinator Connectivity
|
|
177
|
+
print_status "info" "Test 10: Testing Redis coordinator connectivity..."
|
|
178
|
+
if docker exec cfn-redis-coordinator redis-cli ping 2>/dev/null | grep -q "PONG"; then
|
|
179
|
+
record_test "Redis Coordinator" "true" "Responding to pings"
|
|
180
|
+
else
|
|
181
|
+
record_test "Redis Coordinator" "false" "Not responding"
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# Test 11: Container Resource Limits
|
|
185
|
+
print_status "info" "Test 11: Verifying container resource limits..."
|
|
186
|
+
LIMIT_ERRORS=0
|
|
187
|
+
for container in cfn-mcp-playwright cfn-mcp-redis-tools cfn-mcp-n8n cfn-mcp-security-scanner; do
|
|
188
|
+
if docker inspect "$container" --format '{{.HostConfig.Memory}}' 2>/dev/null | grep -q -v "^0$"; then
|
|
189
|
+
: # Memory limit set
|
|
190
|
+
else
|
|
191
|
+
((LIMIT_ERRORS++))
|
|
192
|
+
fi
|
|
193
|
+
done
|
|
194
|
+
|
|
195
|
+
if [ $LIMIT_ERRORS -eq 0 ]; then
|
|
196
|
+
record_test "Container Resource Limits" "true" "All containers have memory limits"
|
|
197
|
+
else
|
|
198
|
+
record_test "Container Resource Limits" "false" "$LIMIT_ERRORS containers missing resource limits"
|
|
199
|
+
fi
|
|
200
|
+
|
|
201
|
+
# Test 12: MCP Server Environment Variables
|
|
202
|
+
print_status "info" "Test 12: Verifying MCP server environment variables..."
|
|
203
|
+
ENV_ERRORS=0
|
|
204
|
+
for container in cfn-mcp-playwright cfn-mcp-redis-tools cfn-mcp-n8n cfn-mcp-security-scanner; do
|
|
205
|
+
if docker exec "$container" env 2>/dev/null | grep -q "MCP_SERVER_TYPE"; then
|
|
206
|
+
: # Environment variable set
|
|
207
|
+
else
|
|
208
|
+
((ENV_ERRORS++))
|
|
209
|
+
fi
|
|
210
|
+
done
|
|
211
|
+
|
|
212
|
+
if [ $ENV_ERRORS -eq 0 ]; then
|
|
213
|
+
record_test "MCP Environment Variables" "true" "All containers have MCP env vars"
|
|
214
|
+
else
|
|
215
|
+
record_test "MCP Environment Variables" "false" "$ENV_ERRORS containers missing MCP env vars"
|
|
216
|
+
fi
|
|
217
|
+
|
|
218
|
+
# Print container status
|
|
219
|
+
echo ""
|
|
220
|
+
print_status "info" "Container Status:"
|
|
221
|
+
docker-compose -f docker-compose.production.yml ps \
|
|
222
|
+
redis-coordinator mcp-playwright mcp-redis-tools mcp-n8n mcp-security-scanner
|
|
223
|
+
|
|
224
|
+
# Print container logs for debugging
|
|
225
|
+
echo ""
|
|
226
|
+
print_status "info" "Recent container logs:"
|
|
227
|
+
for container in cfn-mcp-playwright cfn-mcp-redis-tools cfn-mcp-n8n cfn-mcp-security-scanner; do
|
|
228
|
+
echo ""
|
|
229
|
+
echo "--- $container ---"
|
|
230
|
+
docker logs "$container" --tail 10 2>&1 || true
|
|
231
|
+
done
|
|
232
|
+
|
|
233
|
+
# Summary
|
|
234
|
+
echo ""
|
|
235
|
+
echo "========================================="
|
|
236
|
+
echo " Test Results Summary"
|
|
237
|
+
echo "========================================="
|
|
238
|
+
echo ""
|
|
239
|
+
|
|
240
|
+
for result in "${TEST_RESULTS[@]}"; do
|
|
241
|
+
if [[ $result == PASS:* ]]; then
|
|
242
|
+
echo -e "${GREEN}$result${NC}"
|
|
243
|
+
else
|
|
244
|
+
echo -e "${RED}$result${NC}"
|
|
245
|
+
fi
|
|
246
|
+
done
|
|
247
|
+
|
|
248
|
+
echo ""
|
|
249
|
+
echo "Tests Passed: $TESTS_PASSED"
|
|
250
|
+
echo "Tests Failed: $TESTS_FAILED"
|
|
251
|
+
echo "Total Tests: $((TESTS_PASSED + TESTS_FAILED))"
|
|
252
|
+
echo ""
|
|
253
|
+
|
|
254
|
+
if [ $TESTS_FAILED -eq 0 ]; then
|
|
255
|
+
print_status "success" "All tests passed!"
|
|
256
|
+
exit 0
|
|
257
|
+
else
|
|
258
|
+
print_status "error" "$TESTS_FAILED test(s) failed"
|
|
259
|
+
exit 1
|
|
260
|
+
fi
|