Connect an MCP server to an agent and it will happily advertise everything it has. On a realistic support catalogue that means the model is offered tools that issue refunds, cancel subscriptions and delete customer data, on every request, including requests that have nothing to do with any of them.
We measured what that costs, and what each layer of governance buys back.
The baseline
60 deliberately confusable tools — seven near-identical refund verbs across three risk classes — across 38 tasks. 21 of the tools are in policy-denied classes. With no gateway in front, all 60 are exposed on all 38 tasks: 798 forbidden-tool exposures, and 3,775 schema tokens of context spent per request at 1% precision.
Every policy-respecting strategy records zero forbidden exposures. Not a low number — zero, structurally, because the filter runs before ranking and ranking can only reorder what survived it. No relevance score, semantic match or cost preference can reintroduce a denied tool, because none of them ever sees it.
Zero is not a good score here. It is the only acceptable one, and it has to come from the architecture rather than from the ranker behaving well.
Splitting the value
Policy filtering alone takes 3,775 schema tokens down to 809 — a 79% reduction — and 798 exposures to 0, with no loss of recall at all: the unranked permitted set still finds 100% of required tools. Ranking then takes 809 tokens down to 292, a further 64%, at a cost of four points of recall.
So the filter is free and the ranker is a trade. At 18 tools ranking cost no recall whatsoever; at 60 it costs four points. The trade is real now, and the maximum-tool-count setting is the dial.
Where the zero actually comes from
A filter is only as good as the labels it filters on, and the labels are the part an MCP server would most like to supply. It cannot. Discovery imports capability, never authority: a server returns a tool's name, description and schema, and nothing else. It has no way to assert that its own delete_customer_data is read-only, because nothing it says about risk is read.
Imported tools therefore arrive unclassified, which is a class no policy grants. A freshly synced catalogue is exposed to nothing at all until an operator classifies it — verified on a real n8n server: 18 tools discovered, 0 exposed. A tool class with no configured permission is denied rather than allowed, because an unconfigured trust boundary that defaults to permissive is not a boundary.
There is a corollary that catches people out. If a tool's schema changes, its classification resets to unclassified, even though an operator had already judged it. The contract changed, so the earlier judgement may no longer hold, and carrying it forward would let a server silently repurpose an approved tool into something else.
Why the catalogue was built to be confusing
A benchmark of ten obviously different tools would have scored near-perfectly and taught us nothing. The seven refund verbs exist so that a term saturating the catalogue — "refund" appears in six of 60 tool names — actually breaks naive ranking, which is how we found that IDF weighting over the permitted set was doing necessary work.
It also surfaced the failure mode worth knowing about: when every plausible discriminator is common, lexical matching has no signal left. That is the honest limit of the deterministic approach, and it is why the semantic infrastructure stays built even though it is currently switched off.