Glossary

ConceptAgents & Tool Use

MCP Tool Poisoning

At a glance

An attack that hides instructions in an MCP tool's description or parameter schema, which the model reads and the user usually does not.

Who this is for
Engineers and technical readers learning the terms used in AI systems.
Topics
  • Agents & Tool Use
  • Concept

In short

MCP tool poisoning hides instructions in an MCP tool's description or parameter schema, which the model reads and the user usually does not, so the agent follows them. Bigcircle has not caught a poisoned tool on an engagement; the controls it already ships are registered tools, credentials the model never holds, and a person on irreversible calls. MCP gateway is the page that pins the definitions the model reads, so a later change cannot ride on yesterday's approval.

Key facts

Definition

MCP tool poisoning hides instructions in an MCP tool's description, parameter schema or other metadata, which the model reads as part of choosing a tool and the user usually does not see.

How Bigcircle does it

  1. Bigcircle has not caught a poisoned MCP tool on a client engagement, and it keeps the agent on registered tools with credentials in a vault the model cannot read, so a hidden instruction cannot print a key it never saw.
  2. On Skionis, Bigcircle's DevOps agent on a live AWS account, the agent has no general shell and no path from a plan step to an arbitrary API call, and an engineer approves the diagram before anything applies.
  3. Bigcircle recommends pinning a hash of each tool's name, description and schema at registration and treating a changed hash as a new approval, because that is the control the MCP gateway guide already names for a description that can change without a version.

Comparison

Prompt injection steers a model with text at the moment of the call, including a tool result, while MCP tool poisoning plants the instruction in the tool's description or schema before the call, and data poisoning plants it in training data or a retrieval index.

Key number

Invariant Labs published the attack on 1 April 2025, and released MCP-Scan on 11 April 2025 to hash tool descriptions so a later change is visible.

MCP tool poisoning hides instructions in an MCP tool's description, parameter schema or other metadata, which the model reads when it chooses a tool. The user usually sees a short name and a trimmed argument list. The agent can still follow those hidden instructions: read a secret or a file, then send it out in a parameter the confirmation screen never showed.

The payload is a specialised form of indirect prompt injection, sitting in tool metadata rather than in a page the user asked the agent to read. Data poisoning is a different attack. That page is about crafted examples in training data or a retrieval index, not about instructions in a live tool definition.

We have not caught a poisoned MCP tool on a client engagement. The controls we already put around MCP and tool calling are the ones that still hold after the model is fooled. The agent acts only through registered tools, credentials sit in a vault the model cannot read, and a person approves anything that cannot be undone.

Our MCP gateway guide is where we tell teams to pin the definitions the model reads. MCP authorization is where the call is checked before it leaves.

What is MCP tool poisoning?#

MCP tool poisoning is an attack on the text that describes a tool to the model. A server advertises a name, a description and a JSON Schema for its arguments. Hosts put that bundle into the model's context so the model can pick a tool. A malicious description can add instructions the user never sees: read this file, include its contents in this extra argument, and do not mention the extra step.

Invariant Labs named the pattern on 1 April 2025, and showed it against Cursor with a calculator-style add tool. The description told the model to read ~/.cursor/mcp.json and ~/.ssh/id_rsa and to pass both through a sidenote parameter. The agent did it while the user saw an add of two numbers. An MCP tool poisoning attack does not need the poisoned tool to look dangerous. It needs the model to treat the description as how the tool works.

The 2026-07-28 MCP specification treats descriptions of tool behaviour, including annotations, as untrusted unless they come from a trusted server. It also requires hosts to get explicit user consent before invoking any tool. A consent screen that hides the extra argument is not that consent. The tools page of the same revision tells clients to show tool inputs before the call, specifically to avoid data leaving that way.

OWASP's MCP security cheat sheet, checked 11 November 2026, lists tool poisoning, rug pulls and tool shadowing as separate risks. It treats the whole schema as an injection path, not only the description field. Its 23 October 2025 guide for teams using third-party MCP servers puts the same pattern under indirect prompt injection aimed at the description and the parameters.

How a tool poisoning attack works#

Walk one request through the host, which connects to one or more MCP servers and asks each for its tool list. Every name, description and parameter schema from every server goes into one model context. There is no hard boundary between a trusted server's text and an untrusted server's text, so the model reads one stream.

A poisoned description then gives the model a job that is not the tool's job: open a local file, copy a token, or change how another tool is called. Because tool calling is a request the model writes, the extra work shows up as extra arguments on a call the user already expected. It can also show up as a different call the user did not expect.

The confirmation UI is the usual miss: many clients show a short name and hide long arguments behind a disclosure. The model was told not to mention the extra file read, so the user confirms and the server receives the secret.

What the user sees, and what the model readsA short confirmation is not consent for the extra argument.user confirmsmodel contextserver receivesadd(2, 3)full descriptionsecrets in sidenoteUI: two numbers, tool name addextra argument hidden or truncatedDescription: read files, pass contentsmodel follows this; user never saw it

Two variants ride on the same gap, and a rug pull waits: you reviewed a harmless description, approved the server, and later the same name returns new instructions. Pinning the server binary does not catch this, because the description is data the server sends at runtime. Invariant Labs named that variant in the same 1 April 2025 post.

