#!/bin/bash
# Health Check Script for MCP ComfyUI Flux - Optimized Production Setup
# Validates all components are running correctly
set -euo pipefail
IFS=$'\n\t'
# Configuration
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly PROJECT_ROOT="$(dirname "${SCRIPT_DIR}")"
readonly PROJECT_NAME="${PROJECT_NAME:-mcp-comfyui-flux}"
readonly COMFYUI_PORT="${COMFYUI_PORT:-8188}"
# Colors
readonly GREEN='\033[0;32m'
readonly RED='\033[0;31m'
readonly YELLOW='\033[1;33m'
readonly BLUE='\033[0;34m'
readonly NC='\033[0m'
# Health check results
declare -i CHECKS_PASSED=0
declare -i CHECKS_FAILED=0
declare -a ISSUES=()
# Print header
print_header() {
echo ""
echo "══════════════════════════════════════════════════════════"
echo " MCP ComfyUI Flux Health Check (Optimized Setup)"
echo "══════════════════════════════════════════════════════════"
echo ""
}
# Check function
check() {
local name="$1"
local command="$2"
echo -n "Checking ${name}... "
if eval "${command}" &> /dev/null; then
echo -e "${GREEN}✓${NC}"
((CHECKS_PASSED++))
return 0
else
echo -e "${RED}✗${NC}"
((CHECKS_FAILED++))
ISSUES+=("${name}")
return 1
fi
}
# Check with output
check_with_output() {
local name="$1"
local command="$2"
echo "Checking ${name}..."
if output=$(eval "${command}" 2>&1); then
echo -e "${GREEN}✓${NC} ${output}"
((CHECKS_PASSED++))
return 0
else
echo -e "${RED}✗${NC} Failed"
((CHECKS_FAILED++))
ISSUES+=("${name}")
return 1
fi
}
# Docker checks
check_docker() {
echo ""
echo "Docker Environment:"
echo "-------------------"
check "Docker installed" "command -v docker"
check "Docker daemon running" "docker info"
# Check for docker compose (plugin or standalone)
if docker compose version &> /dev/null; then
echo -e "${GREEN}✓${NC} Docker Compose plugin installed"
((CHECKS_PASSED++))
local compose_version=$(docker compose version --short 2>/dev/null || echo "unknown")
echo " Docker Compose version: ${compose_version}"
elif command -v docker-compose &> /dev/null; then
echo -e "${GREEN}✓${NC} Docker Compose standalone installed"
((CHECKS_PASSED++))
local compose_version=$(docker-compose --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
echo " Docker Compose version: ${compose_version}"
else
echo -e "${RED}✗${NC} Docker Compose not installed"
((CHECKS_FAILED++))
ISSUES+=("Docker Compose")
fi
if docker info &> /dev/null; then
local version
version=$(docker --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -1)
echo " Docker version: ${version}"
# Check BuildKit
if docker buildx version &> /dev/null; then
echo -e "${GREEN}✓${NC} Docker BuildKit available"
((CHECKS_PASSED++))
else
echo -e "${YELLOW}ℹ${NC} Docker BuildKit not available (builds will be slower)"
fi
fi
}
# Container checks
check_containers() {
echo ""
echo "Container Status (Project: ${PROJECT_NAME}):"
echo "--------------------------------------------"
local comfyui_container="${PROJECT_NAME}-comfyui-1"
local mcp_container="${PROJECT_NAME}-mcp-server-1"
check "ComfyUI container running" "docker ps --format '{{.Names}}' | grep -q '^${comfyui_container}$'"
check "MCP server container running" "docker ps --format '{{.Names}}' | grep -q '^${mcp_container}$'"
if docker ps --format '{{.Names}}' | grep -q "^${comfyui_container}$"; then
local health
health=$(docker inspect "${comfyui_container}" --format='{{.State.Health.Status}}' 2>/dev/null || echo "none")
echo " ComfyUI health: ${health}"
# Check PyTorch version
local pytorch_version=$(docker exec "${comfyui_container}" python3.11 -c "import torch; print(torch.__version__)" 2>/dev/null || echo "unknown")
if [[ "${pytorch_version}" == "2.5.1+cu121" ]]; then
echo -e "${GREEN}✓${NC} PyTorch version: ${pytorch_version} (optimized)"
((CHECKS_PASSED++))
else
echo " PyTorch version: ${pytorch_version}"
fi
# Check custom nodes
echo " Checking custom nodes..."
local kjnodes=$(docker exec "${comfyui_container}" ls /app/ComfyUI/custom_nodes/ 2>/dev/null | grep -c "ComfyUI-KJNodes" || echo 0)
local rmbg=$(docker exec "${comfyui_container}" ls /app/ComfyUI/custom_nodes/ 2>/dev/null | grep -c "ComfyUI-RMBG" || echo 0)
local manager=$(docker exec "${comfyui_container}" ls /app/ComfyUI/custom_nodes/ 2>/dev/null | grep -c "ComfyUI-Manager" || echo 0)
if [[ $kjnodes -gt 0 && $rmbg -gt 0 && $manager -gt 0 ]]; then
echo -e " ${GREEN}✓${NC} Custom nodes: KJNodes, RMBG, Manager"
((CHECKS_PASSED++))
else
echo -e " ${YELLOW}⚠${NC} Some custom nodes missing"
ISSUES+=("Custom nodes")
fi
fi
# Check image sizes
echo ""
echo " Docker Images:"
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" | grep -E "(REPOSITORY|${PROJECT_NAME})" || true
}
# Network checks
check_network() {
echo ""
echo "Network Connectivity:"
echo "---------------------"
check "ComfyUI web interface" "curl -s -f http://localhost:${COMFYUI_PORT}/system_stats"
check "ComfyUI WebSocket" "curl -s -f -H 'Upgrade: websocket' -H 'Connection: Upgrade' http://localhost:${COMFYUI_PORT}/ws 2>&1 | grep -q '426\\|101'"
# Check if ComfyUI API is responding
if curl -s http://localhost:${COMFYUI_PORT}/system_stats &> /dev/null; then
local stats
stats=$(curl -s http://localhost:${COMFYUI_PORT}/system_stats | python3 -c "import sys, json; data=json.load(sys.stdin); print(f'CPU: {data.get(\"system\",{}).get(\"cpu_utilization\",\"N/A\")}%')" 2>/dev/null || echo "Unable to parse")
echo " System stats: ${stats}"
fi
}
# GPU checks
check_gpu() {
echo ""
echo "GPU Configuration:"
echo "------------------"
if command -v nvidia-smi &> /dev/null; then
if nvidia-smi &> /dev/null; then
echo -e "${GREEN}✓${NC} NVIDIA GPU detected"
((CHECKS_PASSED++))
# Get GPU info
local gpu_info
gpu_info=$(nvidia-smi --query-gpu=name,memory.total,memory.used --format=csv,noheader 2>/dev/null | head -1)
echo " GPU: ${gpu_info}"
# Check Docker GPU support (check for nvidia runtime)
if docker info 2>/dev/null | grep -q nvidia; then
echo -e "${GREEN}✓${NC} Docker NVIDIA runtime available"
((CHECKS_PASSED++))
# Test GPU in container
local comfyui_container="${PROJECT_NAME}-comfyui-1"
if docker exec "${comfyui_container}" nvidia-smi &> /dev/null; then
echo -e "${GREEN}✓${NC} GPU accessible in ComfyUI container"
((CHECKS_PASSED++))
else
echo -e "${YELLOW}⚠${NC} GPU not accessible in container"
ISSUES+=("Container GPU access")
fi
else
echo -e "${YELLOW}⚠${NC} Docker NVIDIA runtime not configured"
ISSUES+=("Docker GPU support")
fi
else
echo -e "${YELLOW}⚠${NC} NVIDIA driver installed but GPU not accessible"
fi
else
echo -e "${YELLOW}ℹ${NC} No NVIDIA GPU detected (CPU mode)"
fi
}
# Model checks
check_models() {
echo ""
echo "Model Files:"
echo "------------"
local models_dir="${PROJECT_ROOT}/models"
# Check for Flux models (including fp8 variants)
local has_model=false
if [[ -f "${models_dir}/unet/flux1-dev.safetensors" ]] || [[ -f "${models_dir}/unet/flux1-dev-fp8.safetensors" ]] || [[ -f "${models_dir}/unet/flux1-dev-fp8-e4m3fn.safetensors" ]]; then
echo -e "${GREEN}✓${NC} Flux.1-dev model found"
((CHECKS_PASSED++))
has_model=true
fi
if [[ -f "${models_dir}/unet/flux1-schnell.safetensors" ]] || [[ -f "${models_dir}/unet/flux1-schnell-fp8-e4m3fn.safetensors" ]] || [[ -f "${models_dir}/unet/flux1-schnell-fp8.safetensors" ]]; then
echo -e "${GREEN}✓${NC} Flux.1-schnell model found"
((CHECKS_PASSED++))
has_model=true
fi
if [[ "${has_model}" == "false" ]]; then
echo -e "${RED}✗${NC} No Flux model found"
((CHECKS_FAILED++))
ISSUES+=("Flux model")
fi
# Check encoders (including fp8 variants)
if ls "${models_dir}/clip/"t5xxl*.safetensors 2>/dev/null | grep -q . || [[ -f "${models_dir}/clip/t5xxl_fp8_e4m3fn_scaled.safetensors" ]]; then
echo -e "${GREEN}✓${NC} T5-XXL encoder found"
((CHECKS_PASSED++))
else
echo -e "${YELLOW}⚠${NC} T5-XXL encoder not found"
fi
check "CLIP-L encoder" "test -f ${models_dir}/clip/clip_l.safetensors"
check "VAE" "test -f ${models_dir}/vae/ae.safetensors"
# Check disk space
if [[ -d "${models_dir}" ]]; then
local used
used=$(du -sh "${models_dir}" 2>/dev/null | cut -f1)
echo " Models directory size: ${used}"
fi
}
# Environment checks
check_environment() {
echo ""
echo "Environment Configuration:"
echo "--------------------------"
check ".env file exists" "test -f ${PROJECT_ROOT}/.env"
check "docker-compose.yml exists" "test -f ${PROJECT_ROOT}/docker-compose.yml"
check "Dockerfile.comfyui exists" "test -f ${PROJECT_ROOT}/Dockerfile.comfyui"
check "requirements.txt exists" "test -f ${PROJECT_ROOT}/requirements.txt"
if [[ -f "${PROJECT_ROOT}/.env" ]]; then
# Check for HF_TOKEN (without revealing it)
if grep -q "^HF_TOKEN=." "${PROJECT_ROOT}/.env"; then
echo -e "${GREEN}✓${NC} Hugging Face token configured"
((CHECKS_PASSED++))
else
echo -e "${YELLOW}ℹ${NC} Hugging Face token not configured (optional for schnell)"
fi
# Check CUDA settings
local cuda_devices
cuda_devices=$(grep "^CUDA_VISIBLE_DEVICES=" "${PROJECT_ROOT}/.env" | cut -d'=' -f2)
if [[ -n "${cuda_devices}" ]]; then
echo " CUDA_VISIBLE_DEVICES: ${cuda_devices}"
fi
fi
}
# MCP server checks
check_mcp() {
echo ""
echo "MCP Server:"
echo "-----------"
local mcp_container="${PROJECT_NAME}-mcp-server-1"
check "MCP server container exists" "docker ps -a --format '{{.Names}}' | grep -q '^${mcp_container}$'"
if docker ps --format '{{.Names}}' | grep -q "^${mcp_container}$"; then
# Test MCP server
if docker exec "${mcp_container}" node -e "console.log('MCP server check')" &> /dev/null; then
echo -e "${GREEN}✓${NC} MCP server responsive"
((CHECKS_PASSED++))
# Check connection to ComfyUI
if docker logs "${mcp_container}" 2>&1 | tail -20 | grep -q "Connected to ComfyUI"; then
echo -e "${GREEN}✓${NC} MCP connected to ComfyUI"
((CHECKS_PASSED++))
else
echo -e "${YELLOW}⚠${NC} MCP connection to ComfyUI unclear"
fi
else
echo -e "${RED}✗${NC} MCP server not responding"
((CHECKS_FAILED++))
ISSUES+=("MCP server response")
fi
fi
}
# Logs check
check_logs() {
echo ""
echo "Recent Logs:"
echo "------------"
local comfyui_container="${PROJECT_NAME}-comfyui-1"
local mcp_container="${PROJECT_NAME}-mcp-server-1"
# Check for errors in ComfyUI logs
if docker logs "${comfyui_container}" --tail 50 2>&1 | grep -qi "error\|exception\|failed" | grep -v "IMPORT FAILED" | grep -v "comfy_api_nodes"; then
echo -e "${YELLOW}⚠${NC} Potential errors found in ComfyUI logs"
echo " Run 'docker logs ${comfyui_container}' to view"
else
echo -e "${GREEN}✓${NC} No critical errors in ComfyUI logs"
fi
# Check for errors in MCP server logs
if docker logs "${mcp_container}" --tail 20 2>&1 | grep -qi "error\|exception\|failed"; then
echo -e "${YELLOW}⚠${NC} Errors found in MCP server logs"
echo " Run 'docker logs ${mcp_container}' to view"
else
echo -e "${GREEN}✓${NC} No recent errors in MCP server logs"
fi
}
# Performance check
check_performance() {
echo ""
echo "System Resources:"
echo "-----------------"
# Check memory usage
if command -v free &> /dev/null; then
local mem_info
mem_info=$(free -h | grep "^Mem:" | awk '{printf "Total: %s, Used: %s, Free: %s", $2, $3, $4}')
echo " Memory: ${mem_info}"
fi
# Check disk space
local disk_info
disk_info=$(df -h "${PROJECT_ROOT}" | awk 'NR==2 {printf "Total: %s, Used: %s, Available: %s (%s)", $2, $3, $4, $5}')
echo " Disk: ${disk_info}"
# Check Docker resource usage
echo ""
echo " Container Resources:"
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" 2>/dev/null | grep -E "(CONTAINER|${PROJECT_NAME})" || true
}
# Summary
print_summary() {
echo ""
echo "══════════════════════════════════════════════════════════"
echo " Summary"
echo "══════════════════════════════════════════════════════════"
local total=$((CHECKS_PASSED + CHECKS_FAILED))
echo "Checks passed: ${CHECKS_PASSED}/${total}"
if [[ ${CHECKS_FAILED} -eq 0 ]]; then
echo -e "${GREEN}✓ All systems operational!${NC}"
echo ""
echo "Access points:"
echo " • ComfyUI: http://localhost:${COMFYUI_PORT}"
echo " • Project: ${PROJECT_NAME}"
return 0
else
echo -e "${YELLOW}⚠ Issues detected:${NC}"
for issue in "${ISSUES[@]}"; do
echo " • ${issue}"
done
echo ""
echo "Troubleshooting:"
echo " • Check logs: docker compose -p ${PROJECT_NAME} logs"
echo " • Restart services: docker compose -p ${PROJECT_NAME} restart"
echo " • Rebuild: ./build.sh --no-cache"
echo " • Re-run setup: ./install.sh"
return 1
fi
}
# Main execution
main() {
print_header
# Run all checks
check_docker
check_containers
check_network
check_gpu
check_models
check_environment
check_mcp
check_logs
check_performance
# Print summary
print_summary
}
# Handle arguments
case "${1:-}" in
--quick|-q)
# Quick check - only essential services
print_header
check_docker
check_containers
check_network
print_summary
;;
--help|-h)
cat << EOF
Usage: $0 [OPTIONS]
Options:
--quick, -q Run quick health check (essential services only)
--help, -h Show this help message
Performs comprehensive health check of MCP ComfyUI Flux installation.
Checks the optimized production setup with PyTorch 2.5.1 and BuildKit.
EOF
exit 0
;;
*)
main
;;
esac