MCPSafe.io
RegistryThreatsMethodologyDocsPricingScanSign in
⌘K
  • Getting Started
  • Quickstart

API Reference

  • Overview
  • POST /scan
  • GET /scan/:id
  • Private scans
  • Team & billing

Integrations

  • GitHub Actions
  • Cursor
  • Claude Code

Concepts

  • AIVSS Scoring
  • Findings
  • Severity Levels
  • CLI
  • Troubleshooting
  • FAQ
⌘K
MCPSafe.io

Security checks for MCP servers — public packages and private repos, fast or deep.

Legal

Privacy PolicyCookie PolicyTerms of ServiceSecurity disclosure

Resources

State of MCP SecuritySupportSystem statusMade in Germany 🇩🇪

© 2026 MCPSafe. All rights reserved.

GDPR — Privacy Policy

GitHub Actions

Block merges when an MCP server fails the MCPSafe security check.

←PreviousTeam & billingNextCursor→

Add MCPSafe to your CI/CD pipeline to automatically scan MCP servers on every pull request.

Basic scan step

# .github/workflows/mcp-security.yml
name: MCP Security Scan
 
on:
  pull_request:
    paths:
      - "claude_desktop_config.json"
      - ".mcp.json"
 
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Scan MCP server
        id: scan
        run: |
          SCAN_ID=$(curl -s -X POST https://api.mcpsafe.io/scan \
            -H "Content-Type: application/json" \
            -d '{"input": "@modelcontextprotocol/server-github"}' \
            | jq -r '.data.scan_id')
 
          echo "Waiting for scan $SCAN_ID..."
          for i in $(seq 1 20); do
            RESULT=$(curl -s https://api.mcpsafe.io/scan/$SCAN_ID)
            STATUS=$(echo $RESULT | jq -r '.status')
            if [ "$STATUS" = "complete" ]; then
              echo "result=$RESULT" >> $GITHUB_OUTPUT
              break
            fi
            sleep 3
          done
 
      - name: Check security grade
        run: |
          GRADE=$(echo '${{ steps.scan.outputs.result }}' | jq -r '.safety_grade')
          SCORE=$(echo '${{ steps.scan.outputs.result }}' | jq -r '.safety_score')
          echo "Security grade: $GRADE ($SCORE/100)"
          if [[ "$GRADE" == "D" || "$GRADE" == "F" ]]; then
            echo "::error::MCP server failed security check (grade $GRADE)"
            exit 1
          fi

Dynamic package from config

Scan every MCP server listed in claude_desktop_config.json:

- name: Extract and scan MCP servers
  run: |
    SERVERS=$(jq -r '.mcpServers | keys[]' claude_desktop_config.json)
    FAILED=0
    for SERVER in $SERVERS; do
      echo "Scanning $SERVER..."
      SCAN_ID=$(curl -s -X POST https://api.mcpsafe.io/scan \
        -H "Content-Type: application/json" \
        -d "{\"input\": \"$SERVER\"}" \
        | jq -r '.data.scan_id')
 
      # Wait for completion
      for i in $(seq 1 20); do
        RESULT=$(curl -s https://api.mcpsafe.io/scan/$SCAN_ID)
        STATUS=$(echo $RESULT | jq -r '.status')
        [ "$STATUS" = "complete" ] && break
        sleep 3
      done
 
      GRADE=$(echo $RESULT | jq -r '.safety_grade')
      echo "$SERVER: $GRADE"
      [[ "$GRADE" == "D" || "$GRADE" == "F" ]] && FAILED=1
    done
 
    [ $FAILED -eq 1 ] && exit 1
    echo "All servers passed."

Post a PR comment with results

- name: Comment scan results on PR
  uses: actions/github-script@v7
  with:
    script: |
      const result = JSON.parse(`${{ steps.scan.outputs.result }}`);
      const grade = result.safety_grade;
      const score = result.safety_score;
      const emoji = { A: "✅", B: "✅", C: "⚠️", D: "❌", F: "❌" }[grade];
      const body = `## MCPSafe Security Scan ${emoji}\n\n**Grade: ${grade}** (${score}/100)\n\n` +
        `| Severity | Count |\n|---|---|\n` +
        Object.entries(result.severity_distribution)
          .map(([k,v]) => `| ${k} | ${v} |`).join("\n") +
        `\n\n[View full report](https://mcpsafe.io/scan/${result.scan_id})`;
      github.rest.issues.createComment({
        issue_number: context.issue.number,
        owner: context.repo.owner,
        repo: context.repo.repo,
        body,
      });
✦

Use API keys for private repos

Set MCPSAFE_API_KEY as a GitHub secret and pass it as Authorization: Bearer ${{ secrets.MCPSAFE_API_KEY }} for authenticated requests and higher rate limits.