DEV Community

Antonio GM
Antonio GM

Posted on Originally published at agentshortlist.dev AI-assisted

We read 25 MCP servers. Here is what we found

This is a copy of an article first published on AgentShortlist, where the tables and cards live.

On 18 and 19 October 2026 we read the documentation and source of 25 MCP servers and wrote down, line by line, what each one says and does. Every line on a verified card carries a source and a review date. This article adds the 25 cards up.

It isn't a ranking or a security audit. It records what the projects document and what their code shows. Where we couldn't check something, the card says "not verified", and that turned out to be a big part of the result.

Read-only modes: documented in 5 of 25

Plenty of these servers can change data. Whether you can run them read-only is the question that moves the risk the most.

Documented read-only mode or recipe None found in the docs and source we read Not verified
GitHub MCP server, n8n-mcp, MongoDB MCP server, DBHub, pREST Playwright MCP, Desktop Commander, MySQL MCP server, Chrome DevTools MCP, Blender MCP, IDA Pro MCP, Talk to Figma MCP The other 13

"None found" means we didn't find one in what we read, not that none exists. For browser and design tools a read-only mode isn't really the right idea anyway. For the MySQL server it is, and there isn't one, so the limit has to live in the database user.

Telemetry: three on by default, and mostly silence

Chrome DevTools MCP collects usage statistics by default, and its performance tools can send trace URLs to Google's CrUX API. The Apify MCP server collects telemetry about tool calls by default, with Sentry error tracking. Blender MCP collects a minimal anonymous usage record by default; prompts, generated code and scene data are collected only if you opt in.

All three document how to turn it off. Two more projects, codebase-memory-mcp and context-mode, say they send nothing; we didn't verify that claim. For the other 20 we found no statement either way in the docs we read. What stood out to us is how few projects say anything about what leaves your machine.

Advisories: 40 published, none on the latest versions we checked

We matched the cards to packages on npm, PyPI and Go, but only when we could confirm the package belongs to the same repository. That gave 24 packages across 20 of the 25 cards, with 40 published advisories on OSV.dev in total. Half of those 20 cards have none.

We could check the latest version for 23 of the 24 packages, the npm and PyPI ones, and none of them is affected by a published advisory as of 19 October. We didn't check the latest version of the one Go module, the GitHub MCP server.

Card Published advisories
n8n-mcp 11
MCP reference servers (filesystem and git packages) 10
GitHub MCP server 4
MySQL MCP server 4
Chrome DevTools MCP, DBHub, Apify, Desktop Commander and Serena 2 each

Read the table with care. More advisories often just means a project is more used and more closely examined, not that it's worse. A package with none isn't proven safe. The practical takeaway is smaller: older versions are affected, so pin a version you've actually checked.

Upkeep: the issue backlogs differ a lot

Playwright MCP, Chrome DevTools MCP and Browser Tools MCP side by side: telemetry, read-only option, advisories, last push and open issues, checked on 19 October 2026

Open issues created before 20 July 2026, counted on 19 October:

Server Open issues Of which older than that date
Playwright MCP 4 0
n8n-mcp 64 16
Chrome DevTools MCP 173 46
GitHub MCP server 380 112
Desktop Commander 311 126
MySQL MCP server 6 1

A busy project collects more issues. The number tells you where to look, not what to conclude.

Projects that point somewhere else

A few READMEs say another option fits better, which is useful to read before you install:

  • The Playwright MCP README recommends Playwright CLI with Skills for coding agents, because it avoids loading large tool schemas and page snapshots into the model's context.
  • The awslabs/mcp README recommends the Agent Toolkit for AWS for production software built with coding agents, and calls it the successor to the servers in that repository.
  • The IDA Pro MCP README opens by recommending the official Hex-Rays server instead.
  • The MCP reference servers README says they are reference implementations, not production-ready solutions.

What to do with this

If a server can change data, look for its read-only option before anything else. Search the README for telemetry and set the opt-out if you want it. Pin versions and check them against advisories; the config checker does that in your browser. And treat "not stated" as a question to ask the maintainers, not as a yes.

Every card, with its sources, is on the verified cards page. You can compare servers in the live comparator or filter by what you need in the picker. If a card has a mistake, send us the primary source and we'll correct it.

Top comments (17)

Collapse
 
lin7c profile image
xcl •

The read-only finding is the most actionable part: 5 of 25 documented is low, but the MySQL example shows the fix is not always in the MCP layer itself. Enforcing the limit in the underlying credential, like a read-only database user or a narrowly scoped token, survives a server update or a misconfigured flag in a way that a README recipe does not. Did any of the five documented read-only modes enforce it that way at the credential level, rather than just filtering tools inside the server process?

Collapse
 
antoniogm82 profile image
Antonio GM •

Closest is DBHub: its README says it checks statements and runs them under the database's own read-only mechanism, so enforcement sits at the engine, not only in the server. n8n-mcp suggests a read-only API key as defence in depth. GitHub and MongoDB filter tools inside the server. That's what the docs say; we haven't tested any of it. Your point stands: a read-only credential is the layer that survives a bad flag or an update.

Collapse
 
heyvaldemar profile image
Vladimir Mikhalev •

One layer below the read-only credential: who holds it. In the sandbox I run, the records key exists as a Secret in two namespaces, the service's and the MCP server's, and admission refuses any agent pod that references a Secret in a volume or its environment.

The agent's one credential is a ServiceAccount token for the server's audience, valid ten minutes, bound to its pod and refused by the API server. A fooled agent can still misuse a tool it was granted. It can't carry the key out.

Thread Thread
 
antoniogm82 profile image
Antonio GM •