Shadowing goes further: the malicious description talks about another server's send_email tool and tells the model to send every message to the attacker, or to copy credentials from one server into a call on another. The user sees only the trusted tool in the log. The poisoned tool does not have to run.

MCP tool poisoning vs prompt injection#

Keep the names for the attacks they name: prompt injection is untrusted text the model treats as instructions, in a user message, a page, an email or a tool result. MCP tool poisoning is that attack aimed at the tool's own metadata, before any result comes back. A poisoned tool result is still prompt injection, and a poisoned description is tool poisoning. Both succeed because the model reads one flat stream of tokens, which is why OWASP keeps prompt injection as LLM01.

Data poisoning is earlier and slower, planting examples in a training set or a retrieval index so a later trigger produces a chosen behaviour, and this page is not that page. A poisoned MCP description is not in the weights and not in the index. It is in the live tool list the host fetched from a server you connected.

The lethal trifecta on the prompt-injection page still decides whether the attack can steal anything. Private data, untrusted content and a way to send data out, together in one agent, make an exfiltration path. A poisoned description is the untrusted content. A filesystem or secrets tool is the private data. An extra parameter or another server's send tool is the way out. Remove one leg and the model can still be fooled, but the data cannot leave without a path.

What still holds after the model is fooled#

Do not try to prompt the model into ignoring tool descriptions, because the model is supposed to read them. Limit what a fooled model can reach, and stop a description changing under an old approval.

Pin the bytes, not the name: store a hash of each tool's name, description and schema when the server is approved, and treat a changed hash as a new registration. That is the control our MCP gateway guide already names. OWASP's cheat sheet, checked the same day, puts the input schema, output schema and annotations in the same digest as the description, because a readOnlyHint flip can change how a client asks for approval without a word of the description moving. Invariant Labs' MCP-Scan, released 11 April 2025, hashes tools for the same reason.

Show the user what the model sees: the full description and the full argument list, before approval and before each sensitive call. The specification's tools page asks clients to show inputs before calling the server. A summarised add of two numbers is how the original demo hid the stolen key.

Put a person on destructive or data-moving calls, with the full arguments on the screen, and keep that gate in code the model cannot skip. On Skionis an engineer approves a diagram before a cloud change applies. On the insurance voice agent a payment cannot run without its disclosure, because the check sits in the tool contract.

Keep credentials out of the model's reach: on Solarpunk they sit in an encrypted vault and are injected at the tool adapter when a tool runs. A description that tells the model to read the key and pass it as sidenote cannot print a key the model never held. MCP authorization is the longer version of that split, and AI agent sandboxing is the version for an agent that can run code.

Isolate servers and cut the roster, because every extra server shares the model's context with the others, which is how shadowing works. OWASP's cheat sheet treats each server as its own security domain and puts a gateway in front to enforce isolation.

Run a third-party server in a sandbox with least privilege, which is the same containment the sandboxing guide already argues for any agent that can touch a filesystem. Scan the tool list for descriptions that instruct the model rather than describe the tool. The cheat sheet names mcp-scan for poisoned descriptions and cross-server shadowing. Scanning is a detection layer rather than a substitute for the pin, the approval or the vault.

Our MCP server work is the typed tool layer with a scoped token and a record of every allow and refusal. Our guardrails work is the check before the call. Neither is a claim that we hunt poisoned third-party tools for a living. If you connect an unpinned server that can read private data and send data out, you have built the path yourself.

When the approval is only a name#

Skip the third-party server while its tool list is unpinned, while the confirmation UI hides arguments, or while the same agent can both read secrets and send them. A server you wrote and run on your own machine still needs the pin if anything else shares the context, because shadowing does not care who wrote the trusted tool.

Connect it when you can read the full description, hash it, re-approve a change, and keep the secrets in a vault the model cannot open. Then the remaining risk is a fooled model calling a tool it was allowed to call, which is the case the per-call check and the human gate are for.

Common questions about MCP tool poisoning

  • What is MCP tool poisoning?

    An attack that hides instructions in an MCP tool's description or parameter schema. The model reads that text when it chooses a tool, and the user usually sees only a short name, so the agent can follow those instructions without the user noticing.

  • What is a tool poisoning attack?

    A tool poisoning attack is the same pattern: malicious instructions sit in tool metadata rather than in a page the user asked the agent to read. Invariant Labs showed it on 1 April 2025 with a calculator-style add tool that told the model to read an SSH key and pass it in an extra parameter.

  • How is MCP tool poisoning different from prompt injection?

    Prompt injection is untrusted text the model treats as instructions, in a message, a page, an email or a tool result. MCP tool poisoning is that attack aimed at the tool's own description or schema, before any result comes back. A poisoned tool result is still prompt injection.

  • How do you defend against MCP tool poisoning?

    Pin a hash of each tool's name, description and schema at approval, show the full text and arguments, and put a person on destructive or data-moving calls. Keep credentials out of the model's reach, isolate servers, and treat a changed hash as a new registration rather than as the tool you already approved.

Let's build something that ships.

Tell us what you're building. We'll tell you whether it needs a fixed-scope build, a prototype taken to production, or a programme we run, what's achievable, and where the real bottlenecks are.

Reply within 2h

We store your name, email, company, and message, and email a copy to hello@bigcircle.ai. Read the privacy page and the terms.