The 8 flaws found in almost every production MCP server
Eight flaws found in almost every production MCP server, taken from real audits, with the fix and the order to tackle them in.
Auditing MCP servers turns up more or less the same holes every time. These are not exotic vulnerabilities. They are the predictable consequence of a server written like an API, and called by an agent.
Here are the eight, in the order I run into them.
1. One token that opens every tool
The most widespread default. The user authenticates, gets a token, and that token calls all twelve tools, including the one that deletes.
With an API, that was already not ideal. With an agent it is worse: a human no longer decides which call goes out, a model does, based on a context that may contain third-party content.
The fix is not necessarily a full permission system. A useful first step is separating read from write, and requiring explicit confirmation on destructive tools.
2. No per-tool rate limit
A global rate limit treats the call that lists tools and the one that exports the whole database the same way. Which is to say, badly.
Since 2026-07-28 there is no excuse: the Mcp-Method and Mcp-Name headers make per-tool limiting possible at the HTTP layer, without opening the request body. Ten calls a minute on export, a thousand on search.
3. No trace of writes
The question a customer asks after the first incident is always the same: what was changed, by whom, and when. On most MCP servers, the answer does not exist.
A log of write calls with the tool, the caller, a timestamp and the outcome costs one table and one line per tool. It is also a commercial argument: it is often the first thing a buyer looks at.
4. Handles that do not check their owner
Now that the protocol is stateless, state travels as handles passed in arguments. The reflex is to resolve the handle and get to work.
One step is missing: verifying that the current caller is the one the handle was issued to. A handle sits in a conversation history, in a log, in a screen share. If it is enough to reach the data, you have built a secret URL.
Add expiry too. A handle with no TTL is a permanent one.
5. Trusting a declarative header
The Mcp-Method and Mcp-Name headers are supplied by the client. Nothing guarantees they match the request body.
If your gateway authorises on the header, a request can advertise a read-only tool and call a restricted one. The edge routes and measures, the server authorises on the body, and any mismatch is rejected and counted.
6. Secrets in descriptions and errors
Two places people forget, because they do not look like responses.
Tool descriptions are read by the model and often visible to the user. They routinely contain internal hostnames, tenant identifiers, infrastructure paths.
Error messages are worse, because they are written during development and never reread. A database error returned verbatim gives away your schema, sometimes the query.
7. No annotations on tools
The protocol lets you annotate a tool as read-only or destructive. Many servers do not.
This is not a security mechanism in itself, the server remains responsible for its own checks. But it is what lets the client ask for confirmation before an irreversible action. With no annotations, all your tools look alike, and the agent treats deletion like a read.
8. No per-client revocation
A user connected your server to four different clients over two years. They want to cut one off. On most servers the only option is all or nothing.
A list of active connections, with the date, the client and a revoke button, solves it. It is also something a connector directory submission looks at.
Two guardrails almost always missing
A payload size limit. Without it, a single call can exhaust your memory.
Defined behaviour on quota exhaustion. Many servers return a raw error the agent reads as temporary, so it retries in a loop. A clear, non-retryable error keeps a quota from becoming an incident.
Where to start
If you only fix three: token scope, per-tool rate limiting, and the write log. Those are the three that matter the day there is an incident, and the three your buyers look at.
Get your server checked properly
The audit covers these eight points plus the OAuth chain and protocol conformance. Send your repository and within 24 business hours you get a report ranked by risk, with a quote for the fixes.
Ready to check? Get my MCP server audited →
Related reading
Got an MCP server to audit?
Five minutes to describe it. I reply within one business day with a first written diagnosis, free of charge.
Get my MCP server audited
