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

POST /scan

Submit a package or repository for security scanning.

Submit a package, repository, or MCP server for security scanning.

POST/api/v1/scan

Starts a new scan and returns the scan_id for polling or streaming.

Request

curl -X POST https://api.mcpsafe.io/api/v1/scan \
  -H "Content-Type: application/json" \
  -d '{"input": "@modelcontextprotocol/server-github", "mode": "fast"}'

For private scans or higher rate limits, authenticate with an API key:

curl -X POST https://api.mcpsafe.io/api/v1/scan \
  -H "Authorization: Bearer mcpsafe_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"input": "github:owner/repo", "mode": "deep", "scan_visibility": "private"}'

To scan a private GitHub repository, npm package, or PyPI package, pass a read-only token in the credentials object. The token is used once for the download and never logged or stored:

curl -X POST https://api.mcpsafe.io/api/v1/scan \
  -H "Authorization: Bearer mcpsafe_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "input": "github:my-org/private-mcp",
    "mode": "deep",
    "scan_visibility": "private",
    "credentials": { "type": "github", "token": "ghp_xxxxxxxxxxxxxxxxxxxx" }
  }'

The type field must match the input target — submitting an npm token against a GitHub URL returns 400 CREDENTIAL_TYPE_MISMATCH before a scan slot is consumed. See Private scans for token formats per registry, what's logged, and rotation guidance.

Response

{
  "success": true,
  "data": {
    "scan_id": "cAOvXioPjoEEP6g=",
    "canonical_id": "npm:@modelcontextprotocol/server-github@latest"
  }
}
FieldTypeDescription
scan_idstringUnique ID for this scan execution
canonical_idstringNormalised package identifier

Accepted input formats

The full reference (with every variant — npm, PyPI, GitHub, Docker, Official MCP Registry) is at Getting Started — Input formats. Common examples:

@modelcontextprotocol/server-github     # npm scoped
pypi:requests==2.31.0                    # PyPI pinned
github.com/owner/repo                    # GitHub HEAD
docker:nginx:1.27-alpine                 # Docker tag
io.github.punkpeye/fastmcp               # MCP registry

Checking progress

After receiving a scan_id, either:

Option A — SSE stream (recommended for real-time UI):

const es = new EventSource(`https://api.mcpsafe.io/scan/${scanId}/stream`);
es.onmessage = (e) => {
  const event = JSON.parse(e.data);
  if (event.type === "scan_complete") {
    console.log(event.scan_result);
    es.close();
  }
};

Event types: mode_selected, cache_hit, stage_started, stage_completed, rule_started, rule_completed, judge_verdict (deep scans), scan_complete, scan_failed. See GET /scan/:id for the full event schema.

Option B — poll (for CI/CD):

# Poll until status === "complete"
while true; do
  STATUS=$(curl -s https://api.mcpsafe.io/scan/$SCAN_ID | jq -r '.status')
  [ "$STATUS" = "complete" ] && break
  sleep 3
done

Error codes

CodeHTTPMeaning
INVALID_REQUEST400Malformed JSON, missing input, or unparseable target
INVALID_CREDENTIALS400credentials object has the wrong shape or an empty token
CREDENTIAL_TYPE_MISMATCH400credentials.type doesn't match the resolved target (e.g. an npm token on a GitHub URL)
CREDENTIALS_PUBLIC_SCAN400credentials was supplied on a scan_visibility: "public" scan — credentials are private-scan only
REPOSITORY_NOT_FOUND400Target resolves to a package or repo that doesn't exist on the upstream registry
NOT_AN_MCP_SERVER400Target exists but doesn't look like an MCP server (no manifest, no MCP SDK imports)
PRIVATE_REQUIRES_SIGNIN401scan_visibility: "private" was requested without authentication
SIGNIN_REQUIRED_FOR_DEEP401Anonymous user attempted a mode: "deep" scan
FORCE_RESCAN_REQUIRES_SIGNIN401force_rescan: true was set without authentication
SUBSCRIPTION_REQUIRED402Free-tier account hit a paid-only feature (private scan, API key)
RATE_LIMITED429Per-user cap reached for the current window
ORG_RATE_LIMITED429Org-shared cap reached (Team and Business plans share quota across members)
FORCE_RESCAN_RATE_LIMITED429Force-rescan throttle hit (10/h per user, 3/h per repo)
SCAN_START_FAILED500Internal error starting the scan pipeline
←PreviousOverviewNextGET /scan/:id→