|
1 | 1 | #!/bin/bash |
2 | 2 | # ============================================================================= |
3 | | -# Synapse Layer — Smithery Registry Publish Script v2 |
| 3 | +# Synapse Layer — Smithery Registry Publish Script v3 |
4 | 4 | # Run this on your LOCAL machine (not VM) to authenticate and publish. |
| 5 | +# |
| 6 | +# Prerequisites: |
| 7 | +# - Node.js 20+ |
| 8 | +# - Internet access to smithery.ai (Vercel-hosted, needs real browser) |
| 9 | +# |
| 10 | +# Usage: |
| 11 | +# chmod +x scripts/smithery-publish.sh |
| 12 | +# ./scripts/smithery-publish.sh |
5 | 13 | # ============================================================================= |
6 | | -set -e |
| 14 | +set -euo pipefail |
7 | 15 |
|
8 | 16 | SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" |
9 | 17 | REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" |
10 | 18 | CONFIG_SCHEMA="${REPO_ROOT}/scripts/smithery-config-schema.json" |
| 19 | +SERVER_URL="https://forge.synapselayer.org/api/mcp" |
| 20 | +QUALIFIED_NAME="synapselayer/synapse-protocol" |
| 21 | +EXPECTED_TOOLS=13 |
11 | 22 |
|
12 | | -echo "🧠 Synapse Layer — Smithery Publish Pipeline v2" |
| 23 | +echo "🧠 Synapse Layer — Smithery Publish Pipeline v3" |
13 | 24 | echo "================================================" |
14 | 25 | echo "" |
15 | 26 |
|
16 | | -# 1. Check CLI |
| 27 | +# ── Step 0: Pre-flight validation ────────────────────────────────── |
| 28 | +echo "📋 Step 0: Pre-flight validation..." |
| 29 | + |
| 30 | +# Check npx |
17 | 31 | if ! command -v npx &> /dev/null; then |
18 | 32 | echo "❌ npx not found. Install Node.js 20+ first." |
19 | 33 | exit 1 |
20 | 34 | fi |
21 | | -echo "✅ Node.js found: $(node --version)" |
| 35 | +echo " ✅ Node.js: $(node --version)" |
| 36 | + |
| 37 | +# Check config schema |
| 38 | +if [ ! -f "$CONFIG_SCHEMA" ]; then |
| 39 | + echo "❌ Config schema not found at $CONFIG_SCHEMA" |
| 40 | + exit 1 |
| 41 | +fi |
| 42 | +python3 -c "import json; json.load(open('$CONFIG_SCHEMA'))" 2>/dev/null || { |
| 43 | + echo "❌ Config schema is invalid JSON" |
| 44 | + exit 1 |
| 45 | +} |
| 46 | +echo " ✅ Config schema valid" |
| 47 | + |
| 48 | +# Check server accessibility |
| 49 | +TOOL_COUNT=$(curl -sf -X POST "$SERVER_URL" \ |
| 50 | + -H "Content-Type: application/json" \ |
| 51 | + -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' | \ |
| 52 | + python3 -c "import sys,json; print(len(json.loads(sys.stdin.read()).get('result',{}).get('tools',[])))" 2>/dev/null || echo "0") |
| 53 | + |
| 54 | +if [ "$TOOL_COUNT" -lt "$EXPECTED_TOOLS" ]; then |
| 55 | + echo "❌ Server returns $TOOL_COUNT tools (expected $EXPECTED_TOOLS)" |
| 56 | + echo " Fix the MCP server before publishing." |
| 57 | + exit 1 |
| 58 | +fi |
| 59 | +echo " ✅ Server returns $TOOL_COUNT tools" |
| 60 | + |
| 61 | +# Snapshot before |
| 62 | +echo "" |
| 63 | +echo "📸 Current registry state (BEFORE):" |
| 64 | +curl -sf "https://registry.smithery.ai/servers/@${QUALIFIED_NAME}" | python3 -c " |
| 65 | +import json, sys |
| 66 | +data = json.load(sys.stdin) |
| 67 | +tools = data.get('tools', []) |
| 68 | +print(f' Tools: {len(tools)}') |
| 69 | +for t in tools: print(f' - {t[\"name\"]}') |
| 70 | +print(f' Description: {data.get(\"description\", \"N/A\")[:80]}...') |
| 71 | +" 2>/dev/null || echo " ⚠️ Could not fetch current registry state" |
22 | 72 | echo "" |
23 | 73 |
|
24 | | -# 2. Authenticate |
| 74 | +# ── Step 1: Authenticate ────────────────────────────────────────── |
25 | 75 | echo "🔐 Step 1: Authenticating with Smithery..." |
| 76 | +echo " This will open your browser. Log in with your Smithery account." |
| 77 | +echo "" |
26 | 78 | npx @smithery/cli auth login |
27 | 79 | echo "" |
28 | 80 |
|
29 | | -# 3. Verify auth |
| 81 | +# Verify auth |
30 | 82 | echo "🔍 Step 2: Verifying authentication..." |
31 | 83 | npx @smithery/cli auth whoami |
32 | 84 | echo "" |
33 | 85 |
|
34 | | -# 4. Verify config schema exists |
35 | | -if [ ! -f "$CONFIG_SCHEMA" ]; then |
36 | | - echo "❌ Config schema not found at $CONFIG_SCHEMA" |
37 | | - exit 1 |
38 | | -fi |
39 | | -echo "✅ Config schema found: $CONFIG_SCHEMA" |
40 | | -echo "" |
41 | | - |
42 | | -# 5. Publish (update existing listing) |
| 86 | +# ── Step 3: Publish ─────────────────────────────────────────────── |
43 | 87 | echo "🚀 Step 3: Publishing to Smithery Registry..." |
44 | 88 | npx @smithery/cli mcp publish \ |
45 | | - https://forge.synapselayer.org/api/mcp \ |
46 | | - -n synapselayer/synapse-protocol \ |
| 89 | + "$SERVER_URL" \ |
| 90 | + -n "$QUALIFIED_NAME" \ |
47 | 91 | --config-schema "$CONFIG_SCHEMA" |
48 | | - |
49 | | -echo "" |
50 | | -echo "✅ Published!" |
51 | 92 | echo "" |
52 | 93 |
|
53 | | -# 6. Wait for propagation |
54 | | -echo "⏳ Step 4: Waiting 5s for registry propagation..." |
55 | | -sleep 5 |
| 94 | +# ── Step 4: Wait and verify ────────────────────────────────────── |
| 95 | +echo "⏳ Step 4: Waiting 10s for registry propagation..." |
| 96 | +sleep 10 |
56 | 97 |
|
57 | | -# 7. Verify listing |
58 | 98 | echo "🔍 Step 5: Verifying listing..." |
59 | | -curl -s "https://registry.smithery.ai/servers/synapselayer/synapse-protocol" | python3 -c " |
| 99 | +curl -sf "https://registry.smithery.ai/servers/@${QUALIFIED_NAME}" | python3 -c " |
60 | 100 | import json, sys |
61 | 101 | data = json.load(sys.stdin) |
62 | | -print(f' Name: {data.get(\"displayName\")}') |
63 | 102 | tools = data.get('tools', []) |
64 | | -print(f' Tools: {len(tools)} registered') |
| 103 | +print(f' Tools: {len(tools)}') |
65 | 104 | for t in tools: |
66 | 105 | print(f' ✓ {t[\"name\"]}') |
67 | | -print(f' URL: {data.get(\"deploymentUrl\")}') |
| 106 | +print(f' Description: {data.get(\"description\", \"N/A\")[:80]}...') |
68 | 107 | print() |
69 | | -expected = 13 |
70 | | -if len(tools) >= expected: |
71 | | - print(f'✅ All {len(tools)} tools published successfully!') |
| 108 | +if len(tools) >= $EXPECTED_TOOLS: |
| 109 | + print(f'✅ SUCCESS: All {len(tools)} tools published!') |
72 | 110 | else: |
73 | | - print(f'⚠️ Only {len(tools)}/{expected} tools detected — server may need redeployment.') |
| 111 | + print(f'⚠️ Only {len(tools)}/$EXPECTED_TOOLS tools — Smithery may need time to refresh cache.') |
| 112 | + print(f' Check: https://smithery.ai/servers/{\"$QUALIFIED_NAME\".replace(\"/\", \"/\")}\n') |
74 | 113 | " |
75 | 114 |
|
| 115 | +echo "" |
| 116 | +echo "📸 Registry state saved. If publishing succeeded, save the SMITHERY_API_KEY" |
| 117 | +echo " as a GitHub secret for automated future publishing:" |
| 118 | +echo "" |
| 119 | +echo " npx @smithery/cli auth whoami --full" |
| 120 | +echo " → Copy the API key" |
| 121 | +echo " → Go to github.com/SynapseLayer/synapse-layer/settings/secrets/actions" |
| 122 | +echo " → Add secret: SMITHERY_API_KEY = <your key>" |
| 123 | +echo " → Future publishes: Actions → 'Publish to Smithery Registry' → Run workflow" |
76 | 124 | echo "" |
77 | 125 | echo "🎉 Done! Verify at: https://smithery.ai/servers/synapselayer/synapse-protocol" |
0 commit comments