We audited 31 MCP server packages across npm and PyPI.

For every target, we ran two checks: a direct package control against the top-level package, and an installed-tree scan after package installation. The direct package control found 1 finding. The installed trees found 69.

Bar chart showing 1 direct package-control finding versus 69 installed dependency-tree findings.
Scan viewRecordsFindings
Direct package control311
Installed dependency tree3169

That gap is the point of this report. A top-level package can look clean while the code installed on disk carries known vulnerable dependencies. For MCP infrastructure, that distinction matters because servers are not passive packages. They are tool surfaces an agent can call.

This report stays aggregate and anonymized while notification decisions are handled. The evidence is still enough to act on: package-level checks are not a substitute for installed-tree scanning.

What we scanned

The population was intentionally mixed across official/reference implementations and community or vendor packages:

Population chart showing 21 npm targets and 10 PyPI targets.
SegmentTargets
Reference npm servers4
Reference PyPI servers3
Community/vendor npm servers17
Community/vendor PyPI servers7

That gives 31 targets total: 21 npm packages and 10 PyPI packages. Each target produced two scan records: one direct package control and one installed-tree scan after package installation.

The control is useful because it shows what a shallow package-level check is likely to see. The installed-tree scan is useful because it reflects what an operator actually places into the runtime environment.

What changed when we looked deeper

Across the installed trees, we found 54 unique vulnerabilities across 11 vulnerable targets. The severity distribution was:

Severity chart showing 2 critical, 34 high, 28 medium, 4 low, and 1 unknown installed-tree findings.
SeverityFindings
Critical2
High34
Medium28
Low4
Unknown1

The findings were concentrated. Five installed trees accounted for most of the visible risk:

TargetEcosystemTotalCriticalHighMediumLowUnknown
Target 1npm1608710
Target 2npm1418320
Target 3npm901710
Target 4PyPI814300
Target 5npm704300

These labels are anonymized. Named package evidence should go through direct notification before publication.

Why package-level checks miss this

MCP servers are distribution units. Installing one server can pull in dozens or hundreds of transitive dependencies. Vulnerability advisories often apply to those dependencies, not to the top-level server package.

A direct package check can return a true but narrow answer:

No known finding is attached to this top-level package.

That is not the same as:

The code installed for this server is free of known vulnerable dependencies.

The second question is the one operators need answered before they wire a server into an agent environment.

PyPI is part of the MCP surface

MCP scanning is easy to frame as an npm problem. That is incomplete. In this audit, 10 of 31 targets were PyPI packages. Any MCP inventory or scanner that omits PyPI misses a material part of the ecosystem.

Python packaging also carries different metadata. npm has package deprecation. PyPI has yanked releases. This run found no yanked-release signal in the scanned target versions, but the scanner now records that status explicitly so future runs do not lose it.

Registry metadata belongs in the evidence

The scan also captured registry-level status. One target in the population carried a deprecation signal in its registry metadata.

Deprecation is not the same thing as a vulnerability. It is still useful operational evidence. It can mean a package has moved, an install path has been retired, or users need a different run path to receive current updates.

Dependency risk is broader than known CVE or no known CVE. It also includes whether the package an operator installs is the package maintainers expect users to install today.

What operators should do

For MCP servers, the minimum useful baseline is:

  1. Inventory npm and PyPI targets.
  2. Install each target in an isolated work directory.
  3. Record the resolved version, not just the requested version.
  4. Scan the installed dependency tree.
  5. Keep the direct package check as a control.
  6. Capture registry metadata such as deprecation and yanked-release status.
  7. Treat lockfiles and generated environments as evidence.

The direct package check is still useful. It is fast and makes a good control. It just should not be the only scan standing between an agent and the tool code it will execute.

The takeaway

In this audit, direct package controls found 1 finding. Installed-tree scans found 69. For MCP, the operational unit is not the package name. It is the installed tree.

If you operate MCP servers, agent platforms, or internal tool registries, scan what actually gets installed.

Bindfort Research is expanding this work into a broader MCP ecosystem audit. If you maintain MCP servers or operate an agent platform and want to compare results privately, contact Bindfort Research at research@bindfort.com.