Agent Runbook

Scoping an MCP Server's Permissions Before You Connect It

Last reviewed: 9 October 2026.

Method disclosure, up front: this is an operational runbook, not a vulnerability write-up. The threat descriptions are sourced to published 2026 security research, linked at the end. The checklist and the permission matrix are ours — they are how we gate tool access across an agent fleet, and you should adapt rather than copy them blindly.


Connecting an MCP server feels like adding a dependency. It is closer to granting a contractor a key to the building.

The difference is that a normal dependency does what its code does. An MCP server supplies text the model reads with full trust — tool names, descriptions, parameter documentation — and that text is instruction-shaped. The model acts on it. Your user never sees it.

This is not theoretical. Tool poisoning — hiding instructions for the model inside a tool's description or parameter metadata — was the most-discussed MCP vulnerability of 2026. Trail of Bits demonstrated an attack that silently exfiltrated a user's entire chat history, including credentials, tokens and intellectual property, from a tool description alone. The Cloud Security Alliance published a research note in May 2026 characterising the issue as systemic design flaws in agent infrastructure, not isolated bugs.

So: before you connect, scope. Here is the order we do it in.

Step 1: Decide what the server is allowed to be

Before reading its tool list, write down one sentence: what is the smallest job this server needs to do?

That sentence is your scope ceiling. Everything after this step is checking the server against it. Teams that skip this step end up justifying each permission the server asks for, rather than asking whether the job needs it — and the result is predictable: a tool built to read one table ends up with write access to an entire database, simply because nobody scoped its credentials down after the initial build.

Step 2: Read every tool description as if it were user input

Not the tool names — the full descriptions, including parameter descriptions, enum values and any examples blocks. Dump the raw tool list and read it as text.

You are looking for anything that reads as an instruction to the model rather than a description of a function:

A legitimate tool description describes inputs and outputs. If it describes behaviour you should perform, treat the server as hostile until proven otherwise.

Automate the dump, not the judgement. Store the full tool manifest as a file in your repo. That turns step 2 into a reviewable diff, which is what makes step 6 possible.

Step 3: Scope the credential, not the tool

The tool asks for what it wants. The credential decides what it gets. Only the second one is enforceable.

For each tool the server exposes, issue a credential that satisfies the scope sentence from step 1 and nothing beyond it:

Tool wants Issue instead
database connection string a read-only role, scoped to named tables, with a statement timeout
repository access a token scoped to one repo, read-only, no org scope
cloud account credentials a role with a resource-level policy and no * actions
"API key" a key from a sub-account with its own rate limit and spend cap
filesystem access a bind-mounted subdirectory, read-only where possible

If the provider cannot issue a credential narrower than "everything", that is a finding. Record it and decide explicitly whether the job is worth it — do not let the gap pass silently because the integration was convenient.

Step 4: Put the dangerous half behind a human

Not every action needs approval. Approval fatigue is a real failure mode: a reviewer who confirms forty prompts an hour is a rubber stamp, and a rubber stamp is worse than no gate because it creates a record that implies review happened.

So split actions by reversibility and blast radius, not by how scary they sound:

Class Examples Gate
Read, scoped query a read-only table, fetch an issue, read a file in-scope auto-allow, log
Write, reversible, bounded create a draft, open a PR, write to a scratch path auto-allow, log, keep the undo path
Write, irreversible or unbounded delete, force-push, send an email, charge a card, change permissions always ask
Anything that touches identity or money rotate a key, add a user, modify a policy, move funds always ask, and name the approver in the log
Egress to an unapproved destination HTTP to a domain not on the allowlist block, do not ask

The last row matters more than it looks. Exfiltration needs a destination. An agent that cannot reach an arbitrary host cannot leak to one, regardless of what a poisoned tool description tells it to do. Domain allowlisting is the single highest-leverage control on this list because it defends against attacks you have not thought of yet.

Step 5: Authenticate properly, and centralise the tokens

For remote servers, the 2026 baseline from the security literature is narrow and specific:

One specific trap if you are building or proxying: the confused deputy attack. When an MCP proxy uses a static client ID against a third-party authorisation server and lets clients dynamically register against that same server, an attacker can craft an authorisation request that reuses an existing consent cookie — and the user is never asked to consent again, because as far as the authorisation server is concerned, they already did. If you operate a proxy, do not share one static client ID across dynamically registered clients.

Step 6: Pin the manifest and watch it for changes

This is the step almost everyone skips, and it is the one that catches the attack that gets past steps 2–5.

Tool definitions are mutable. A server that was clean when you reviewed it can push a new description tomorrow, and nothing in the protocol makes that visible to you. Mitigating tool poisoning requires version pinning, signed tool definitions where available, and continuous monitoring for tool-definition changes across every connected server.

Practically:

  1. Pin the server version. No floating latest.
  2. Commit the tool manifest from step 2 to your repo.
  3. Re-fetch it on a schedule and diff it against the committed copy.
  4. Fail the build — or disconnect the server — on an unreviewed diff.

A changed tool description should be as loud as a changed lockfile. Today, in most setups, it is completely silent.

The 10-minute version

If you connect a server today and have ten minutes:

Seven lines. The first and the last are the two that teams skip, and they are the two that do the most work: the first prevents scope creep by making it visible, and the last is the only control that survives the server changing after you reviewed it.

What this does not protect against

Honesty about the limits, because a checklist that implies completeness is its own risk:

Scope reduces blast radius. It does not make an agent trustworthy. Those are different problems, and the second one is solved with evals and review, not with permissions.


Sources

Not tested hands-on: we did not reproduce the published attacks. The threat descriptions are sourced above; the checklist, the action-class table and the credential-scoping table are our operational practice.

← All articles