{
  "schema_version": "1.3.0",
  "slug": "why-does-an-instance-of-an-mcp-server-pass-tool-poisoning-review-but-still-leak-capability-at-runtime",
  "title": "Why does an instance of an MCP server pass tool-poisoning review but still leak capability at runtime",
  "date_of_record": "2026 November 14",
  "scope": "Applies to MCP (Model Context Protocol) servers that expose tools whose declared schema, description, or annotations are reviewed at install/consent time, but whose runtime behavior is gated by arguments, environment, or downstream tool calls not captured in that declaration. Does not apply to servers whose tool surface is fully static and whose arguments cannot influence capability selection (e.g., pure computational tools with no I/O).",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/why-does-an-instance-of-an-mcp-server-pass-tool-poisoning-review-but-still-leak-capability-at-runtime.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/why-does-an-instance-of-an-mcp-server-pass-tool-poisoning-review-but-still-leak-capability-at-runtime.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/why-does-an-instance-of-an-mcp-server-pass-tool-poisoning-review-but-still-leak-capability-at-runtime.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 2223,
    "python_slice_tokens": 477,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "Tool-poisoning defenses operate on the **declared** capability surface: the `name`, `description`, `inputSchema`, and annotations that a server publishes during `tools/list`. Capability-scoped consent UIs operate on the **realized** capability surface: the set of side effects a tool invocation can actually produce given the arguments the model supplies. Thes...",
    "what_was_observed": "A filesystem-adjacent MCP server was reviewed and approved with three tools: `read_file(path)`, `list_dir(path)`, and `search(pattern)`. The consent UI displayed `readOnlyHint: true` on all three and scoped the grant to the `~/projects/` root. The reviewer confirmed that `read_file`'s schema declared `path` as a `string` with a `pattern` of `^[^/].*` (relative paths only). This was treated as the containment boundary...",
    "condition_of_validity": "The defense holds — consent scope bounds realized capability — only under the conjunction: 1. **Argument-honesty:** every argument value the schema admits maps to exactly one capability class, and that class is a subset of the declared capability. Violated by path/URL/shell/template/dispatch arguments, and by normalization that widens the admitted set beyond...",
    "decision_boundary": "Treat a tool as **not safely scopeable by declaration alone** — and require either runtime mediation or refusal — when any of the following is true: - An argument's schema is `string`, `array`, or `object` *without* a closed `enum`, and the tool's description implies the value selects a resource (path, host, query target, tool name, template). Open string ar...",
    "operational_effect": "For an agent operating under a capability-scoped grant, the practical consequence is that **the grant's scope string is not a security boundary; it is a hint to a cooperating server.** The agent should: - Prefer tools whose arguments are closed enums; when forced to use open-string arguments, treat the invocation as *widening* the effective grant and log it ..."
  },
  "matched_failure_symptoms": [
    "DOMAIN:EPISTEMIC_PROVENANCE_AND_FEDERATION_ROUTING"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "5b248881d012f4e0825228d4957d064bc53fb768e475fed4dfd9f7df36aaecb5",
    "verified_classes": [
      "CapabilityScopeError"
    ],
    "verified_functions": [
      "assert_scope_safe",
      "guarded_invoke"
    ],
    "verified_functions_count": 2,
    "defensive_guards_count": 3,
    "raised_exceptions": [
      "CapabilityScopeError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
