bevy_debugger_mcp 0.1.8

AI-assisted debugging for Bevy games through Claude Code using Model Context Protocol
Documentation
#!/bin/bash

# Bevy Debugger MCP Control Script
# Copyright (C) 2025 ladvien
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

# Bevy Debugger MCP Control Script
# Manages the bevy-debugger-mcp server lifecycle

PROGRAM_NAME="bevy-debugger-mcp"
LOG_DIR="$HOME/.bevy-debugger"
LOG_FILE="$LOG_DIR/bevy-debugger.log"
PID_FILE="$LOG_DIR/bevy-debugger.pid"
DEFAULT_PORT=3001
DEFAULT_HOST="localhost"

# Create log directory if it doesn't exist
mkdir -p "$LOG_DIR"

# Color output for better readability
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

print_status() {
    echo -e "${GREEN}[✓]${NC} $1"
}

print_error() {
    echo -e "${RED}[✗]${NC} $1"
}

print_info() {
    echo -e "${YELLOW}[i]${NC} $1"
}

get_pid() {
    if [ -f "$PID_FILE" ]; then
        cat "$PID_FILE"
    else
        pgrep -x "$PROGRAM_NAME" | head -1
    fi
}

is_running() {
    local pid=$(get_pid)
    if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
        return 0
    else
        return 1
    fi
}

start_server() {
    if is_running; then
        print_error "$PROGRAM_NAME is already running (PID: $(get_pid))"
        return 1
    fi

    print_info "Starting $PROGRAM_NAME..."
    
    # Rotate logs if they're too large (>10MB)
    if [ -f "$LOG_FILE" ] && [ $(stat -f%z "$LOG_FILE" 2>/dev/null || stat -c%s "$LOG_FILE" 2>/dev/null || echo 0) -gt 10485760 ]; then
        mv "$LOG_FILE" "$LOG_FILE.$(date +%Y%m%d_%H%M%S)"
        print_info "Rotated large log file"
    fi
    
    # Set environment variables for MCP port
    export MCP_PORT="${BEVY_DEBUGGER_PORT:-$DEFAULT_PORT}"
    export BEVY_BRP_HOST="${BEVY_BRP_HOST:-localhost}"
    export BEVY_BRP_PORT="${BEVY_BRP_PORT:-15702}"
    
    # Start the server in TCP mode
    nohup "$PROGRAM_NAME" --tcp >> "$LOG_FILE" 2>&1 &
    
    local pid=$!
    echo $pid > "$PID_FILE"
    
    # Wait a moment to check if it started successfully
    sleep 2
    
    if is_running; then
        print_status "$PROGRAM_NAME started successfully (PID: $pid)"
        print_info "Listening on ${BEVY_DEBUGGER_HOST:-$DEFAULT_HOST}:${BEVY_DEBUGGER_PORT:-$DEFAULT_PORT}"
        print_info "Logs: $LOG_FILE"
        return 0
    else
        print_error "Failed to start $PROGRAM_NAME"
        print_info "Check logs at: $LOG_FILE"
        return 1
    fi
}

stop_server() {
    if ! is_running; then
        print_error "$PROGRAM_NAME is not running"
        return 1
    fi
    
    local pid=$(get_pid)
    print_info "Stopping $PROGRAM_NAME (PID: $pid)..."
    
    # Try graceful shutdown first
    kill "$pid" 2>/dev/null
    
    # Wait up to 5 seconds for graceful shutdown
    local count=0
    while [ $count -lt 5 ] && is_running; do
        sleep 1
        count=$((count + 1))
    done
    
    # Force kill if still running
    if is_running; then
        print_info "Force stopping $PROGRAM_NAME..."
        kill -9 "$pid" 2>/dev/null
        sleep 1
    fi
    
    # Clean up PID file
    rm -f "$PID_FILE"
    
    if ! is_running; then
        print_status "$PROGRAM_NAME stopped successfully"
        return 0
    else
        print_error "Failed to stop $PROGRAM_NAME"
        return 1
    fi
}

restart_server() {
    print_info "Restarting $PROGRAM_NAME..."
    stop_server
    sleep 1
    start_server
}

server_status() {
    if is_running; then
        local pid=$(get_pid)
        print_status "$PROGRAM_NAME is running (PID: $pid)"
        
        # Show process info
        ps -p "$pid" -o pid,user,%cpu,%mem,start,time,command | tail -n +1
        
        # Check if port is listening
        if lsof -i ":${BEVY_DEBUGGER_PORT:-$DEFAULT_PORT}" >/dev/null 2>&1; then
            print_info "Port ${BEVY_DEBUGGER_PORT:-$DEFAULT_PORT} is open"
        fi
        
        # Show recent logs
        if [ -f "$LOG_FILE" ]; then
            print_info "Recent logs:"
            tail -5 "$LOG_FILE" | sed 's/^/  /'
        fi
        
        return 0
    else
        print_error "$PROGRAM_NAME is not running"
        return 1
    fi
}

show_logs() {
    if [ ! -f "$LOG_FILE" ]; then
        print_error "No log file found"
        return 1
    fi
    
    if [ "$1" = "-f" ] || [ "$1" = "--follow" ]; then
        print_info "Following logs (Ctrl+C to stop)..."
        tail -f "$LOG_FILE"
    else
        less "$LOG_FILE"
    fi
}

clean_logs() {
    print_info "Cleaning log files..."
    
    # Keep current log and remove old rotated logs older than 7 days
    find "$LOG_DIR" -name "bevy-debugger.log.*" -mtime +7 -delete
    
    # Truncate current log if requested
    if [ "$1" = "--all" ]; then
        > "$LOG_FILE"
        print_status "All logs cleared"
    else
        print_status "Old rotated logs removed"
    fi
}

show_help() {
    cat << EOF
Bevy Debugger MCP Control Script

Usage: $(basename "$0") <command> [options]

Commands:
    start       Start the bevy-debugger-mcp server
    stop        Stop the bevy-debugger-mcp server
    restart     Restart the bevy-debugger-mcp server
    status      Show server status and information
    logs        Show server logs (use -f to follow)
    clean       Clean old log files (use --all to clear all)
    help        Show this help message

Environment Variables:
    BEVY_DEBUGGER_HOST    Host to bind to (default: localhost)
    BEVY_DEBUGGER_PORT    Port to listen on (default: 3001)

Examples:
    $(basename "$0") start                    # Start server
    $(basename "$0") restart                  # Restart server
    $(basename "$0") logs -f                  # Follow logs in real-time
    BEVY_DEBUGGER_PORT=3002 $(basename "$0") start  # Start on different port

Files:
    Logs:     $LOG_FILE
    PID:      $PID_FILE

EOF
}

# Main command handling
case "${1:-help}" in
    start)
        start_server
        ;;
    stop)
        stop_server
        ;;
    restart)
        restart_server
        ;;
    status)
        server_status
        ;;
    logs)
        show_logs "$2"
        ;;
    clean)
        clean_logs "$2"
        ;;
    help|--help|-h)
        show_help
        ;;
    *)
        print_error "Unknown command: $1"
        echo
        show_help
        exit 1
        ;;
esac