Measured with mcp-surface-scan, against the npm tarballs people actually install. Updated 1 October 2026.
Every MCP server runs with your privileges. The thing that declares it is one JSON blob: a package name, a few arguments, maybe a URL, maybe a token. Nobody reads it, because it is written as arguments. So I read it mechanically — and then read the code behind it.
| server | run commands | write files | read files | network out | env creds | listens | SQL |
|---|---|---|---|---|---|---|---|
| desktop-commander | ✓ | ✓ | ✓ | ✓ | ✓ | ||
| mcp-server-kubernetes | ✓ | ✓ | ✓ | ✓ | |||
| firecrawl-mcp | ✓ | ✓ | ✓ | ✓ | ✓ | ||
| server-everything | ✓ | ✓ | ✓ | ✓ | |||
| server-filesystem | ✓ | ✓ | |||||
| server-memory | ✓ | ✓ | ✓ | ||||
| server-gdrive | ✓ | ✓ | ✓ | ||||
| server-github | ✓ | ✓ | |||||
| server-slack | ✓ | ✓ | |||||
| server-brave-search | ✓ | ✓ | |||||
| server-google-maps | ✓ | ✓ | |||||
| server-puppeteer | ✓ | ||||||
| server-postgres | ✓ | ||||||
| server-redis | |||||||
| playwright-mcp |
Fifteen servers, as published on npm. An empty cell does not mean the server lacks that capability — it means this regex pass did not find it in a minified build artifact. Read the table as "what is visibly there", never as a clean bill of health.
1. Credentials live in the config, and that is the ecosystem default.
Ten of fifteen read credentials from the environment. MCP client configs
(claude_desktop_config.json, .mcp.json, .vscode/mcp.json) are
ordinary files: they sync, they end up in dotfiles repos, and they are one command away from being
listed.
2. Capabilities are granted per server, not per capability.
desktop-commander has five families at once, and mcp-server-kubernetes runs commands
and writes files while holding your cluster credentials — mounting it grants all of that at once — because mounting it
grants all five. There is no layer that says “read this directory but do not run commands”.
The scope is binary: the server exists, or it does not.
3. The broadest server is also the most useful one.
That is not a criticism — terminal and filesystem access are the value. The problem is that
the tradeoff is not shown anywhere. The config says "command": "npx"; nothing in that
line tells you that you just handed over your shell.
Capability-level authorisation is not impossible — three servers here show it working:
file:// and restricts file
access to the workspace root by default; you have to pass
--allow-unrestricted-file-access to widen it. Its docs also say plainly that
--allowed-origins “does not serve as a security boundary” — which is
more honest than most.kubernetes-readonly mode.All three are opt-in or opt-out, never the default. That is the whole gap: the mechanisms exist, the defaults do not use them.
mss does).npx -y), path
arguments that mean everything (/), --privileged, plaintext
endpoints. Not “be careful with third-party servers”.pip install mcp-surface-scan npm pack @modelcontextprotocol/server-filesystem && tar xzf *.tgz mss ./package --source-only
The tool is regex-based on purpose: a reviewer’s first pass. It points at places; it never
claims a specific call is exploitable. Severity is deliberately uneven — “runs a local
process” is info, because that is what MCP servers do. The findings are the parts
you can change.