#!/usr/bin/env bash # ============================================================================= # MCPletA2A — start.sh # Starts: Mock Service (port 5100) + Platform Host (Dashboard :4000, A2A :4001) # MCPlet servers are spawned automatically by the Host via stdio. # ============================================================================= set -euo pipefail BASE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PLATFORM_DIR="$BASE_DIR/platform_impl" REF_DIR="$BASE_DIR/reference_impl" PID_DIR="$BASE_DIR/.pids" LOG_DIR="$BASE_DIR/.logs" export REF_IMPL_DIST="$REF_DIR/dist" # ---- Colour helpers ---------------------------------------------------------- RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' CYAN='\033[0;36m'; BOLD='\033[1m'; RESET='\033[0m' info() { echo -e "${CYAN}[start]${RESET} $*"; } ok() { echo -e "${GREEN}[start]${RESET} $*"; } warn() { echo -e "${YELLOW}[start]${RESET} $*"; } die() { echo -e "${RED}[start] ERROR:${RESET} $*" >&2; exit 1; } # ---- Pre-flight checks ------------------------------------------------------- command -v node >/dev/null 2>&1 || die "node is not in PATH" [[ -f "$PLATFORM_DIR/dist/index.js" ]] || \ die "platform_impl not built. Run: cd platform_impl && npm run build" [[ -f "$REF_DIR/dist/mock-services/server.js" ]] || \ die "reference_impl not built. Run: cd reference_impl && npm run build" # ---- LLM API key check ------------------------------------------------------- # Read the provider from reference.yaml (line starting with " provider:") _llm_provider="$(grep -E '^\s+provider:' "$REF_DIR/config/reference.yaml" | head -1 | awk '{print $2}')" case "$_llm_provider" in openrouter) if [[ -z "${OPENROUTER_API_KEY:-}" ]]; then warn "LLM provider is 'openrouter' but OPENROUTER_API_KEY is not set." warn " → Get a key at https://openrouter.ai/keys" warn " → Then run: export OPENROUTER_API_KEY=sk-or-..." warn " LLM calls will fail until the key is set." fi ;; claude|"") if [[ -z "${ANTHROPIC_API_KEY:-}" ]]; then warn "LLM provider is 'claude' but ANTHROPIC_API_KEY is not set." warn " → Get a key at https://console.anthropic.com/settings/keys" warn " → Then run: export ANTHROPIC_API_KEY=sk-ant-..." warn " To switch to OpenRouter instead, edit:" warn " $REF_DIR/config/reference.yaml" warn " Uncomment the 'provider: openrouter' block and set OPENROUTER_API_KEY." warn " LLM calls will fail until the key is set." fi ;; *) warn "Unknown LLM provider '$_llm_provider' in reference.yaml." warn " Supported values: claude, openrouter" ;; esac mkdir -p "$PID_DIR" "$LOG_DIR" # ---- Check already running --------------------------------------------------- is_running() { local pidfile="$PID_DIR/$1.pid" [[ -f "$pidfile" ]] && kill -0 "$(cat "$pidfile")" 2>/dev/null } if is_running mock-services || is_running platform-host; then warn "Some services are already running. Run ./stop.sh first." exit 1 fi # ---- Start Mock Service (port 5100) ----------------------------------------- info "Starting Mock Service on port 5100 ..." node "$REF_DIR/dist/mock-services/server.js" \ >"$LOG_DIR/mock-services.log" 2>&1 & echo $! > "$PID_DIR/mock-services.pid" # Wait until port 5100 is accepting connections (max 10 s) for i in $(seq 1 20); do if node -e " const net = require('net'); const s = net.createConnection(5100, '127.0.0.1'); s.on('connect', () => { s.destroy(); process.exit(0); }); s.on('error', () => { s.destroy(); process.exit(1); }); " 2>/dev/null; then ok "Mock Service ready (pid $(cat "$PID_DIR/mock-services.pid"))" break fi sleep 0.5 if [[ $i -eq 20 ]]; then die "Mock Service did not start in time. Check $LOG_DIR/mock-services.log" fi done # ---- Start Platform Host (spawns MCPlet servers internally) ------------------ info "Starting Platform Host ..." info " Config : $REF_DIR/config/reference.yaml" info " Dashboard → http://localhost:4000" info " A2A ext → http://localhost:4001" MCPLET_CONFIG="$REF_DIR/config/reference.yaml" \ MCPLET_AGENT_MODULE="file://$REF_DIR/dist/agents/register.js" \ node "$PLATFORM_DIR/dist/index.js" \ >"$LOG_DIR/platform-host.log" 2>&1 & echo $! > "$PID_DIR/platform-host.pid" # Wait until Dashboard is reachable (max 15 s) for i in $(seq 1 30); do if node -e " const net = require('net'); const s = net.createConnection(4000, '127.0.0.1'); s.on('connect', () => { s.destroy(); process.exit(0); }); s.on('error', () => { s.destroy(); process.exit(1); }); " 2>/dev/null; then ok "Platform Host ready (pid $(cat "$PID_DIR/platform-host.pid"))" break fi sleep 0.5 if [[ $i -eq 30 ]]; then warn "Platform Host did not expose Dashboard in time." warn "Check $LOG_DIR/platform-host.log for errors." fi done # ---- Summary ----------------------------------------------------------------- echo "" echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" echo -e "${GREEN}${BOLD} MCPletA2A started successfully${RESET}" echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" echo -e " Mock Service → ${CYAN}http://localhost:5100${RESET}" echo -e " Dashboard → ${CYAN}http://localhost:4000${RESET}" echo -e " A2A Endpoint → ${CYAN}http://localhost:4001/a2a/task${RESET}" echo "" echo -e " Logs : ${LOG_DIR}/" echo -e " Stop : ${BOLD}./stop.sh${RESET}" echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"