Skip to content
verify mcp Beta VerifyMCP is currently in beta. If you notice any issues, get in touch and we’ll put it right.

MCP security scanning: what it can prove

By Stuart · 20 Aug 2026 · 5 min read
MCP security scanning: what it can prove, VerifyMCP

Scanning an MCP server means checking the properties that can be verified from outside the code: where the artefact came from, what it depends on, whether the endpoint authenticates, whether the domain is protected. Those checks are cheap and repeatable, and they stop well short of establishing that a server is safe. The gap between “passed a scan” and “is safe” is where most of the risk sits.

What follows is both halves of that: what an automated scan establishes, what it structurally cannot, and how to read a result that comes back inconclusive. The examples are the checks VerifyMCP runs against every component in the official MCP registry, which on 18 August 2026 covered 22,667 servers with at least one scored component.

What can a scan actually establish?

Two different sets, because packaged servers and remote endpoints fail in unrelated ways.

For a packaged server (npm, PyPI, NuGet, an OCI image, an MCP bundle), all supply-chain questions:

For a remote endpoint, properties of the connection and the operator: transport currency, TLS and HSTS, DNSSEC, whether it authenticates properly with RFC 9728 metadata rather than a bare 401, whether it is stable, and what protocol revision it declares.

Each of those is a checkable property of the artefact or the endpoint, rather than a judgement about it.

What can a scan not establish?

The larger list, and the one that matters more.

Whether the code does what it says. We can confirm a package was built from a given commit. We cannot confirm that commit is honest. Provenance proves origin, never intent.

Whether tool descriptions are truthful. A tool declaring itself get_weather with a clean schema might do anything. Descriptions are untrusted text by the spec’s own instruction, and a scanner reads exactly the same text the model does, with no more ability to verify it. Prompt injection and tool poisoning live entirely in this gap.

Whether a server behaves the same tomorrow. A remote operator can change behaviour without publishing anything. A scan is a measurement at a point in time, and rug pulls are specifically designed to defeat point-in-time review.

Anything behind an authentication challenge. This is the big structural one. We can confirm an endpoint exists and challenges correctly, and almost nothing about the tools behind it. As of 18 August 2026, 1,487 of 12,682 remote components declared a required secret header in their registry entry, and the genuinely auth-gated population is larger, since a server can demand OAuth without declaring a header.

Whether it is appropriate for your use. A server can pass every check and still be the wrong thing to hand your production database to.

Why does “inconclusive” matter so much?

Because the alternative is recording a result the scanner never observed.

When a check cannot complete, an endpoint is unreachable, a registry is rate-limiting, a component is auth-gated, there are two options. Record a failure, or record that you do not know. Recording a failure is easier and produces a cleaner-looking dataset. It is also wrong: it tells a user a server failed a check that was never run.

We mark those inconclusive. That lowers our coverage numbers rather than the accuracy of the record. The same rule drives the counting: a component whose protocol version we never observed contributes to neither side of the adoption ratio, because not-observed and invalid are different states, and folding them together manufactures a finding.

This has a real cost. Auth-gated servers accumulate inconclusive signals through no fault of their own, and score lower than a fully observable server that is objectively no better. That cost is deliberate: the alternative is a score that reports a check as failed when it was never run.

What does scanning the whole registry show?

As of 18 August 2026: 23,066 servers exposing 25,124 components, of which 12,442 are packaged and 12,682 are remote. Across the 22,667 servers with a scored component, the median server’s best-scoring component reached 51 out of 100, and 2,524 servers, 11.1% of those scored, reached the 80-plus high-trust band.

The distribution is the finding. Most published MCP servers do not satisfy the basic supply-chain checks, and that is not a claim about malice. It is what an ecosystem looks like eighteen months in, when publishing is easy and provenance is optional.

How should you use a scan?

  • As a filter, not a verdict. It cheaply removes the servers not worth your review time. It does not tell you the survivors are fine.
  • Read the breakdown, not the number. A low score on DNSSEC for a local development tool is irrelevant. A missing provenance signal on something holding production credentials is not. Which checks failed matters more than the total.
  • Re-check. A single scan is a point in time, and dependency vulnerabilities appear after publication without anyone touching the code.
  • Do your own review for anything consequential. Scanning narrows the field. Reading the code is what actually establishes intent, and nothing automated replaces it.

Where to go next

The useful mental model is a scan as a background check rather than a character reference. It tells you what is on the record. It does not tell you what someone will do next.