The capability graph

Gate's central design decision is that it does not reason about tools. It reasons about consequences, and tools are just how consequences get named.

The problem with tool names

Here are four tools from four different MCP servers:

filesystem.write_file
github.create_or_update_file
gdrive.upload
s3.put_object

They have nothing in common lexically. They have one thing in common that matters: each lets an agent change bytes that something else will later read.

Any analysis built on tool names has to enumerate every name in every ecosystem, and is wrong the moment somebody ships a server it has never seen. Since new MCP servers appear faster than anyone can catalogue them, that is a losing position by construction.

The alternative is to normalise. Give every tool a set of capability classes, run the analysis on the classes, and the analysis becomes portable. It works on a server nobody has ever catalogued, including one written this morning.

The graph

The structure is bipartite: agents reach systems through tools, and tools carry capabilities.

                       ┌──────────────┐
                       │    Agent     │
                       └──────┬───────┘
            ┌─────────────────┼─────────────────┐
            │                 │                 │
     ┌──────▼─────┐    ┌──────▼─────┐    ┌──────▼─────┐
     │  postgres  │    │ filesystem │    │   slack    │
     │            │    │            │    │            │
     │ prod creds │    │  ~/ (home) │    │ bot token  │
     └──────┬─────┘    └──────┬─────┘    └──────┬─────┘
            │                 │                 │
    execute_query        read_file         post_message
    ─────────────        ─────────         ────────────
    execute              read              communicate
    read                 secrets*          write
    write
    delete

    * because the grant reaches ~/.ssh and ~/.aws

Three things are represented that a list of tools does not represent:

  • Standing grants are capabilities too. The filesystem mount is not a tool, and it carries read and secrets because of where it points. Capability can come from configuration as well as from a callable.
  • Credentials sit on the edge, not the node. The same execute_query tool against a scratch database and against production are different edges.
  • The agent is the root. Everything reachable from it composes, whether or not it lives on the same server.

The ten classes

read         Observe data
search       Discover data across a corpus
write        Modify persistent state
communicate  Send information outside the system
delete       Destroy state
identity     Change who is able to act
admin        Change the rules of the system
secrets      Read credential material
execute      Run arbitrary code
financial    Move money

Each has a baseline risk floor, used when nothing more specific applies:

read, search              low
write, communicate        medium
identity, admin,
  delete, secrets         high
execute, financial        critical

Why ten

The number is a design choice with two failure modes on either side.

Too few and the classes stop discriminating. Collapsing read and search loses the fact that search finds things nobody pointed at. Collapsing write and delete loses reversibility, which is the single most useful distinction in the whole model.

Too many and nobody can hold them in their head. A reviewer who cannot recite the taxonomy skims it.

Ten survives both tests: it fits on one screen, and every pair of classes has a concrete case where the distinction changes what you would do.

Three of the ten exist specifically because agents made them matter:

  • communicate would be a strange class in a traditional permission model. "can send an email" is not usually a security boundary. For agents it is the exfiltration leg of the trifecta, and it is the difference between a leak and an incident.
  • secrets is separate from read because a tool that returns a credential puts it in the context window, where it can be repeated.
  • execute is separate from everything because it generates the others.

Classification

Deterministic, layered, most trustworthy first.

1. Known-server mapping. When Gate recognises the exact package, it knows the real tool list and what each tool does. This is fact.

The table is Gate's accumulating asset: every entry turns a guess into a fact, for everyone who scans that server. It is split into exact matches (a specific package whose tool list is known) and category matches (the kind of server, but not the exact tools). A category match never enumerates tools, inventing a tool list would make Gate's headline counts wrong, and wrong numbers are worse than coarse ones.

2. Name tokens. The verb, tokenised across snake_case, kebab-case, dotted.paths and camelCase, matched against an ordered rule table.

3. Description keywords. Additive only, and never sufficient to introduce execute or financial.

That last restriction is a security boundary rather than a heuristic. A description is text written by whoever wrote the server, and it is what the model reads when deciding whether a call is safe. If a description could lower a classification, a hostile server could describe its way out of a finding. Gate treats the description as a claim and the classification as evidence, and when they disagree it believes the evidence. GATE016 reports the disagreement.

Implications. delete, financial, identity and admin all imply write. execute implies nothing. It does subsume everything, but expanding it would make every execution finding also fire three other rules, and a second copy of a finding is noise. The blast-radius engine handles execution's dominance separately, with its own contributor and its own escalation floor.

Paths, not nodes

Once the graph exists, the interesting questions stop being about individual tools.

Is there a path from read to communicate? Then anything readable is sendable, regardless of which servers those capabilities live on. This is the composition that individual tool review structurally cannot catch, because at no point does a reviewer see both halves.

Is there a path from execute to a production credential? That is a remote shell on production, however the two got onto the same agent.

Is there a path from admin to anything? Then the graph can be rewritten by the thing being analysed. admin is the class that lets an agent change its own limits.

Is there a path from secrets to communicate? The trifecta, concretely.

Gate encodes seven of these as dangerous combinations and reports them through GATE015.

What the graph enables

Portability. One rule set, every ecosystem. A rule written against execute works on Claude Code, VS Code, Cursor, Windsurf, Codex, Gemini CLI and a framework that does not exist yet.

Comparability. Two agents with completely different tools can be compared, because their capability sets are in the same vocabulary.

Diffability. "This change added the execute capability" is a sentence that survives a tool being renamed, replaced, or swapped for a different server entirely. That is what makes baselines meaningful over time.

Explainability. gate explain postgres.execute_query can say what a tool means without knowing anything about Postgres, because the capability classes carry the meaning.

Open problems

Known limitations of the model:

Data sensitivity is not modelled. read on public documentation and read on a customer database are the same class. Gate has no way to know which it is looking at, and the distinction matters enormously. Nothing in configuration carries it.

Scope within a capability is coarse. write to one file and write to a whole bucket are the same class. Filesystem scope is modelled separately, which covers the most common case and not the general one.

Composition across time is not modelled. An agent that writes to a file in one session and executes it in the next has effectively chained two capabilities. Static analysis of one configuration sees two grants.

Classification of unknown tools is a guess. Name-based inference is right often and not always. The known-server table is how that improves, which makes it the highest-value contribution anyone can make to Gate.

The weights are judgement. There is no dataset of agent incidents to calibrate against; the field is eighteen months old. So the score is always decomposed into its contributors, and a reader who disagrees can see which one they disagree with.

Was this page helpful?