cratesio-mcp 0.2.1

MCP server for querying crates.io - the Rust package registry
Documentation
name: Deploy to Fly.io

on:
  # Deploy only when a release is cut: release-plz pushes a v{MAJOR}.{MINOR}.{PATCH}
  # tag (git_tag_enable in release-plz.toml), which is the same signal cargo-dist's
  # release.yml uses. This keeps the live server on the latest released version and
  # avoids bouncing the machine (and wiping in-memory MCP sessions, see #93/#97) on
  # every merge to main. Use the manual workflow_dispatch run for hotfix deploys.
  push:
    tags:
      - 'v[0-9]+.[0-9]+.[0-9]+'
  workflow_dispatch:

jobs:
  deploy:
    name: Deploy to Fly.io
    runs-on: ubuntu-latest
    if: github.repository == 'joshrotenberg/cratesio-mcp'
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Setup Fly CLI
        uses: superfly/flyctl-actions/setup-flyctl@master

      - name: Deploy to Fly.io
        run: flyctl deploy --remote-only --strategy immediate
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

      - name: Reap stale machines
        run: |
          echo "Destroying any stopped/suspended machines left from the deploy..."
          flyctl machines list --json | jq -r '.[] | select(.state != "started") | .id' | xargs -I{} flyctl machines destroy {} --force || true
          echo "Active machines after reap:"
          flyctl machines list
        env:
          FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

      - name: Verify deployment (health check)
        run: |
          echo "Waiting for server to be ready..."
          MAX_RETRIES=6
          RETRY_DELAY=10
          for attempt in $(seq 1 $MAX_RETRIES); do
            # Tolerate transient connect/TLS errors while the machine comes up
            # (a single early curl false-failed the v0.2.0 release run).
            HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" --max-time 10 https://cratesio-mcp.fly.dev/health || echo "000")
            echo "Attempt $attempt/$MAX_RETRIES: HTTP $HTTP_STATUS"
            if [ "$HTTP_STATUS" = "200" ]; then
              echo "Health check passed!"
              exit 0
            fi
            sleep $RETRY_DELAY
          done
          echo "Health check failed after $MAX_RETRIES attempts"
          exit 1

      - name: Verify deployment (MCP protocol)
        run: |
          MAX_RETRIES=3
          RETRY_DELAY=5

          for attempt in $(seq 1 $MAX_RETRIES); do
            echo "=== Attempt $attempt of $MAX_RETRIES ==="

            echo "Sending initialize request..."
            INIT_RESPONSE=$(curl -s -D /tmp/headers.txt -X POST https://cratesio-mcp.fly.dev/ \
              -H "Content-Type: application/json" \
              -H "Accept: application/json" \
              -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"deploy-check","version":"1.0"}}}')

            echo "Init response: $INIT_RESPONSE"

            SESSION_ID=$(grep -i "mcp-session-id" /tmp/headers.txt | cut -d' ' -f2 | tr -d '\r')

            echo "Session ID: $SESSION_ID"

            if [ -z "$SESSION_ID" ]; then
              echo "Failed to get session ID"
              if [ $attempt -lt $MAX_RETRIES ]; then
                echo "Retrying in ${RETRY_DELAY}s..."
                sleep $RETRY_DELAY
                continue
              fi
              exit 1
            fi

            sleep 1

            echo "Sending initialized notification..."
            curl -s -X POST https://cratesio-mcp.fly.dev/ \
              -H "Content-Type: application/json" \
              -H "Accept: application/json" \
              -H "MCP-Session-Id: $SESSION_ID" \
              -d '{"jsonrpc":"2.0","method":"notifications/initialized"}'

            sleep 1

            echo "Sending test tool call..."
            TOOL_RESPONSE=$(curl -s -X POST https://cratesio-mcp.fly.dev/ \
              -H "Content-Type: application/json" \
              -H "Accept: application/json" \
              -H "MCP-Session-Id: $SESSION_ID" \
              -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"search_crates","arguments":{"query":"tower"}}}')

            echo "Tool response: $TOOL_RESPONSE"

            if echo "$TOOL_RESPONSE" | grep -q '"result"'; then
              echo "MCP protocol verification successful!"
              exit 0
            else
              echo "MCP protocol verification failed - unexpected response"
              if [ $attempt -lt $MAX_RETRIES ]; then
                echo "Retrying in ${RETRY_DELAY}s..."
                sleep $RETRY_DELAY
                continue
              fi
              exit 1
            fi
          done