You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/scripts/mcp/DiscoveryAgent/ClaudeCode_Headless/headless_db_discovery.sh

266 lines
7.3 KiB

#!/usr/bin/env bash
#
# headless_db_discovery.sh
#
# Multi-Agent Database Discovery using Claude Code
#
# This script runs Claude Code in non-interactive mode to perform
# comprehensive database discovery using 4 collaborating agents:
# STRUCTURAL, STATISTICAL, SEMANTIC, and QUERY.
#
# Usage:
# ./headless_db_discovery.sh [options]
#
# Options:
# -d, --database DB_NAME Database name to discover (default: discover from available)
# -s, --schema SCHEMA Schema name to analyze (default: all schemas)
# -o, --output FILE Output file for results (default: discovery_YYYYMMDD_HHMMSS.md)
# -m, --mcp-config JSON MCP server configuration (inline JSON)
# -f, --mcp-file FILE MCP server configuration file
# -t, --timeout SECONDS Timeout for discovery in seconds (default: 3600 = 1 hour)
# -v, --verbose Enable verbose output
# -h, --help Show this help message
#
# Examples:
# # Basic discovery (uses available MCP database connection)
# ./headless_db_discovery.sh
#
# # Discover specific database
# ./headless_db_discovery.sh -d mydb
#
# # With custom MCP server
# ./headless_db_discovery.sh -m '{"mcpServers": {"mydb": {"command": "...", "args": [...]}}}'
#
# # With output file
# ./headless_db_discovery.sh -o my_discovery_report.md
#
# Environment Variables:
# CLAUDE_PATH Path to claude executable (default: ~/.local/bin/claude)
#
set -e
# Default values
DATABASE_NAME=""
SCHEMA_NAME=""
OUTPUT_FILE=""
MCP_CONFIG=""
MCP_FILE=""
TIMEOUT=3600 # 1 hour default (multi-agent discovery takes longer)
VERBOSE=0
CLAUDE_CMD="${CLAUDE_PATH:-$HOME/.local/bin/claude}"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
log_success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
log_verbose() {
if [ "$VERBOSE" -eq 1 ]; then
echo -e "${BLUE}[VERBOSE]${NC} $1"
fi
}
# Print usage
usage() {
grep '^#' "$0" | grep -v '!/bin/' | sed 's/^# //' | sed 's/^#//'
exit 0
}
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-d|--database)
DATABASE_NAME="$2"
shift 2
;;
-s|--schema)
SCHEMA_NAME="$2"
shift 2
;;
-o|--output)
OUTPUT_FILE="$2"
shift 2
;;
-m|--mcp-config)
MCP_CONFIG="$2"
shift 2
;;
-f|--mcp-file)
MCP_FILE="$2"
shift 2
;;
-t|--timeout)
TIMEOUT="$2"
shift 2
;;
-v|--verbose)
VERBOSE=1
shift
;;
-h|--help)
usage
;;
*)
log_error "Unknown option: $1"
usage
;;
esac
done
# Validate Claude Code is available
if [ ! -f "$CLAUDE_CMD" ]; then
log_error "Claude Code not found at: $CLAUDE_CMD"
log_error "Set CLAUDE_PATH environment variable or ensure claude is in ~/.local/bin/"
exit 1
fi
# Set default output file if not specified
if [ -z "$OUTPUT_FILE" ]; then
OUTPUT_FILE="discovery_$(date +%Y%m%d_%H%M%S).md"
fi
# Get the directory where this script is located
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROMPT_FILE="$SCRIPT_DIR/prompts/multi_agent_discovery_prompt.md"
# Validate prompt file exists
if [ ! -f "$PROMPT_FILE" ]; then
log_error "Multi-agent discovery prompt not found at: $PROMPT_FILE"
log_error "Ensure the prompts/ directory exists with multi_agent_discovery_prompt.md"
exit 1
fi
log_info "Starting Multi-Agent Database Discovery"
log_info "Output will be saved to: $OUTPUT_FILE"
log_verbose "Using discovery prompt: $PROMPT_FILE"
# Read the base prompt
DISCOVERY_PROMPT="$(cat "$PROMPT_FILE")"
# Add database-specific context if provided
if [ -n "$DATABASE_NAME" ]; then
DISCOVERY_PROMPT="$DISCOVERY_PROMPT
**Target Database:** $DATABASE_NAME"
if [ -n "$SCHEMA_NAME" ]; then
DISCOVERY_PROMPT="$DISCOVERY_PROMPT
**Target Schema:** $SCHEMA_NAME"
fi
log_verbose "Target database: $DATABASE_NAME"
[ -n "$SCHEMA_NAME" ] && log_verbose "Target schema: $SCHEMA_NAME"
fi
# Build MCP args
MCP_ARGS=""
if [ -n "$MCP_CONFIG" ]; then
MCP_ARGS="--mcp-config $MCP_CONFIG"
log_verbose "Using inline MCP configuration"
elif [ -n "$MCP_FILE" ]; then
if [ -f "$MCP_FILE" ]; then
MCP_ARGS="--mcp-config $MCP_FILE"
log_verbose "Using MCP configuration from: $MCP_FILE"
else
log_error "MCP configuration file not found: $MCP_FILE"
exit 1
fi
fi
# Log the command being executed
log_info "Running Claude Code in headless mode with 6-agent discovery..."
log_verbose "Timeout: ${TIMEOUT}s"
# Build Claude command
CLAUDE_ARGS=(
--print
--no-session-persistence
--permission-mode bypassPermissions
)
# Add MCP configuration if available
if [ -n "$MCP_ARGS" ]; then
CLAUDE_ARGS+=($MCP_ARGS)
fi
# Execute Claude Code in headless mode
log_verbose "Executing: $CLAUDE_CMD ${CLAUDE_ARGS[*]}"
# Run the discovery and capture output
if timeout "${TIMEOUT}s" $CLAUDE_CMD "${CLAUDE_ARGS[@]}" <<< "$DISCOVERY_PROMPT" > "$OUTPUT_FILE" 2>&1; then
log_success "Discovery completed successfully!"
log_info "Report saved to: $OUTPUT_FILE"
# Print summary statistics
if [ -f "$OUTPUT_FILE" ]; then
lines=$(wc -l < "$OUTPUT_FILE")
words=$(wc -w < "$OUTPUT_FILE")
log_info "Report size: $lines lines, $words words"
# Check if file is empty (no output)
if [ "$lines" -eq 0 ]; then
log_warn "Output file is empty - discovery may have failed silently"
log_info "Try running with --verbose to see more details"
fi
# Try to extract key info if report contains markdown headers
if grep -q "^# " "$OUTPUT_FILE"; then
log_info "Report sections:"
grep "^# " "$OUTPUT_FILE" | head -10 | while read -r section; do
echo " - $section"
done
fi
fi
else
exit_code=$?
# Exit code 124 means timeout command killed the process
if [ "$exit_code" -eq 124 ]; then
log_error "Discovery timed out after ${TIMEOUT} seconds"
log_error "The multi-agent discovery process can take a long time for complex databases"
log_info "Try increasing timeout with: --timeout $((TIMEOUT * 2))"
log_info "Example: $0 --timeout $((TIMEOUT * 2))"
else
log_error "Discovery failed with exit code: $exit_code"
log_info "Check $OUTPUT_FILE for error details"
fi
# Show last few lines of output if it exists
if [ -f "$OUTPUT_FILE" ]; then
file_size=$(wc -c < "$OUTPUT_FILE")
if [ "$file_size" -gt 0 ]; then
log_verbose "Last 30 lines of output:"
tail -30 "$OUTPUT_FILE" | sed 's/^/ /'
else
log_warn "Output file is empty (0 bytes)"
log_info "This usually means Claude Code failed to start or produced no output"
log_info "Check that Claude Code is installed: $CLAUDE_CMD --version"
log_info "Or try with --verbose for more debugging information"
fi
fi
exit $exit_code
fi
log_success "Done!"