#!/bin/bash set -e # ======================= Supabase Config ======================= # Strip any whitespace/newlines from environment variables export SUPABASE_URL="${SUPABASE_URL//[$'\t\r\n ']}" export SUPABASE_ANON_KEY="${SUPABASE_ANON_KEY//[$'\t\r\n ']}" export CONFIG_ID="mcp_settings" # ================================================================ # --- Define paths --- APP_SRC_DIR="/app" RUN_DIR="/tmp/mcphub" CONFIG_FILE_NAME="mcp_settings.json" CONFIG_FILE_PATH="${RUN_DIR}/${CONFIG_FILE_NAME}" echo "--- MCPHub with Supabase Storage ---" # 1. Create runtime directory and copy files echo "Setting up runtime environment..." mkdir -p "$RUN_DIR" cp -a "${APP_SRC_DIR}/." "$RUN_DIR/" # 2. Download config from Supabase echo "Loading configuration..." RESPONSE=$(curl --http1.1 -s -S -X GET \ "${SUPABASE_URL}/rest/v1/configs?id=eq.${CONFIG_ID}&select=content" \ -H "apikey: ${SUPABASE_ANON_KEY}" \ -H "Authorization: Bearer ${SUPABASE_ANON_KEY}" \ -H "Accept: application/json" 2>&1) if [ -n "$RESPONSE" ] && [ "$RESPONSE" != "[]" ] && [[ ! "$RESPONSE" =~ "ERROR" ]]; then echo "$RESPONSE" | python3 -c " import sys, json try: data = json.load(sys.stdin) if data and len(data) > 0: print(json.dumps(data[0]['content'])) else: print('{}') except: print('{}') " > "$CONFIG_FILE_PATH" echo "✅ Configuration loaded" else echo "{}" > "$CONFIG_FILE_PATH" echo "⚠️ Using default configuration" fi # 3. Function to sync file to Supabase sync_to_supabase() { if [ ! -f "$CONFIG_FILE_PATH" ]; then return 1 fi # Create JSON payload using Python (just for JSON formatting) PAYLOAD=$(python3 -c " import json from datetime import datetime with open('$CONFIG_FILE_PATH', 'r') as f: config = json.load(f) payload = { 'content': config, 'updated_at': datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%S') } print(json.dumps(payload)) " 2>/dev/null) if [ -n "$PAYLOAD" ]; then # Upload using curl curl --http1.1 -s -X PATCH \ "${SUPABASE_URL}/rest/v1/configs?id=eq.${CONFIG_ID}" \ -H "apikey: ${SUPABASE_ANON_KEY}" \ -H "Authorization: Bearer ${SUPABASE_ANON_KEY}" \ -H "Content-Type: application/json" \ -H "Prefer: return=minimal" \ -d "$PAYLOAD" > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "✅ Config synced to Supabase at $(date)" fi fi } # 4. Heartbeat function to keep Supabase active send_heartbeat() { curl --http1.1 -s -X POST \ "${SUPABASE_URL}/rest/v1/heartbeat" \ -H "apikey: ${SUPABASE_ANON_KEY}" \ -H "Authorization: Bearer ${SUPABASE_ANON_KEY}" \ -H "Content-Type: application/json" \ -H "Prefer: return=minimal" \ -d "{\"source\": \"mcphub-$(hostname 2>/dev/null || echo 'docker')\"}" > /dev/null 2>&1 if [ $? -eq 0 ]; then echo "♥️ Heartbeat sent at $(date)" fi } # 5. Start background sync process echo "Starting background sync..." ( LAST_HASH="" if [ -f "$CONFIG_FILE_PATH" ]; then LAST_HASH=$(md5sum "$CONFIG_FILE_PATH" | awk '{ print $1 }') fi while true; do sleep 30 if [ -f "$CONFIG_FILE_PATH" ]; then CURRENT_HASH=$(md5sum "$CONFIG_FILE_PATH" | awk '{ print $1 }') if [ "$CURRENT_HASH" != "$LAST_HASH" ]; then sync_to_supabase LAST_HASH=$CURRENT_HASH fi fi done ) & # 6. Start heartbeat process to keep Supabase active echo "Starting heartbeat process..." ( # Send initial heartbeat send_heartbeat # Send heartbeat every 6 hours while true; do sleep 21600 # 6 hours send_heartbeat done ) & # 7. Start application echo "🚀 Starting MCPHub server..." cd "$RUN_DIR" npm start echo "MCPHub server stopped."