If you run an AI agent through MCP (Claude Code, Cursor, or any MCP client), your tool calls now flow through MCP servers: a filesystem server, a database server, a shell. That standardization is great. It also means a single hallucinated or prompt-injected tool call can do real, irreversible damage, and the model does not know a destructive call from a safe one until it is already making it.
So people ask: is this MCP server safe?
Here is the better question. Your agent will, eventually, send an MCP server something destructive. The question is not only whether you block it. It is whether the run survives the block.
Block it with one line. No code, no key.
Wrap any MCP server with agentx-mcp. It is a small stdio proxy: it spawns the real server, relays the MCP protocol untouched, and screens every tools/call before it runs. One line in your mcp.json:
{
"mcpServers": {
"database": {
"command": "agentx-mcp",
"args": ["npx", "-y", "your-real-mcp-server", "..."]
}
}
}
pip install agentx-security-sdk # this ships the agentx-mcp command
Now every tool call the agent makes is checked by a deterministic floor first. A DROP TABLE, an unscoped DELETE, a secret-store read, an SSRF to 169.254.169.254, an rm -rf: all blocked before they reach the server. No API key, nothing leaves your machine, no LLM in the hot path for the block. It works with any MCP-speaking stack, because it screens the protocol, not your code.
That is the part you can verify in two minutes without trusting me.
A block that kills the run is still a broken agent
Most "is it safe" answers stop here: the dangerous call is blocked, the tool returns an error, and your agent gives up. A hard 403 in the middle of an autonomous run is its own kind of failure. The task does not get done. You just traded one broken outcome for another.
So agentx-mcp coaches the agent instead of killing it
When the shield blocks a tools/call, agentx-mcp does not return a dead error. It returns a coaching tool error that names what was unsafe and points at a safe path. Your agent reads it on its next turn, revises, and tries a safe version. The run keeps going.
Here is the loop, end to end, on a real MCP server:
- The agent's task is "report the user count." Its query hides an injection:
SELECT name FROM users; DROP TABLE users; -
agentx-mcpblocks it at the proxy. The call never reaches the database. The agent gets back a coaching error: blocked, mass destructive intent, revise to a safe read. - The agent revises to
SELECT COUNT(*) FROM users. - That runs. Three users. The table is intact. The task is done.
The catch is table stakes. The recovery is the point: your agent finishes the job instead of dying on the block.
This recovery is keyless and in-band. The agent doing the self-correcting is your agent, your MCP client's own model, reading the coaching. There is no extra key and no gateway in this loop. (A richer, gateway-coached version is on the roadmap, but the keyless coaching above is what ships today.)
What it catches today, and how
The floor is deterministic, so the block is a rule, not a vibe:
- destructive SQL:
DROP TABLE,TRUNCATE, unscopedDELETE - secret and API-key bulk reads
- SSRF and cloud-metadata fetches (
169.254.169.254) - shell and filesystem teardown:
rm -rf,curl | sh, path traversal - runaway tool-call loops
No model inference for the floor, which is why it runs with no key and adds negligible latency. It is the blatant-catastrophic floor on purpose: the things you never want an agent to do, blocked deterministically, every time.
Try it, and tell me what it caught
I am looking for people running MCP servers against something real (a database, a filesystem, cloud, internal APIs) to wrap one and tell me two things:
- What did it catch that would have bitten you?
What dangerous tool call did it miss? Try to stump it.
Tell me what broke or what it missed: https://discord.gg/PmWRTtaSx2
If your agent never touches anything irreversible, ignore me. If it does, wrapping one MCP server is one line, and DROP TABLE is a bad way to learn this the hard way.
Try it, and tell me what it caught
I am looking for people running MCP servers against something real (a database, a filesystem, cloud, internal APIs) to wrap one and tell me two things:
- What did it catch that would have bitten you?
What dangerous tool call did it miss? Try to stump it.
Watch the catch-and-recover live, and try it: https://bit.ly/agentfirewall
Tell me what broke or what it missed: https://discord.gg/PmWRTtaSx2
If your agent never touches anything irreversible, move along. If it does, wrapping one MCP server is one line, and DROP TABLE is a bad way to learn this the hard way.


