Govern MCP tools before your agents get them
Model access is a data question. Tool access is an action question, and it is the one that wakes your on-call.
Governing model access is a data problem: what leaves, where it goes, what gets stripped on the way. Governing tools is a different problem, because a tool call is an action with consequences in a real system.
An agent that can read a repository is a disclosure question. An agent that can delete one is an availability question, and nobody wants to answer it after the fact.
The registration problem
MCP servers arrive the way integrations always arrive: one team stands one up to unblock a demo, it works, and six weeks later three agents depend on it. Nobody wrote down which tools it exposes, and the list changed twice since.
Putting servers behind a governed endpoint fixes the inventory as a side effect. Register the server as an upstream, expose it to agents through an endpoint you control, and the tool list stops being folklore.
That used to be an argument about hygiene. It is now an argument about a named attack class.
The tool list is not a list, it is a moving target
Two things about MCP tool definitions are worth internalising before you connect anything.
The description is instructions. A tool definition is natural-language metadata the model reads and acts on. Invariant Labs named the resulting attack tool poisoning in April 2025 and demonstrated it against imitation WhatsApp and GitHub servers, where a single poisoned description was enough to exfiltrate repository contents and message history. The user never sees the malicious text, because descriptions are not surfaced in the interface. What they see is the agent calling a plausible tool with plausible-looking arguments, one of which quietly carries the payload. The family has variants: hidden instructions in the description, in the JSON schema's parameter descriptions, or in the tool's returned output.
Approval is a moment, not a state. A rug pull is the persistence version: a server that passed review later changes a tool definition, and the agent reloads it without asking anyone. MCP has no built-in mechanism to detect that a definition changed or to verify that current behaviour matches what was approved. Defensive guidance is consistent on the remedy: re-prompt when descriptions change materially, and at minimum log the change for review.
So "the list changed twice since" is not an inventory annoyance. It is the exploit. Which turns the registration argument into three concrete requirements:
- Tool definitions are pinned at approval, with a hash or equivalent, not just noted.
- A material change to a definition is a change event that a human confirms, not a silent reload.
- The diff is on the record, so the question "what was this tool allowed to do in March" has an answer.
Scanning helps and does not finish the job. Tools like mcp-scan catch poisoned descriptions at a point in time; pinning and allow-listing are what hold between scans.
Allow and deny belongs per tool, not per server
- One server can back many endpoints, and one endpoint can compose many servers.
- Read tools and destructive tools from the same server rarely deserve the same answer.
- Destructive write and delete tools should be flagged before an agent connects, not discovered in an incident review.
- Trust, transport and auth posture belong on the server record, where a reviewer can read them.
MCP gives you a vocabulary for the third of those. The specification defines four behavioural hints on a tool, covering whether it is read-only, whether its changes are destructive rather than additive, whether it is safe to retry, and whether it reaches outside its local environment. The defaults are deliberately pessimistic: a tool with no annotations is treated as destructive, non-idempotent and open-world.
Use that vocabulary. Do not use it as a control. The specification is direct about this: clients are required to treat annotations as untrusted unless they come from a server that is itself trusted, because nothing at the protocol level stops a server from declaring a tool read-only and deleting your files anyway.
Which is exactly the case for classification living on your side of the boundary. The server's annotation is a claim by the server. The flag on your endpoint is a decision by you, it survives the server changing its mind, and it is the one a reviewer can hold you to.
The risk is in the composition, not the server
The sharpest framing available for agent risk is the lethal trifecta: private data, untrusted content, and the ability to communicate externally. Any one is manageable. Together they are an exfiltration path, and the agent does not need to be compromised for it to work, only helpful.
The important property is that no single server owns that risk. A read-only ticketing tool is safe. A file-write tool is safe. An HTTP tool is safe. An agent holding all three, one of which returns text an outsider controls, is not. The risk lives in the union of tools exposed to one agent, which is precisely the thing a per-server allow list cannot see and a per-endpoint composition can.
The ecosystem is moving toward vocabulary for this. Proposals under discussion would add hints for tools that touch sensitive data and for tools that can send data outside the boundary, splitting today's open-world hint into its two distinct halves. Until those land, and even after, composing the trifecta is a judgment someone has to make per endpoint, with a name attached.
The other half of the problem is the supply chain
Tool definitions are the interesting attack surface. They are not the only one.
The 2025 to 2026 record includes remote code execution in a widely used MCP proxy, vulnerabilities in the MCP Inspector and in agent IDEs, and two incidents that need no interpretation: an official Postmark MCP server that silently blind-copied every sent email to its maintainer, and a path traversal in Smithery that exposed deployment credentials for over three thousand hosted MCP apps. Around all of it ran the worst year npm has had, with self-replicating token-stealing worms moving through hundreds of packages.
None of that is exotic for anyone who has run a package registry. It is the ordinary supply chain problem, arriving in a layer that is usually wired up in an afternoon by someone unblocking a demo. The server record is where the answer lives: where the server came from, how it is transported, how it authenticates, who approved it, and when it was last reviewed.
If you want an external structure for that review, the OWASP MCP Top 10 is in beta and lists tool poisoning among its entries, the Cloud Security Alliance's AI Controls Matrix maps to ISO 42001, ISO 27001 and the NIST AI RMF, and MITRE ATLAS added agent-specific techniques including context poisoning and memory manipulation.
The useful default is narrow
Allow the tools the agent needs for the job it was approved to do, and make widening it an explicit change with a name attached.
Concretely, that means an endpoint starts empty rather than starting with a server's full catalogue; read tools and destructive tools are approved separately even when they arrive together; and a new tool appearing on an upstream server is not automatically available to anything, because appearing is what a rug pull looks like from the inside.
Why this lands in the same place as model governance
Both are the same request path.
If tool calls pass through the layer that already redacts and routes model calls, the agent chain, the model turns and the tool calls end up in one record instead of three systems. That is what makes the question "what did this agent actually do" answerable.
It is also the only way the earlier controls stay honest. Redaction that runs on the prompt and not on the tool result is redaction with a hole in it, since a tool result is untrusted text arriving from outside and heading straight into the model's context. Policy that governs which model an agent may call, but not which tools it may reach, governs the cheaper half of the problem.
An agent is not a model with extra features. It is a small distributed system that takes actions, and the record of what it did has to read as one chain.
This is an engineering perspective on where tool governance belongs, not security advice specific to any deployment. The MCP threat landscape is moving quickly; treat named incidents as illustrations of a class rather than as a current inventory.
Sources
- Tool annotations as risk vocabulary: what hints can and cannot do, Model Context Protocol blog, March 2026
- MCP tool annotations and approval decisions, on the specification's untrusted-annotation requirement
- MCP security in 2026: tool poisoning, rug pulls and the npm supply chain
- MCP rug pull attacks, on why one-time approval workflows fail
- Securing MCP: a defense-first architecture guide, Christian Schneider
- Agentic MCP security best practices, Cloud Security Alliance, on the AI Controls Matrix and MITRE ATLAS agent techniques
- MCP tool annotations: what is coming next, on proposed sensitivity and egress hints
- MCP tool poisoning: how to secure AI agents, on the OWASP MCP Top 10 beta