That is a useful extra layer: a read-only credential limits what a leaked key can do, but who holds it decides whether it can leak at all. Short-lived, pod-bound tokens and refusing secrets in the agent’s environment is a stronger setup than anything the cards we’ve read describe. Most documented setups put the credential in an env var in the client config. We can’t verify your sandbox from here, but “where the credential lives” is a good axis to add next to “what it allows”.

Thread Thread
 
heyvaldemar profile image
Vladimir Mikhalev •

You can check it from there: the refusal is a test in a public repo, not a description of one.

On every change, the e2e on a fresh kind cluster applies twelve planted manifests, among them a Secret in the environment, a Secret as a volume, a token with no audience and a token valid for a day. Each must be refused for the reason it names, and two compliant controls must be admitted, so the check can't pass by refusing everything.

The rules are ValidatingAdmissionPolicies, so the API server enforces them itself, with no webhook that can be down. kubernetes-ai-agent-sandbox

Thread Thread
 
antoniogm82 profile image
Antonio GM •

Thanks, that is the distinction I was missing: a refusal that is a test, not a description of one. I read the repo’s README and tree: two ValidatingAdmissionPolicies in manifests/admission.yaml, and an e2e on kind with twelve planted manifests, each refusal paired with compliant controls so it can’t pass by refusing everything. I haven’t run it or read the CEL rules, so on our side I would record it as “documented by the project, not tested by us”, with the link. The axis I’d add to our cards is yours: where the credential lives, separate from what it allows. If I got any detail wrong, tell me and I’ll fix it.

Thread Thread
 
heyvaldemar profile image
Vladimir Mikhalev •

Those details are right, and the credential axis belongs on the cards.

To move it from documented to tested, it is two commands on a laptop with kind and Docker:

make up
make test
Enter fullscreen mode Exit fullscreen mode

One trap first: make test fails on purpose on a machine with swap, because under gVisor a pod's memory limit then becomes its RAM plus unlimited swap. Docker Desktop has swap, so run it on a Linux host with swap off, as the CI runner does.

Thread Thread
 
antoniogm82 profile image
Antonio GM •

Thanks for checking the details, and for the swap warning: I’d have hit that on Docker Desktop. I’ll add the credential axis to our cards as “documented by the project” for now, with a link. I won’t run the kind test yet, since it needs a Linux host with swap off and I’d rather do that on an isolated machine than on a laptop. One question: may I cite your repo as an example of a refusal that is a test, not a description, in a future post? I won’t name you or the project unless you say it’s fine.

Thread Thread
 
heyvaldemar profile image
Vladimir Mikhalev •

Yes, cite it, and name the project and me; it is public so that it can be checked. Link a tag rather than main, so the refusal your readers check is the one you read: v1.2.0.

Until you run it yourself, the e2e workflow is a record you can point to. It runs on main every night on a public GitHub runner, and its log shows swapoff -a before the test starts.

Thread Thread
 
antoniogm82 profile image
Antonio GM •

Thanks, Vladimir. With your permission I will cite it by name. We have not run kubernetes-ai-agent-sandbox ourselves, so I will describe it as a record, not as something we tested: the repository's e2e workflow runs on a schedule on a public GitHub runner, and at tag v1.2.0 it runs sudo swapoff -a and prints /proc/swaps before and after, as you said. The last three scheduled runs on main passed. I will link the tag: github.com/heyvaldemar/kubernetes-...

Thread Thread
 
heyvaldemar profile image
Vladimir Mikhalev •

That description is accurate, and the permission stands.

Today the nightly runs and v1.2.0 are the same commit, 7a13a20. The schedule checks out main, so after the next merge "the last three runs passed" describes main, not the tag you link.

If the citation has to stay true, point at the push run on the tagged commit, from 20 October, instead of the nightly list. A tag stays put. A branch moves.

Collapse
 
antoniogm82 profile image
Antonio GM •

A correction to my DBHub answer: since then we matched a published advisory to its card (GHSA-mwwr-p57h-56pf). It says DBHub’s read-only mode did not prevent database writes before 0.22.6. So “the README says it enforces at the engine” did not hold for those versions. It’s the same lesson as your credential point: documented is not enforced, and a read-only database user would have covered it.

Collapse
 
gautamtalksdev profile image
Gautam K •

The pinning advice runs into how most people install these. A lot of README config snippets start the server with npx -y package-name and no version, so every client restart pulls whatever is latest. A version you checked against OSV only stays checked if the version sits in the client config itself.

On telemetry, "not stated" could become a measured line on the card: run each server once with outbound traffic logged and record which hosts it actually contacts. That would move several of the 20 silent ones from unknown to observed, without waiting on the maintainers.

Collapse
 
antoniogm82 profile image
Antonio GM •

Agreed on pinning: a version only stays checked if it's in the client config, which is why the checker flags npx without a version. The traffic-log idea is good. I'd label it as observed on one version with the tools actually exercised, so it doesn't claim more than it saw. Starting with the silent ones makes sense.

Collapse
 
raju_dandigam profile image
Raju Dandigam •

The “not verified” category matters: silence about telemetry or read-only mode is not evidence of absence. For the server cards, I'd separate a documented switch, source-level enforcement, and a negative write probe under a constrained credential. Your MySQL example shows the real boundary may be the database role, not the MCP server. Are runnable capability checks on your roadmap?

Collapse
 
antoniogm82 profile image
Antonio GM •

Yes, that's the next step: a documented switch, what the source enforces, and a write attempt under a constrained credential, each line labelled by how it was learned. We'll start with read-only on a handful of servers and publish the failures too. Not started yet, so no date.

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

the readme says read-only, the readme also says a lot of things