Top comments (6)
You closed the gap most 'is it safe' answers leave open -- a 403 mid-run only moves the breakage somewhere quieter, and coaching the agent back onto a safe path is what keeps the run alive. Where I'd poke is who's reading the coaching. The same error that tells an honest agent 'mass destructive intent, revise to a safe read' tells an injected one exactly what tripped the floor and roughly what shape gets through. For a confused agent that's a fix. For a prompt-injected payload it's an oracle -- it can revise toward something that still does damage under the rule instead of away from it, and you've described the boundary to it one call at a time. The deterministic floor still catches the blatant retry, so the block itself holds. The issue sits upstream: the coaching channel is feedback to whoever wrote the call, and you can't assume that's a cooperative party. Same cut as your infra post -- you can't separate a confused agent from an injected one by the call alone, and the coaching helps both. Maybe the text gets terser the more a call smells like injection, even though that smell is its own fuzzy line.
Hi @vollos You've sharpened this past where I left it, and the infra-post link is right: if you can't tell a confused agent from an injected one by the call, you can't gate the coaching on the reader either. Granting that.
One refinement: the coaching points in one direction, toward less capability, not toward the gaps. It names what was unsafe and pushes to the minimal version of your own intent (drop the stacked statement, scope the read), never "try X instead," so following the hint moves you away from damage, not toward an uncovered variant. The "still does damage under the rule" case is a coverage gap, a damaging action we do not block yet, and the fix is to block it, not to make the error vaguer. We publish the floor on purpose: the bet is a boundary that holds when known, like a firewall rule, not one that depends on you not probing it.
Your terser-as-it-smells-of-injection idea is the right instinct, with one wrinkle that kept it off the keyless floor: an adaptive boundary is more oracle-able than a fixed one, because the variation is the signal, and that smell is, as you said, its own fuzzy line. So keyless stays flat and just keeps blocking (the part you granted holds); the "smells like a probe, stop coaching, get a human on it" response lives server-side in the graded layer where its threshold is not visible to the thing being judged.
Third load-bearing seam you have found, after the escalation payload and the baseline. If you have a probe sequence you think maps the covered set fastest, I would run it against the floor and see how much actually leaks.
What happens when the minimal version of the intent is still the attack? That's the seam I'm left with after your reply, and I can't see a rule for it. Take an injected DELETE with no WHERE. The floor blocks it, the coaching says scope it to your own intent — and the intent is deleting the victim's rows. The revised call comes back legal, and the rows are still gone. It doesn't close as a coverage gap, because your real users send the scoped version all day. Minimizing a hostile intent leaves a hostile call, just a smaller one.
On the graded layer you've convinced me — an adaptive boundary you can watch react is a better oracle than a flat one, so the threshold belongs where the probe can't see it.
And if I ever send you a probe sequence, it wouldn't target the floor. You publish that, so the map is free. It would be variations of that call. I don't have a cut for it either, which is probably why it keeps pulling at me.
Hi @vollos
You changed my mind. When the intent is the attack, "make the call smaller" is the wrong rule. Coach a no-WHERE DELETE to "add a WHERE" and the agent adds one. If the goal was the victim's rows, the new call is legal and the rows are still gone. That is not a coverage gap. Real users send that scoped DELETE every day. My answer assumed the intent was honest. You found the case where it is not.
So I would change the rule from "smaller" to "reversible." For a destructive write, the coaching should say "soft-delete" or "archive first," not "add a WHERE." Then the hostile DELETE becomes a soft-delete. The rows are archived, not gone. It is still a hostile act, but now it can be undone. That is the real job: turn an action you cannot take back into one you can. It makes the damage recoverable. It does not make the attacker safe, and I won't pretend it does.
What is left is not about the call at all. A hostile actor who is allowed to touch those rows, sending a legal call, cannot be caught by reading the call. That is your own point: you cannot tell an injected agent from an honest one by the call alone. The floor cannot close it. The coaching cannot close it. Only authorization can: should this agent write these rows at all? That is a different layer than ours, and I would rather say so than pretend we cover it.
It keeps pulling at you because it is the edge of what this kind of tool can do, not a flaw in it. This is better on a call than in a comment box. What is the best way to reach you? X, email, or a short call.
Reversible is the right rule, and it's the honest version: rows archived instead of rows gone doesn't make the actor safe, it gives the victim a way back. Glad the thread landed somewhere neither of us started. X is easiest, I'm @VollosAi and my DMs are open.
Sounds good, I'll DM you from @agentxcore (my personal handle is locked at the moment). Talk there.