a fancy canvas mcp server!
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: add deploy workflow

+100
+81
.github/workflows/deploy.yaml
··· 1 + name: Deploy Canvas MCP 2 + 3 + on: 4 + push: 5 + branches: 6 + - main 7 + workflow_dispatch: 8 + 9 + jobs: 10 + deploy: 11 + runs-on: ubuntu-latest 12 + steps: 13 + - uses: actions/checkout@v3 14 + 15 + - name: Setup Tailscale 16 + uses: tailscale/github-action@v3 17 + with: 18 + oauth-client-id: ${{ secrets.TS_OAUTH_CLIENT_ID }} 19 + oauth-secret: ${{ secrets.TS_OAUTH_SECRET }} 20 + tags: tag:ci 21 + use-cache: "true" 22 + 23 + - name: Configure SSH 24 + run: | 25 + mkdir -p ~/.ssh 26 + echo "StrictHostKeyChecking no" >> ~/.ssh/config 27 + 28 + - name: Deploy to server 29 + run: | 30 + ssh canvas-mcp@terebithia << 'EOF' 31 + cd /var/lib/canvas-mcp/app 32 + git fetch --all 33 + git reset --hard origin/main 34 + bun install 35 + sudo /run/current-system/sw/bin/systemctl restart canvas-mcp.service 36 + EOF 37 + 38 + - name: Wait for service to start 39 + run: sleep 10 40 + 41 + - name: Health check 42 + run: | 43 + HEALTH_URL="https://canvas.dunkirk.sh/health?detailed=true" 44 + MAX_RETRIES=6 45 + RETRY_DELAY=5 46 + 47 + for i in $(seq 1 $MAX_RETRIES); do 48 + echo "Health check attempt $i/$MAX_RETRIES..." 49 + 50 + RESPONSE=$(curl -s -w "\n%{http_code}" "$HEALTH_URL" || echo "000") 51 + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) 52 + BODY=$(echo "$RESPONSE" | sed '$d') 53 + 54 + if [ "$HTTP_CODE" = "200" ]; then 55 + STATUS=$(echo "$BODY" | jq -r '.status // "unknown"') 56 + 57 + if [ "$STATUS" = "healthy" ]; then 58 + echo "✅ Service is healthy" 59 + echo "$BODY" | jq '.' 60 + exit 0 61 + elif [ "$STATUS" = "degraded" ]; then 62 + echo "⚠️ Service is degraded but responding" 63 + echo "$BODY" | jq '.' 64 + exit 0 65 + else 66 + echo "⚠️ Service returned HTTP 200 but status is: $STATUS" 67 + echo "$BODY" | jq '.' 68 + fi 69 + fi 70 + 71 + echo "❌ Health check failed with HTTP $HTTP_CODE" 72 + echo "$BODY" 73 + 74 + if [ $i -lt $MAX_RETRIES ]; then 75 + echo "Retrying in ${RETRY_DELAY}s..." 76 + sleep $RETRY_DELAY 77 + fi 78 + done 79 + 80 + echo "❌ Health check failed after $MAX_RETRIES attempts" 81 + exit 1
+19
src/index.ts
··· 51 51 }, 52 52 }, 53 53 54 + // Health check endpoint 55 + "/health": { 56 + GET(req: Request) { 57 + const url = new URL(req.url); 58 + const detailed = url.searchParams.get("detailed") === "true"; 59 + 60 + if (detailed) { 61 + return Response.json({ 62 + status: "healthy", 63 + timestamp: new Date().toISOString(), 64 + version: "1.0.0", 65 + uptime: process.uptime(), 66 + }); 67 + } 68 + 69 + return Response.json({ status: "healthy" }); 70 + }, 71 + }, 72 + 54 73 // MCP Protocol endpoint (Streamable HTTP) 55 74 "/mcp": { 56 75 async POST(req: Request) {