The whole flow is one loop — submit, wait, read the verdict — and the certificate detail is what turns a score into an explanation: a login page whose certificate names a different organisation is the kind of thing a number alone will not tell you.
A Python server over the public ScanMalware.com API. It submits a URL for scanning, follows the scan to completion, and returns the status, risk score and the indicators behind it, along with TLS and certificate detail, screenshots and previous scans.
- A URL submitted for scanning and followed until it completes (`submit_scan`)
- The verdict: status, risk score and the top indicators
- The scan's AI analysis and its screenshot resource, when the risk warrants a closer look
- Past scans searched by term, each with its identifier, status, risk score and URL
- TLS details and the certificate PEM for a scan — issuer, subject, validity dates and alternative names
- Search tools that require at least one filter, so an empty query returns a validation error rather than everything
Nothing for the public endpoints. The hosted endpoint is `https://mcp.scanmalware.com/mcp` over Streamable HTTP; a GET without the MCP accept headers returns 406, which is expected. To run it yourself, `pip install .` on Python or the Docker image, with `MCP_TRANSPORT`, `MCP_HOST` and `MCP_PORT` set — and `MCP_AUTH_TOKEN` if you want your own instance to demand a bearer token from connecting clients. `SCANMALWARE_BEARER_TOKEN` is only for the parts of the upstream API that ask for one. Two limits worth knowing: downloads are capped by `SCANMALWARE_MAX_DOWNLOAD_BYTES` at 10485760 bytes by default, and private network targets are refused unless `SCANMALWARE_ALLOW_PRIVATE_TARGETS` is turned on. A few upstream endpoints are disabled and left out of the tool list entirely.
One command — https://mcp.scanmalware.com/mcp
