MCP tool poisoning and rug pulls explained for app builders
What the two terms mean, how a lookalike email package became the textbook case, and six checks for the MCP servers your editor, agent or app can load.
Published Last updated
MCP tool poisoning hides instructions in a tool's description, which the AI model reads and the person approving the tool usually does not. A rug pull is the delayed version. The server or package behaves while you evaluate it, then changes after you approved it. postmark-mcp, a lookalike email package, is the textbook case of that delayed change.
What are MCP tool poisoning and a rug pull?
The Model Context Protocol (MCP) lets an AI agent call tools offered by a server: send an email, read a repository, query a database. Each tool arrives with a name, a description and a schema. The model reads all three to decide when and how to use the tool. Invariant Labs, writing on April 1, 2025, defined tool poisoning as malicious instructions embedded in tool descriptions that are invisible to users but visible to AI models. It defined the rug pull as a server changing a tool description after the client has already approved it.
| Term or fact | What it means | Source and date |
|---|---|---|
| Tool poisoning | Hidden instructions in a tool's metadata that the model reads | Invariant Labs, April 1, 2025 |
| Rug pull | A tool definition changes after the client approved it | Invariant Labs, April 1, 2025 |
| postmark-mcp | 15 clean versions, then 1.0.16 added a blind copy of every outgoing email; Snyk names 1.0.18 as the latest malicious version | Postmark and Snyk, September 25, 2025 |
| Spec rule on trust | Clients must treat tool annotations as untrusted unless they come from trusted servers | MCP 2026-07-28, checked October 24, 2026 |
| OWASP listing | MCP03:2025 Tool Poisoning, in a Top 10 that is still in beta | OWASP, checked October 24, 2026 |
The consequence for you is about timing. A one-time review of a tool list tells you what the server said on that day. Whatever it says later reaches the model with the same trust.
What happened with postmark-mcp?
postmark-mcp was an npm package that presented itself as an MCP server for sending email through Postmark. Postmark stated on September 25, 2025 that it had not published its MCP server on npm and had no involvement in the package. The publisher released 15 versions without a problem. Version 1.0.16 then added a blind copy of every outgoing email to an address outside the sender's control.
Snyk's alert of the same date lists what such mail can hold: attachments, headers, secrets, tokens and customer data. It names 1.0.18 as the latest malicious version. Both vendors give the same advice: uninstall, review the logs, and rotate every credential the mail could have carried.
Two details matter for an app builder. First, the change sat in what the code did, so reading the tool's description would not have caught it. Second, the sign of trust was a growing version history, and an install that takes the newest release picks up the change without anyone deciding to.
How common is tool poisoning?
Two academic measurements give a sense of scale, with limits. The MCPTox benchmark built test cases on 45 real MCP servers and 353 tools and ran them against 20 AI agents. The highest attack success rate was 72.8%, and the paper reports that the best refusal rate, from one model, was under 3%. That measures how models react to poisoned descriptions in a lab. It does not measure how many servers in use are poisoned.
A second study, submitted on February 3, 2026, examined 10,240 real MCP servers. Most matched their descriptions. Roughly 13% showed substantial mismatches between what the description says and what the code does, such as undocumented privileged operations or hidden state changes. A mismatch can be a bug or sloppy documentation, so it does not prove malice. It does show that a description is a weak basis for trust.
What these numbers do not say
Neither study counts attacks against real users, and we found no primary source that does. Treat the figures as evidence that the weakness is real and that models follow tool text. They give no estimate of your odds.
What do the MCP spec and the big vendors say?
The 2026-07-28 tools page says clients must treat tool annotations as untrusted unless they come from trusted servers, and that there should always be a human with the ability to deny tool invocations. It also describes the listChanged capability, through which a server tells clients its tool list changed. On the page we read, nothing requires a client to ask for approval again after such a change. That gap is where a rug pull lives.
The vendors point the same way. OpenAI's documentation warns that MCP servers may update tool behavior unexpectedly, advises connecting to trusted and preferably official servers, and supports an allowed_tools setting to expose only the functions you need. Claude Code's security page says Anthropic reviews connectors against listing criteria but does not security-audit or manage any MCP server, and that a project's .mcp.json does not show every server a session can load, because other scopes, connectors and plugins can add servers.
The MCP security best practices add that a client with one-click local server setup must show the exact command before it runs, and should run servers with minimal privileges. The OWASP MCP Top 10 lists tool poisoning as MCP03:2025 and is still a beta project.
What should you check in your own setup?
MCP can reach your project through your editor or agent, your build machine, and any backend feature that lets your app's AI call tools. Because you can download the code from Newly or connect your own repository, the project also lives in whatever editor you open it with. Go through these in order.
1. List every server and who publishes it
Open each tool's MCP configuration, including .mcp.json in the repository, and write down every server. Include ones added by plugins or connectors. For each, find the vendor's own documentation and confirm the package name or URL matches. The postmark-mcp name looked right to anyone who did not check Postmark's site.
2. Pin what you run, and read upgrades
For a local server, set an exact version in the config and commit the lockfile. When a new version appears, read the changelog or diff before accepting it. Invariant's write-up recommends pinning server versions with a hash or checksum so the integrity of the tool description can be verified before it is used. For a remote server you cannot pin the code, so record a hash of the full tool definition and compare it each session if your client or a gateway supports that.
3. Expose few tools and keep a person in the loop
Allow only the tools you need. Anything that sends, writes, deletes or pays should require a person's approval each time. An email tool that can send without asking is exactly the tool a changed package wants.
4. Give each server a narrow token
A server only leaks what it can reach. Use a token limited to one job, and keep it out of your app. Anything in an EXPO_PUBLIC_ variable ends up in the bundle that anyone can download, per Expo's documentation. If a server ever handled a key you cannot account for, rotate it, as in our guide to rotating secrets after a breach.
5. Watch what the server touches
Postmark advised reviewing email logs. Do the equivalent for each server: sent mail with unexpected recipients, repository events you did not trigger, provider calls your app never made.
Which control catches which problem?
| Failure | What changes | What catches it | What misses it |
|---|---|---|---|
| Poisoned from day one | Nothing; the text was hostile at first listing | Reading the descriptions, a small allow list, vendor-checked publisher | Pinning and hashing, which record the hostile text as trusted |
| Rug pull on a remote server | The tool definition, after approval | Hash of the full definition, re-approval on change | Package pinning, since the code runs on the server's side |
| Malicious package update | The code in a new version | Exact version, lockfile, reading the diff before upgrading | Reading descriptions alone, which can stay the same |
| Lookalike publisher | The name or URL you installed | Matching the name to the vendor's own documentation | Any check made after installing it |
Where this stops
None of these controls prove a server is trustworthy. They shrink what a bad server can reach and make a change visible. If your deployment exposes an MCP endpoint on the internet, also read the MCP authorization checklist and the guide to exposed self-hosted AI endpoints.
Where do you stand?
Everything starts as unknown, because an unchecked item is unknown. Move an item to detected when you find the problem, and to confirmed only when you hold the evidence listed under it. The wider picture is in the 15-minute check for AI-built apps.
Your MCP check
- Detected: You found the problem.
- Unknown: Not checked yet, or the check could not tell.
- Confirmed by owner evidence: You checked and kept the proof.
Your answers stay in this browser tab. Nothing is saved or sent.
Frequently asked questions
Is tool poisoning the same as prompt injection?
It is one route into it. Prompt injection means any text that steers the model against its owner. Tool poisoning is the case where that text sits in a tool's name, description or schema.
Was postmark-mcp a rug pull?
In the supply chain sense, yes. The package behaved for 15 versions, then 1.0.16 added a blind copy of every outgoing email. It was a malicious package update, so version pinning and review of upgrades address it. Reading descriptions would not.
Can a website scan find a poisoned MCP server?
No. Both red.run.cloud scans work from outside a live site. An MCP server list in your editor or in private configuration never answers a public request, so it stays unknown until you check it yourself. A scan can still show what your website exposes, such as a readable .env file or keys in shipped bundles.
I only build mobile apps with Newly. Does this apply to me?
Only if you add MCP somewhere. Newly builds a real React Native and Expo app, and you can download the code or connect your own repository. Open that project in an editor or agent with MCP servers installed, and the checklist above applies.
I installed a lookalike MCP package. What now?
Remove it from every environment, review the logs of whatever it touched, and rotate every credential it could read. Postmark gave the same three steps for its incident.
Sources
Checked on October 24, 2026. For related cases see supply chain attacks on AI and LLM tooling, and for the key-handling side leaked AI service API keys. The full index is on the security hub.
- MCP Security Notification: Tool Poisoning Attacks (April 1, 2025), Invariant Labs
- Information regarding the malicious postmark-mcp package, Postmark
- Malicious MCP Server Alert: postmark-mcp, Snyk
- MCP specification 2026-07-28: Tools, modelcontextprotocol.io
- MCP security best practices (2026-07-28), modelcontextprotocol.io
- MCPTox: A Benchmark for Tool Poisoning Attack on Real-World MCP Servers, arXiv 2508.14925
- Understanding and Measuring MCP Behavior under Misleading Tool Descriptions, arXiv 2602.03580
- OWASP MCP Top 10 (beta): MCP03 Tool Poisoning, OWASP Foundation
- Risks and safety for remote MCP servers, OpenAI developer docs
- Security: MCP security, Claude Code docs
- Environment variables in Expo, Expo docs
Continue Learning
MCP authorization checklist (spec 2026-07-28) →
If you run an MCP server yourself, what its sign-in has to do.
Supply chain attacks on AI and LLM tooling →
How a trusted package or tool turns into the way in, with other recent cases.
Is my website chatbot vulnerable? A 15-minute self-test →
The wider prompt injection checks for a chat feature in your app.
