MCPTriage

Scan MCP servers and agent skills from a program or an AI agent. No API key. Static analysis only: nothing is installed or run. Submitted text is scanned in a temporary directory and deleted; only a hash, the verdict and content-free findings are stored.

Limits

Per IP address, shared by the API and the MCP endpoint: 60 requests per minute, 30 paste scans per hour and 10 package scans per hour. A result served from cache costs only the request. Bodies are capped at 1 MB. Package analyses run one at a time; when 5 are waiting, the API answers 503 with Retry-After: 30. Past a limit the answer is 429 with Retry-After in seconds.

Browsers. /api/v1/verdict and /openapi.json answer web pages on any site (CORS: Access-Control-Allow-Origin: *, with an OPTIONS preflight; no cookies or credentials are involved). The two scan routes and /mcp do not: a request with an Origin header that is not this service's gets 403. Calls from a server or a script send no Origin and are answered.

Endpoints

EndpointBodyReturns
POST /api/v1/scan{ "text", "filename"? }verdict, content-free findings, pinning advice for a config file, permalink
POST /api/v1/scan-package{ "ref" }: npm:<name>[@ver], pypi:<name>[==ver], github:<owner>/<repo>/<path>[@ref]verdict, findings, MCP pre-install checks (npm, PyPI), permalink; reused for 24 hours
POST /api/v1/verdict{ "ecosystem": "npm"|"pypi", "name", "version"? }the published catalogue verdict, or found:false (not a clean result)
GET /api/reputation-feed.jsonevery published MCP verdict, to match on your side without naming a server
GET /scan/:id.json · /package/:id.jsona scan's Evidence Pack; POST /api/verify recomputes its digest
POST /mcpJSON-RPC 2.0the MCP endpoint (below)

Examples

curl -s https://mcptriage-sandbox.crane.glick.run/api/v1/scan-package \
  -H 'Content-Type: application/json' \
  -d '{"ref":"npm:@modelcontextprotocol/server-filesystem"}'
curl -s https://mcptriage-sandbox.crane.glick.run/api/v1/scan \
  -H 'Content-Type: application/json' \
  -d '{"filename":".mcp.json","text":"{\"mcpServers\":{\"files\":{\"command\":\"npx\",\"args\":[\"-y\",\"@modelcontextprotocol/server-filesystem\",\".\"]}}}"}'
curl -s https://mcptriage-sandbox.crane.glick.run/api/v1/scan \
  -H 'Content-Type: application/json' \
  --data-binary @<(jq -Rs '{filename:"SKILL.md", text:.}' SKILL.md)
curl -s https://mcptriage-sandbox.crane.glick.run/api/v1/verdict \
  -H 'Content-Type: application/json' \
  -d '{"ecosystem":"pypi","name":"mcp-server-fetch"}'

MCP endpoint

https://mcptriage-sandbox.crane.glick.run/mcp is a remote MCP server (Streamable HTTP, no sign-in) with four tools: scan_package, scan_mcp_config, scan_skill and lookup_verdict. It answers protocol version 2026-07-28 and the earlier 2025-11-25, 2025-06-18 and 2025-03-26. It is stateless: no sessions, JSON responses, no GET stream. Remove secrets from env and headers before you ask it to check a config: they are not needed.

Claude Code

claude mcp add --transport http mcptriage https://mcptriage-sandbox.crane.glick.run/mcp

Claude Desktop and claude.ai: Customize › Connectors › Add › Add custom connector, enter https://mcptriage-sandbox.crane.glick.run/mcp, and choose no sign-in.

Cursor (.cursor/mcp.json in a project, or ~/.cursor/mcp.json)

{
  "mcpServers": {
    "mcptriage": {
      "url": "https://mcptriage-sandbox.crane.glick.run/mcp"
    }
  }
}

Any client, by hand:

curl -s https://mcptriage-sandbox.crane.glick.run/mcp -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -H 'MCP-Protocol-Version: 2025-11-25' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"lookup_verdict","arguments":{"ecosystem":"npm","name":"@modelcontextprotocol/server-everything"}}}'