{"slug": "we-audited-what-mcp-servers-put-in-your-agent-s-context", "title": "We Audited What MCP Servers Put in Your Agent's Context", "summary": "A documentation audit of 19 widely deployed Model Context Protocol (MCP) servers found that 18 of 19 do not document the spec's instructions field or any free-text instruction surface, and none of the retrieval-focused servers warn that returned content could carry embedded instructions. The audit follows CVE-2026-75130, a prompt-injection vulnerability in Context7 through 2.1.2, published August 18, 2026, which allows attackers to execute malicious instructions in connected AI coding agents. Only Context7 documents a free-text, persistent instruction mechanism, the same feature class named in the CVE.", "body_md": "MCP servers can put text into your agent’s context through several distinct surfaces — tool descriptions, an optional server-level instructions field, resource content, prompt templates, and the tool results themselves — yet almost none of the ecosystem’s most widely deployed servers document which of those surfaces they actually use. We audited 19 of them against the Model Context Protocol specification’s own definitions to find out what is disclosed, and what isn’t.\n\nThe result is a census, not a ranking. For each server we recorded whether its own current documentation discloses a server-level `instructions`\n\nfield, a user- or vendor-configurable free-text instruction surface, and any explicit warning that the content its tools return could carry embedded instructions. The modal answer, across all three columns, is **undocumented** — which is itself the finding, because a security reviewer cannot evaluate a surface a vendor never mentions.\n\nOne caveat governs every row and we will repeat it wherever the numbers appear: this is a documentation audit, not a source-code audit. “Undocumented” means the server’s own public docs do not disclose the surface — it does not mean the surface is absent from the running code. The two can diverge, and only a code-level audit (out of scope here) could close that gap.\n\n- 01One of nineteen servers documents a served instruction surface.Only Context7 documents a free-text, persistent instruction mechanism beyond ordinary tool-call arguments — the same feature class named in CVE-2026-75130, published August 18, 2026.\n- 02Undocumented is the modal cell, not the exception.18 of 19 audited servers document neither the spec’s DiscoverResult instructions field nor any free-text instruction surface beyond ordinary tool-call arguments. Five say something adjacent — cautions from Stripe and Playwright, a general data-exposure caveat from Notion, client-side prompt advice from Memory, and the Everything test server’s demonstration of sampling and elicitation as protocol features — each printed as a qualified cell rather than counted as disclosure.\n- 03The taxonomy comes from the spec itself.The 2026-07-28 MCP revision defines the surfaces: the instructions field, tool descriptions, tool annotations (untrusted per the spec), resource content and annotations, server-authored prompt content, and a deprecated sampling systemPrompt.\n- 04The biggest practical surface is ordinary tool-result content.A fetched web page, a search result, or an issue body reaches context as a tool result — and none of the sample’s retrieval-focused servers (Fetch, Firecrawl, Brave Search) documents a warning that returned content could carry embedded instructions.\n- 05The reference set most tutorials cite has moved.Seven servers remain actively maintained in modelcontextprotocol/servers; thirteen early ones — including GitHub, Slack, and Postgres — moved to a separate archived repo, several living on as forks under different ownership.\n\n## 01 — Why This CensusA CVE made the question *concrete*.\n\nOn August 18, 2026, the National Vulnerability Database published CVE-2026-75130, a prompt-injection vulnerability in Context7, Upstash’s widely installed MCP documentation server. The mechanism matters more than the vendor: a free-text “Custom AI Instructions” feature served through the MCP server let unsanitised content reach connected coding agents during what looked like a routine library-documentation request. The disclosed impact, per the VulnCheck advisory, includes exfiltration of credentials from environment files and destructive file deletion. The weakness is classified as CWE-1427, “Improper Neutralization of Input Used for LLM Prompting,” credited to researcher Eli Ainhorn of Noma Security.\n\n[CVE-2026-75130](https://nvd.nist.gov/vuln/detail/CVE-2026-75130): “Context7 through 2.1.2 contains a prompt injection vulnerability that allows attackers to execute malicious instructions in connected AI coding agents by injecting unsanitized content through the Custom AI Instructions feature served via the MCP server.” The two scoring frameworks diverge sharply on the same flaw:\n\n**CVSS 3.1 rates it 9.0 CRITICAL**, while\n\n**CVSS 4.0 rates it 6.4 MEDIUM**— quoting either number alone tells half the story. Affected versions: 0 through 2.1.2. No public fix was documented in the advisory, and none had been documented as of our retrieval date (2026-08-22) — we state that as an absence of documentation, not a claim about later releases. Independent confirmation:\n\n[VulnCheck advisory](https://vulncheck.com/advisories/context7-prompt-injection-via-custom-ai-instructions), retrieved 2026-08-22.\n\nThis post is not about Context7. The CVE simply made a general question concrete: **which of the text-injection surfaces the MCP specification defines do widely deployed servers actually document?** If a vulnerability of this class can sit inside a feature most users never knew was an injection surface, the useful reference is not another vendor writeup — it is a dated, reproducible census of what every major server discloses, built from the spec’s own definitions. That is what the rest of this page is.\n\nWe built the taxonomy from the specification’s field definitions first, before opening a single vendor page. Most MCP security content starts from an attack and works backward; starting from the protocol’s primitives is what makes this census reproducible — anyone can redo it, column by column, against the same spec-defined surfaces. It also extends the method of our [companion census on coding-agent data terms](/blog/coding-agent-data-terms-census-2026): score vendor documentation against a fixed question set, keep the unresolved cells visible, and date everything.\n\n## 02 — The TaxonomySeven surfaces, defined by the *spec itself*.\n\nThe current MCP revision — 2026-07-28, the stateless-core release we covered in [our migration guide](/blog/mcp-2026-07-28-spec-stateless-migration-guide) — defines three server primitives with an explicit control-hierarchy: Prompts are user-controlled to invoke, Resources are application-controlled, Tools are model-controlled. Reading the primitive definitions closely yields seven distinct routes by which server-originated text can reach a model’s context. All seven are in the table below, each with the spec section that defines it and the spec’s own words.\n\n| Surface | Spec section | Who controls the text | Status (2026-07-28 rev) | The spec’s own words |\n|---|---|---|---|---|\nServer `instructions` field |\n|\n\n`description`\n\n[Tools](https://modelcontextprotocol.io/specification/2026-07-28/server/tools)[Tools](https://modelcontextprotocol.io/specification/2026-07-28/server/tools)[Tools](https://modelcontextprotocol.io/specification/2026-07-28/server/tools)[Resources](https://modelcontextprotocol.io/specification/2026-07-28/server/resources)`priority`\n\nannotation runs 0.0–1.0, where “A value of 1 means ‘most important’ (effectively required)”[Prompts](https://modelcontextprotocol.io/specification/2026-07-28/server/prompts)`systemPrompt`\n\n[Sampling](https://modelcontextprotocol.io/specification/2026-07-28/client/sampling)(client feature)Three details from the spec text deserve emphasis, because the census’s columns are built on them. First, the spec’s caution about self-reported metadata is stated for `serverInfo`\n\nspecifically — “Clients SHOULD NOT use it to change their behavior, and SHOULD NOT rely on it for security decisions” — and is not extended verbatim to the `instructions`\n\nfield, so the two should not be conflated. Second, the deprecated `includeContext`\n\nsampling parameter’s `\"thisServer\"`\n\n/`\"allServers\"`\n\nvalues (SEP-2596) closed a narrower channel by which one server’s sampling request could have pulled in context from *other* connected servers. Third, and most important for what follows: the spec has no named security-classification framework separating server instructions from tool descriptions from resource content. Its Security Considerations sections give generic input-validation and access-control guidance — not a disclosure requirement for context-injection surfaces. Transparency on this question is therefore left entirely to individual server maintainers, which is exactly what makes a disclosure census worth running.\n\n\"For trust & safety and security, clients MUST consider tool annotations to be untrusted unless they come from trusted servers.\"— MCP Specification, Tools, 2026-07-28 revision\n\n## 03 — MethodologyWhat we checked, and what we *didn’t*.\n\n**What was collected.** For each of 19 MCP servers, we recorded whether the server’s own public documentation — its README, official docs page, or hosted docs site, never a third party’s writeup — discloses any of three text-injection surfaces the MCP specification defines: (1) the optional `instructions`\n\nfield returned on connection discovery; (2) a user- or vendor-configurable free-text instruction surface distinct from ordinary tool-call arguments; and (3) any explicit warning in the server’s own docs that content it returns is untrusted third-party text that could carry embedded instructions. A fourth spec-defined surface, tool descriptions, is present by definition — a tool is unusable without one — so we treated it as a baseline rather than scoring it row by row.\n\n**Sources and date.** The source of truth for every cell is the vendor’s or maintainer’s own current documentation page, fetched on **2026-08-22** — the dataset’s as-of date, distinct from this post’s publish date. No row was inferred from a server’s category, from another server in the same category, or from third-party coverage. Where a fetched excerpt could not confirm a cell (one cell, on the Everything test server), the cell says so rather than resolving it.\n\n**Sampling frame — 19 servers.** The seven servers still maintained as reference implementations in *modelcontextprotocol/servers* (Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking, Time), plus twelve of the highest-traffic named servers: GitHub, Slack, Sentry, Postgres, Playwright (the maintained successor to the archived Puppeteer server), Context7, Firecrawl, Supabase, Notion, Linear, Stripe, and Brave Search.\n\n**Excluded, and why.** (1) MCP clients — this census is about what servers can put in context, not how a client renders it. (2) Archived, unmaintained servers (AWS KB Retrieval, EverArt, Google Drive, Google Maps, Redis, SQLite and others now in *servers-archived*) — we did not audit code nobody maintains. (3) The official MCP registry’s full self-published catalog — auditing it exhaustively would require fetching thousands of individual listing pages, out of scope for one post.\n\n**Known limitations.** (a) 19 rows is a sample of the highest-traffic, most-cited servers, not a census of the registry’s population — and we could not obtain an exact total server count from the registry API without paginating the full listing, so no population size is stated or implied anywhere on this page. (b) “Undocumented” means the server’s own current public docs do not disclose the surface — not that the surface is absent from the running code; only a source-level audit could close that gap. (c) We audited each server’s primary README or docs page; a server may disclose more in a secondary page we did not locate. (d) GitHub’s server exposes free-text tool-call *parameters* (a `custom_instructions`\n\nargument on its Copilot-assignment tool, a `rationale`\n\nfield) — recorded separately, because caller-supplied per-call input is not a server-served surface.\n\nOne counting rule needs stating before the table, because two rows carry qualified “Documented” notes that do not count toward the headline figure — and the rule is a judgement call, so we state it plainly rather than burying it. The **1 of 19** statistic counts servers whose docs describe a *persistent* free-text instruction mechanism that is part of the server’s own product, rather than generic advice about configuring a client. Both qualifying candidates are configured on the client side, so “client-side” is not what separates them. What separates them is whose product the instruction belongs to. Context7’s README documents “Add a Rule” as a persistent instruction, wording supplied, whose purpose is to drive Context7 itself — an instruction mechanism the audited product documents as its own, which is what we counted. (The NVD advisory describes the same feature class as “served via the MCP server,” which corroborates that reading, but the row is scored from the README, since every cell in this census comes from the vendor’s own docs.) The reference Memory server’s “System Prompt” section is advice telling operators to paste guidance into the client’s own custom-instructions setting, naming no Memory feature of its own, so we did not count it. Read the headline as 1 of 19 on that rule, with Memory as the borderline row a stricter counter would call 2 of 19. The Everything server demonstrates the sampling `systemPrompt`\n\nand elicitation as protocol features — but it is the spec’s own test server demonstrating the protocol, not a vendor content surface. Both non-counting caveats are printed in their rows rather than flattened into a yes or a no.\n\n##### Documented\n\nThe disclosure exists in the primary documentation, and the qualifying detail — what exactly is documented, and any distance between the feature and its stated risk — is printed in the cell rather than reduced to a checkmark.\n\n*Undocumented*\n\nThe server’s primary docs were fetched and read, and they do not address the surface. This is a finding about documentation, never an inference about the running code — the two can diverge in both directions.\n\n##### Partial\n\nThe docs carry a nearby caution that stops short of answering the census question — Notion’s general data-exposure note is the sample’s one example. Scored separately so the 2-of-19 warning count stays strict.\n\n##### Not confirmed in fetched excerpt\n\nThe fetched portion of the documentation could not settle the cell. One cell in the dataset carries this status — the Everything test server’s instructions field — and it is recorded as our limitation, not the vendor’s silence.\n\n## 04 — The DatasetThe complete census: *19* servers, three disclosure columns.\n\nThe table below is the asset — all 19 rows, no summary substitution. **Instructions field** asks whether the docs mention populating the spec’s `DiscoverResult`\n\n`instructions`\n\nstring. **Custom-instruction surface** asks whether the docs describe a user/vendor-configurable free-text field beyond ordinary tool-call arguments. **Injection warning** asks whether the docs explicitly warn that returned content could carry untrusted instructions. Every cell reads “Undocumented” unless the server’s own docs say otherwise. **Data as of August 22, 2026**, fetched from the linked source in each row.\n\n| Server | Maintainer | Instructions field | Custom-instruction surface | Injection warning | Source (fetched 2026-08-22) |\n|---|---|---|---|---|---|\n| Rows 1–7 · Active reference servers · modelcontextprotocol/servers | |||||\n| Filesystem | MCP reference (active) | Undocumented | Undocumented | Undocumented |\n|\n\n[README](https://github.com/modelcontextprotocol/servers/blob/main/src/fetch/README.md)[README](https://github.com/modelcontextprotocol/servers/blob/main/src/git/README.md)[README](https://github.com/modelcontextprotocol/servers/blob/main/src/memory/README.md)[README](https://github.com/modelcontextprotocol/servers/blob/main/src/sequentialthinking/README.md)[README](https://github.com/modelcontextprotocol/servers/blob/main/src/time/README.md)`systemPrompt`\n\n+ elicitation as protocol features — test/demo server, not a vendor content surface[README](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/README.md)·[features.md](https://github.com/modelcontextprotocol/servers/blob/main/src/everything/docs/features.md)`custom_instructions`\n\n/ `rationale`\n\nare caller-supplied per call, not a server-served surface[README](https://github.com/github/github-mcp-server)[README](https://github.com/zencoderai/slack-mcp-server)[mcp.sentry.dev](https://mcp.sentry.dev/)[README](https://github.com/microsoft/playwright-mcp)[README](https://github.com/upstash/context7)[README](https://github.com/mendableai/firecrawl-mcp-server)[README](https://github.com/supabase-community/supabase-mcp)[README](https://github.com/makenotion/notion-mcp-server)[linear.app/docs/mcp](https://linear.app/docs/mcp)[docs.stripe.com/mcp](https://docs.stripe.com/mcp)[README](https://github.com/brave/brave-search-mcp-server)[README](https://github.com/crystaldba/postgres-mcp)A fourth surface is deliberately absent as a column: tool descriptions. Every server in the sample publishes them, but that cell is *definitional* rather than audited — the spec makes the description a required field and a tool is unusable without one, so we did not run a per-row check and no row in the dataset records one. Treat “19 of 19” here as a property of the protocol, not a measurement we took. It is still the baseline that makes the rest of the table legible: every server publishes the surface it must publish for the product to function, and almost none documents anything beyond it.\n\n## 05 — FindingsWhat the table *says* — and what it can’t.\n\nRecomputing the audited columns: 2 of 19 carry a prompt-injection or untrusted-content caution, with Notion’s general data-exposure caveat scored partial rather than counted; 1 of 19 documents a persistent custom-instruction surface belonging to the server’s own product; and 0 of 19 document populating the spec’s `instructions`\n\nfield — 18 of those confirmed absent from the docs we fetched, with the Everything test server’s cell unresolved by our fetch rather than confirmed negative. Tool descriptions sit outside that recount as the definitional baseline described above — present because the protocol requires them, not because we scored nineteen rows. Undocumented is not the exception in this dataset — it is the default state of the ecosystem’s disclosure.\n\n#### Documentation disclosure rates · 19-server sample · as of 2026-08-22\n\nSource: Digital Applied census of 19 MCP servers’ own documentation, fetched 2026-08-22Four findings deserve individual attention, and two of them are negative findings we are keeping in deliberately.\n\n**The one documented surface is the one with the CVE.** Context7’s README documents an “Add a Rule” section instructing users to add a persistent instruction — for example, in an editor’s rules settings or a project’s instruction file — reading “Always use Context7 when I need library/API documentation, code generation, setup or configuration steps without me having to explicitly ask.” That is the user-facing half of the same Custom AI Instructions mechanism named in CVE-2026-75130 — the feature NVD describes as “served via the MCP server,” corroborating a row our counting rule scores from the README itself. The README documents no security or trust warning alongside the feature — only a generic community-project disclaimer. Documented, in other words, is not the same as documented with its risk stated.\n\n**The retrieval servers carry no warning at all.** None of the audited servers whose core function is retrieving external, attacker-reachable text — Fetch (arbitrary URLs), Firecrawl (web scraping), Brave Search (search results) — carries a documented warning that the content its tools return could contain embedded instructions aimed at the calling agent. We checked each one’s current README specifically for that language and found none. This is a first-class negative finding: these are precisely the servers for which tool-result content — the largest practical injection surface the spec describes — is the entire product.\n\n**The two warnings that do exist warn about different things.** Stripe’s docs tell operators to “Enable human confirmation of tools and exercise caution when using the Stripe MCP with other servers to avoid prompt injection attacks” — a caution about combining servers, not about Stripe’s own content. Playwright’s README states flatly that the server is not a security boundary, without naming page-content injection specifically. Notion’s README sits between: it acknowledges “a non-zero risk to workspace data by exposing it to LLMs,” a general data-exposure caveat we scored as partial rather than an injection warning. Even among the disclosing minority, there is no shared vocabulary for the risk.\n\n**Free-text tool input is not a served surface — and the distinction matters.** GitHub’s official server exposes a `custom_instructions`\n\nparameter on its Copilot-assignment tool and a `rationale`\n\nfield on an intent-classification tool. Both let a caller inject free text — but as tool *input*, supplied by the calling agent or user per call. Context7’s documented rule is different in kind: a saved instruction that fires on every future session. Coverage of MCP security tends to conflate these; the census keeps them in separate cells because one is scoped to a single call and the other persists.\n\n\"Playwright MCP is not a security boundary.\"— microsoft/playwright-mcp README, retrieved 2026-08-22\n\n## 06 — The Maintenance ShiftThe reference set your tutorial cites has *moved*.\n\nA secondary finding surfaced while assembling the sampling frame, and it affects anyone following early MCP tutorials. The set of reference servers actively maintained inside [modelcontextprotocol/servers](https://github.com/modelcontextprotocol/servers) is now just seven: Everything, Fetch, Filesystem, Git, Memory, Sequential Thinking, and Time. Thirteen servers named in the original server list — GitHub, GitLab, Postgres, Puppeteer, Sentry, Slack, Brave Search, AWS KB Retrieval, EverArt, Google Drive, Google Maps, Redis, and SQLite — were moved to [modelcontextprotocol/servers-archived](https://github.com/modelcontextprotocol/servers-archived). Several live on as separately maintained forks or vendor-hosted rewrites under different ownership — GitHub’s official server, Zencoder’s Slack fork, Microsoft’s Playwright server succeeding Puppeteer, Crystal DBA’s Postgres rewrite — and those successors, not the archived originals, are what this census audited. A reader following a year-old tutorial link can land on unmaintained code without any signal that ownership changed.\n\nBeyond the reference repo sits the official MCP registry at [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io/) — a self-published catalog, not a curated list, whose sampled entries range from single-purpose vendor integrations to aggregators fronting scores of apps. We restate the limitation from the methodology because it bears on how far these findings generalise: we could not obtain an exact total server count from the registry API without paginating the full listing, so this census makes no claim about the registry’s population — only about the 19 highest-traffic servers sampled. For a wider but shallower view of the ecosystem, our [earlier 50-server ecosystem tracker](/blog/mcp-server-ecosystem-tracker-50-servers-cataloged-2026) catalogs the landscape this census drills into.\n\n## 07 — Using the TableWhat a security review does with *undocumented*.\n\nThe census is a question generator, not a verdict sheet. An “Undocumented” cell tells a reviewer exactly what to ask the vendor — or what to check in the source, for the open-source rows — before granting a server a place in an agent’s context. Three uses follow directly from the columns. First, inventory: list the MCP servers your agents actually connect to, and read each one’s row — or run the same three questions against any server not in this sample; the method section is written so the audit can be reproduced column by column. Second, prioritise by content origin: the spec’s own text makes tool-result content the largest practical surface, so servers that fetch attacker-reachable text deserve the hardest questions, and this sample shows those are precisely the servers documenting the least. Third, treat a documented instruction surface as configuration worth reviewing: a persistent rule that fires in every future session is agent configuration, and CVE-2026-75130 is the existence proof of what happens when that surface goes unsanitised.\n\nThe trend this table captures is worth projecting forward. The spec’s security sections currently impose input-validation guidance but no disclosure requirement, so server transparency is a maintainer-by-maintainer choice — and in this sample the choice has mostly been silence. Two forces seem likely to change that: CVEs in this class make “what can this server put in context” a procurement question rather than a curiosity, and clients keep adding controls — allowlists, approval prompts, sandboxing — that work better when servers declare their surfaces. If disclosure norms do emerge, re-running this census is cheap, and the delta between snapshots becomes the story. Until then, containment is the compensating control: our guides to [isolation patterns that limit what a compromised MCP connection can reach](/blog/ai-agent-sandboxing-isolation-patterns-2026) and [sandbox escapes that start the same way](/blog/agent-sandbox-escapes-worktree-symlink-command-filters-2026) cover the client side, and our [MCP server security engineering guide](/blog/mcp-server-security-best-practices-2026-engineering-guide) covers hardening the servers themselves. Teams formalising an agent-tooling review process can fold this census’s three questions into it directly, alongside the wider agent-evaluation scope set out under [AI transformation](/services/ai-transformation).\n\n## 08 — ConclusionThe silence is the *dataset*.\n\n### Nineteen servers, three scored disclosure columns, and one documented instruction surface beyond the mandatory minimum.\n\nThe census’s headline is not that MCP servers are hiding something. It is that on the question the specification itself makes askable — which of the protocol’s text-injection surfaces does this server use? — eighteen of nineteen widely deployed servers document neither the spec’s instructions field nor a free-text instruction surface beyond tool-call arguments, and the nineteenth documents the feature without documenting its risk. Five of those eighteen do say something adjacent — Stripe and Playwright carry cautions, Notion a general data-exposure caveat, Memory client-side prompt advice, and the Everything test server demonstrates sampling and elicitation as protocol features — and the table prints each of those as a qualified cell rather than as an answer to the census question. Every claim in that sentence is a documentation finding with a date on it, reproducible from the linked primaries, and every cell where our method hit a limit says so in the cell.\n\nThe equally important half is what the table does not say. An “Undocumented” cell is not an accusation — it records an absence in the docs, not a behaviour in the code. A documented warning is not a verified safeguard, and the one documented instruction surface is not shown to be worse than the eighteen that document none — only more legible, which is why it is also the row where a CVE could name its mechanism precisely. Keeping those distinctions in the table, rather than flattening them into a score, is what makes the dataset citable.\n\nDocumentation is the cheapest security surface there is. The spec already defines the vocabulary; a server needs one paragraph to say which surfaces it uses and one sentence to warn when its results carry third-party text. This page is a dated snapshot with a stated method — re-run it in six months, and the servers that moved from “Undocumented” to a real disclosure will be the most useful signal in the ecosystem.", "url": "https://wpnews.pro/news/we-audited-what-mcp-servers-put-in-your-agent-s-context", "canonical_source": "https://www.digitalapplied.com/blog/mcp-server-context-injection-transparency-audit", "published_at": "2026-08-22 00:00:00+00:00", "updated_at": "2026-08-22 05:42:33.059117+00:00", "lang": "en", "topics": ["ai-safety", "ai-agents", "ai-policy"], "entities": ["Model Context Protocol", "Context7", "Upstash", "CVE-2026-75130", "Noma Security", "Eli Ainhorn", "Stripe", "Playwright"], "alternates": {"html": "https://wpnews.pro/news/we-audited-what-mcp-servers-put-in-your-agent-s-context", "markdown": "https://wpnews.pro/news/we-audited-what-mcp-servers-put-in-your-agent-s-context.md", "text": "https://wpnews.pro/news/we-audited-what-mcp-servers-put-in-your-agent-s-context.txt", "jsonld": "https://wpnews.pro/news/we-audited-what-mcp-servers-put-in-your-agent-s-context.jsonld"}}