We statically scanned the install manifests of 83 public MCP servers, up from our original 45. No fabricated stats, no cherry-picked worst cases: here's the real dataset, the real method, and where it does and doesn't generalize.
Every "MCP servers are insecure" claim we could find online was either a single anecdote or an unspecified vibe. So we built a small, honest dataset instead: originally 45 real public MCP servers, scanned the same way our open-source CLI scans anything, with the raw data and scan code left in the open. We've since expanded it to 83 servers with a second, independently-drawn sample, and the numbers barely moved, which is itself the most useful finding here.
Nine in ten of the servers we scanned ship with no signature or provenance metadata at all: nothing tying the package you install to a specific, verifiable source commit or build. Eighty-five percent install via an unpinned remote reference, most commonly npx -y <package> or pip install <package> with no version pin, which means the code that runs today can silently be different code tomorrow, with no action from the user. Four of the 83 manifests had a hardcoded credential sitting in the install config. That's a low base rate, but it's not zero, and if one of those four had been you, it wouldn't have felt like a low base rate.
A fourth heuristic, overbroad_tool_scope, hit 0 of 83. We're not reporting that as "MCP servers don't have overbroad tool scopes." See the limitations section below for why that number is close to meaningless here.
Why we're confident in these numbers: when we doubled the sample size with a second, independently-drawn batch of 38 new servers, the rates barely moved: missing provenance shifted +1.7 points, unpinned source -1.2 points, hardcoded credentials +0.4 points, and overbroad tool scope stayed at exactly zero. That stability across an independent second sample is stronger evidence than either dataset alone, it means the original N=45 numbers weren't a small-sample artifact.
We wanted a sample that wasn't just "servers we already suspected were bad," so we mixed a random community sample with a fixed, known-quality baseline. The dataset now spans two independently-drawn batches:
Full pipeline (unchanged between batches):
awesome-mcp-servers.md from the upstream repo.- [name](github-url) entry into a candidate record with category and any published install one-liner (256 total candidates).mcp.json-style manifest per server: used a published mcpServers JSON block from the README when one existed, otherwise fell back to tokenizing the documented install one-liner. No server was ever executed; every manifest is static config, nothing more.sentinel-scan mcp --manifest <file>, the actual open-source CLI, the same code path anyone running the public tool gets, against all 83 manifests.No server was contacted, executed, or sent data at any point, in either batch. This is static text analysis of publicly documented configuration that the projects' own maintainers published, which is consistent with normal scope and consent norms for a self-submitted community index.
| Finding class | v1 (N=45) | v2 (N=83) | v2 % |
|---|---|---|---|
| Missing provenance metadata | 41 / 45 (91.1%) | 77 / 83 | 92.8% |
| Unpinned remote source | 39 / 45 (86.7%) | 71 / 83 | 85.5% |
| Hardcoded credential | 2 / 45 (4.4%) | 4 / 83 | 4.8% |
| Overbroad tool scope | 0 / 45 (0.0%) | 0 / 83 | 0.0% |
The rates barely moved when the sample nearly doubled: missing provenance +1.7 points, unpinned remote source -1.2 points, hardcoded credential +0.4 points, overbroad tool scope unchanged at zero. We read that stability across an independently-drawn second batch as evidence the original headline numbers weren't a small-sample artifact.
We'd rather undersell this than get quoted for something it doesn't say:
overbroad_tool_scope and prompt-injection-in-tool-description detection need a server's actual advertised tool definitions, which usually aren't in a README's install snippet. Read the 0% figure as "not observed in this manifest-only slice," not "this doesn't happen in MCP servers."awesome-mcp-servers is curated but self-submitted, so it isn't a random sample of every MCP server actually deployed in production, just of what gets listed in one popular community index.final35.json + batch2_40.json), not the blended N=83.None of these findings require a zero-day or a sophisticated attacker. An unpinned npx -y install means the maintainer's next publish, or a compromised npm account, or a typosquatted package name, becomes your supply chain risk with zero warning. Missing provenance means you can't answer "is this the code the maintainer actually wrote" even if you wanted to check. A hardcoded credential in a public install manifest is just a credential in a public repo, MCP or not, and four out of 83 is exactly the kind of number that doesn't show up until it's someone's incident report.
None of this is exotic. It's the same supply-chain hygiene problem package ecosystems have had for a decade, showing up again in a newer wrapper. What's new here is that we've now checked twice, independently, and gotten the same answer.
The full dataset, all 83 built manifests across both batches, raw per-server scan output, and sampling provenance back to the source index, is public. We're not asking anyone to take the percentages on faith.
We ran this scan with sentinel-scan-cli, our free, open-source, zero-network static scanner for MCP manifests and LLM app prompt-injection surfaces. It's the same tool anyone can run against their own MCP config in a few seconds. If you maintain or install MCP servers, it's worth pointing at your own mcp.json, if only to see whether you're in the 85% or the 15%.
We're deciding whether to build something specifically for the provenance gap this data shows, install-time trust, drift detection on unpinned sources, or an audit trail for approvals. Tell us which one is a real problem for you →