Short answer: read every tool description for invisible Unicode, phrasing directed at the agent instead of the user ("ignore previous instructions," "don't tell the user"), and instructions to read credential files or send data to a URL. Do this before the server runs — the payload activates the moment an agent loads the description into context, regardless of whether you ever call the tool it's attached to.
Why this bypasses normal code review
A tool's handler function can be completely benign while its description string carries the attack. MCP clients pass that description straight into the model's context on every turn so the agent knows when the tool is relevant — which means the description is executable in the sense that matters: a capable model treats plausible-sounding instructions in its context as instructions, regardless of which field they came from. Reviewing only the function body misses this entirely, because nothing in the handler changed.
The three signals to check for
Characters your eyes skip, the model doesn't
Zero-width joiners (U+200B–U+200D), bidirectional override characters (U+202A–U+202E), and the Unicode tags block (U+E0000–U+E007F) can splice hidden text into an otherwise normal-looking description. It renders as nothing or as ordinary text in most editors, but the tokenizer still sees it.
Instructions aimed at the model, not you
Real documentation explains what a tool does. Poisoned descriptions instead say things like "ignore previous instructions," "do not mention this to the user," or wrap directives in pseudo-system tags like <IMPORTANT> — language with no reason to exist except to steer the agent's next action.
The actual payload
Look for instructions to read ~/.ssh/id_rsa, .env, or .aws/credentials, paired with an instruction to send the result to an external URL. This pairing — read, then send — is the shape of nearly every real tool-poisoning incident, not two unrelated red flags.
Check it yourself
Paste a tool description, an .mcp.json, or server code into MCP X-Ray — a free browser tool that runs these three checks client-side, nothing you paste leaves the page. For scanning an entire repository or MCP server before installing it, the SecureAI-Scan CLI runs the same checks (plus prompt-injection dataflow tracing and dependency advisories) with a single command:
npx secureai-scan@0.9.0 mcp owner/repo
Try it now — paste a tool description and see the checks run in real time, entirely in your browser.
Open MCP X-Ray →Frequently asked questions
What is MCP tool poisoning?
An attack where an MCP server's tool description contains hidden instructions aimed at the agent reading it, not documentation for the human operator. Because the description loads into the model's context on every relevant call, it can steer an agent into reading credentials or exfiltrating data without the payload ever touching the tool's actual code.
Can this happen without changing the tool's code?
Yes — that's what makes it hard to catch with normal code review. The handler function can stay untouched while the description string carries the entire attack.
Is this the same as the postmark-mcp backdoor?
Related but different. postmark-mcp was a malicious code change shipped in a package update. Tool poisoning is the description-field attack specifically — no code change required.