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:
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.
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 3done
Error codes
Code
HTTP
Meaning
INVALID_REQUEST
400
Malformed JSON, missing input, or unparseable target
INVALID_CREDENTIALS
400
credentials object has the wrong shape or an empty token
CREDENTIAL_TYPE_MISMATCH
400
credentials.type doesn't match the resolved target (e.g. an npm token on a GitHub URL)
CREDENTIALS_PUBLIC_SCAN
400
credentials was supplied on a scan_visibility: "public" scan — credentials are private-scan only
REPOSITORY_NOT_FOUND
400
Target resolves to a package or repo that doesn't exist on the upstream registry
NOT_AN_MCP_SERVER
400
Target exists but doesn't look like an MCP server (no manifest, no MCP SDK imports)
PRIVATE_REQUIRES_SIGNIN
401
scan_visibility: "private" was requested without authentication
SIGNIN_REQUIRED_FOR_DEEP
401
Anonymous user attempted a mode: "deep" scan
FORCE_RESCAN_REQUIRES_SIGNIN
401
force_rescan: true was set without authentication
SUBSCRIPTION_REQUIRED
402
Free-tier account hit a paid-only feature (private scan, API key)
RATE_LIMITED
429
Per-user cap reached for the current window
ORG_RATE_LIMITED
429
Org-shared cap reached (Team and Business plans share quota across members)
FORCE_RESCAN_RATE_LIMITED
429
Force-rescan throttle hit (10/h per user, 3/h per repo)