generated from coulomb/repo-seed
152 lines
3.5 KiB
Bash
Executable File
152 lines
3.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
STATE_HUB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
CLAUDE_JSON="${CLAUDE_JSON:-$HOME/.claude.json}"
|
|
SERVER_NAME="${STATE_HUB_MCP_NAME:-state-hub}"
|
|
API_BASE="${API_BASE:-}"
|
|
MCP_URL="${MCP_URL:-}"
|
|
DRY_RUN=0
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: scripts/register-mcp.sh [--url URL] [--api-base URL] [--dry-run]
|
|
|
|
Registers the State Hub MCP server for Claude Code.
|
|
|
|
Options:
|
|
--url URL MCP SSE URL to register. Defaults to local :8001 or tunnel :18001.
|
|
--api-base URL State Hub API URL used for reachability checks.
|
|
--dry-run Print what would happen without changing Claude config.
|
|
-h, --help Show this help.
|
|
USAGE
|
|
}
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--url)
|
|
MCP_URL="${2:-}"
|
|
shift 2
|
|
;;
|
|
--api-base)
|
|
API_BASE="${2:-}"
|
|
shift 2
|
|
;;
|
|
--dry-run)
|
|
DRY_RUN=1
|
|
shift
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "ERROR: unknown argument: $1" >&2
|
|
usage >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
status() {
|
|
printf '%s\n' "$*"
|
|
}
|
|
|
|
api_healthy() {
|
|
local base="$1"
|
|
curl -fsS --max-time 2 "${base%/}/state/health" >/dev/null 2>&1
|
|
}
|
|
|
|
port_open() {
|
|
local host="$1"
|
|
local port="$2"
|
|
timeout 2 bash -c ":</dev/tcp/$host/$port" >/dev/null 2>&1
|
|
}
|
|
|
|
if [ -z "$API_BASE" ]; then
|
|
if api_healthy "http://127.0.0.1:8000"; then
|
|
API_BASE="http://127.0.0.1:8000"
|
|
elif api_healthy "http://127.0.0.1:18000"; then
|
|
API_BASE="http://127.0.0.1:18000"
|
|
else
|
|
API_BASE="http://127.0.0.1:8000"
|
|
fi
|
|
fi
|
|
|
|
if [ -z "$MCP_URL" ]; then
|
|
if port_open 127.0.0.1 8001; then
|
|
MCP_URL="http://127.0.0.1:8001/sse"
|
|
elif port_open 127.0.0.1 18001; then
|
|
MCP_URL="http://127.0.0.1:18001/sse"
|
|
elif [ "$API_BASE" = "http://127.0.0.1:18000" ]; then
|
|
MCP_URL="http://127.0.0.1:18001/sse"
|
|
else
|
|
MCP_URL="http://127.0.0.1:8001/sse"
|
|
fi
|
|
fi
|
|
|
|
CONFIG="$(python3 - "$MCP_URL" <<'PY'
|
|
import json
|
|
import sys
|
|
|
|
print(json.dumps({"type": "sse", "url": sys.argv[1]}, separators=(",", ":")))
|
|
PY
|
|
)"
|
|
|
|
status "State Hub directory: $STATE_HUB_DIR"
|
|
status "API health check: ${API_BASE%/}/state/health"
|
|
status "MCP registration: $SERVER_NAME -> $MCP_URL"
|
|
|
|
if api_healthy "$API_BASE"; then
|
|
status "OK: State Hub API is reachable."
|
|
else
|
|
status "WARN: State Hub API is not reachable at ${API_BASE%/}/state/health."
|
|
status " Start it with 'make api' or bring up the ops-bridge tunnel."
|
|
fi
|
|
|
|
if ! command -v claude >/dev/null 2>&1; then
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
status "WARN: claude CLI not found on PATH; dry-run will still show the command."
|
|
else
|
|
status "ERROR: claude CLI not found on PATH."
|
|
status " Install or expose Claude Code CLI, then rerun: make register-mcp"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
CURRENT_URL="$(python3 - "$CLAUDE_JSON" "$SERVER_NAME" <<'PY'
|
|
import json
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
path = Path(sys.argv[1])
|
|
name = sys.argv[2]
|
|
if not path.exists():
|
|
print("")
|
|
raise SystemExit
|
|
try:
|
|
data = json.loads(path.read_text())
|
|
except json.JSONDecodeError:
|
|
print("")
|
|
raise SystemExit
|
|
entry = data.get("mcpServers", {}).get(name, {})
|
|
print(entry.get("url", ""))
|
|
PY
|
|
)"
|
|
|
|
if [ "$CURRENT_URL" = "$MCP_URL" ]; then
|
|
status "OK: $SERVER_NAME is already registered with this URL."
|
|
exit 0
|
|
fi
|
|
|
|
if [ "$DRY_RUN" -eq 1 ]; then
|
|
status "DRY-RUN: would run:"
|
|
status " claude mcp add-json -s user $SERVER_NAME '$CONFIG'"
|
|
exit 0
|
|
fi
|
|
|
|
claude mcp add-json -s user "$SERVER_NAME" "$CONFIG"
|
|
|
|
status "OK: registered $SERVER_NAME."
|
|
status "Restart Claude Code so the MCP server list is refreshed."
|