I looked at 1,384 tools across 28 MCP servers. Here's what the attack surface actually looks like. A developer surveyed 1,384 tools across 28 popular Python MCP servers and found that 14 of the 28 expose at least one untrusted-content source and one high-impact sink in the same agent context, while 59 individual tools both ingest external content and perform actions. The analysis, based on a reproducible harness reading public source code as of 2026-10-20, also found that all 9 pattern-based tool-poisoning matches across four vendors were benign, since legitimate servers routinely write descriptions as direct instructions to the model. Quick context if you're new to this: an MCP server is a plug-in that gives an AI agent a set of tools it can call, like "fetch this URL," "run this database query," or "send this email." There are hundreds of open-source MCP servers now. This writeup measures what those tools actually let an agent do, and how often the risky combinations sit side by side. Method note. The numbers are a snapshot taken on 2026-10-20 of 28 popular Python MCP servers plus the reference-servers repo , produced with a reproducible harness https://github.com/agentsploit/agentsploit/tree/main/examples/mcp-survey . Upstream repos change over time, so re-running this later gives somewhat different counts. Everything below is read from public source code . No server was connected to or executed. The capability labels are rough heuristics see the caveats , and this writeup deliberately does not call anything a vulnerability. I kept running into MCP servers where one tool fetches a web page and another tool runs a command, both handed to the same agent, with nothing telling the model which one is dangerous. Instead of guessing how common that is, I decided to measure it. So I pulled the tool definitions straight from the source code of the most popular Python MCP servers on GitHub AWS Labs, Google Workspace, Atlassian, Home Assistant, Snowflake, the Neo4j / Redis / Qdrant / Chroma / Milvus database servers, the Office / Excel document servers, Telegram, and more , and ran AgentSploit https://github.com/agentsploit/agentsploit 's inventory checks plus a simple source/sink classifier over them. That comes to 1,384 tools across 28 servers. The reproducible harness is at the bottom. A tool's description is just text, and the AI reads it. The "tool poisoning" attack is built on that fact: if an attacker can slip instructions into a description, the model may follow them. Think of it like hiding a note in a manual that the reader obeys without question. What the survey shows is that normal, legitimate servers already write their descriptions as direct orders to the model. These are real examples, and all of them are completely harmless: "Before using this tool, provide a 1-3 sentence explanation…" AWS Labs "CRITICAL: YOU MUST CALL inspect doc structure FIRST…" Google Workspace "🔴 PREREQUISITE: Before calling this tool, you MUST first call … " AWS Labs Those are good-faith usage notes. The problem is that, at the level of plain text, they look exactly like an injected IGNORE ALL PREVIOUS INSTRUCTIONS . A pattern-based scanner AgentSploit's included flags both the same way. I went through all 9 matches by hand, spread across 4 independent vendors AWS, Google, Home Assistant, arXiv , and every single one was benign . That is the real finding: there's no clean way to tell a harmless instruction-style description from a malicious one, because the whole ecosystem already uses that same channel on purpose. I sorted every tool into two buckets: url , uri , path , or document , or its name looks like fetch / read / search / crawl . exec / run / query / write / send / delete , or an argument like command , code . The danger isn't either bucket on its own. It's having both in front of the same agent, so that something the agent read can flow into something the agent does . Across 1,384 tools: | | count | |---|---| | untrusted-content sources | 239 | | high-impact sinks | 384 | | tools that are both they ingest and act | 59 | | servers that expose at least one source and one sink in the same context | 14 / 28 | The 59 "both" tools are the sharpest edge. A single tool that pulls in a URL or a file and also runs a query or a command is a one-call bridge from untrusted input straight to a real action, if the content it pulls is attacker-controlled. For example search table url that also takes a query , or run query db endpoint, sql , or the Google Workspace and Office document tools that read a document and write it back. And 14 of the 28 servers put sources and sinks in the same agent context with nothing marking one as untrusted or the other as dangerous. The harness prints the full list so you can check it yourself. A few are weak matches. For instance AWS IAM's create user trips the filter on an IAM path argument, which isn't really outside content. Plenty of the sink tools take a raw string with no enum , pattern , or format constraint on it, like executeQuery query , run opencypher query query , or read documentation url . Those constraints are the schema's way of saying "only these specific values are allowed." Without them, the field accepts anything. That's by design for a query tool. It's also exactly the kind of wide-open sink that turns "the agent read a poisoned page" into "the agent ran the attacker's SQL." To be clear: none of the above is a bug in these servers. A source-to-sink chain only becomes a real exploit when two things both happen: untrusted input actually reaches a source, and the agent actually carries it over to a sink. Both of those depend on how the server gets deployed and wired together, not on the code itself. Proving a real chain needs a live agent, which is what AgentSploit's permission-graph mapper and canary runner are for. That's out of scope for a static survey like this one. enum / pattern / format rather than taking any raw string. The quickest way to run this against a server yourself shipped in v1.7 : pip install agentsploit agentsploit survey ./path/to/mcp-server a repo directory or a single .py file Or reproduce the full multi-repo survey with the harness: git clone https://github.com/agentsploit/agentsploit && cd agentsploit pip install -e . cd examples/mcp-survey edit servers.yaml to pick targets python survey.py collect read tool definitions from public source python survey.py scan run agentsploit's inventory checks python survey.py aggregate print the findings table python survey.py surface run the source/sink classification scrape names , and the matching is token-based. It's still a guess at what a tool can do, not a traced data-flow. So read the counts as "could plausibly be," and trust the overall shape more than any single number. The shape is the sturdy part: most servers mix ingestion and action, and 59 tools do both in one call. The tool is Apache-2.0: github.com/agentsploit/agentsploit https://github.com/agentsploit/agentsploit . Ideas and pull requests welcome.