# Per-tool vs per-connector restrictions: six cases

> Six worked cases for per-tool vs per-connector restrictions, the same intent written as a block list and as an allowlist, and what tool churn does to each.

**TL;DR** A per-connector restriction in Elaichi removes an entire app from a role or user, and it covers tools that do not exist yet. A per-tool restriction keeps the rest of the connector working, but it is a list you have to maintain as the connector changes. Choose per-connector when the role has no business in the app or the tool list churns, and per-tool when the role needs a narrow slice of a broad app.

## Where the per-tool vs per-connector restrictions question comes up

The per-tool vs per-connector restrictions question arrives the first time a role needs part of an app and not all of it. Support needs to read tickets and post comments. Nobody wants the Support role bulk-deleting saved views.

At that point two shapes of rule are available. Name the connector, and the whole app disappears for that role. Name individual tools, and the rest of the connector stays reachable.

MCP (Model Context Protocol) is the standard way an AI assistant calls tools in other apps A restriction in Elaichi decides which connectors and which individual tools a target may reach. Targets are roles or users only. There is no organization target. The organization default is the absence of any rule, and absence means allow-all. A rule on a user replaces the role rules for that user rather than adding to them

Inside whichever layer wins, allow rules union, block rules union, and blocks always beat allows. Everything below follows from that, plus one fact about time. A restriction change takes effect within about two minutes, not on the next call.

## Three cases where blocking the whole connector is the wrong rule

Blocking the connector is wrong when the role has a narrow and legitimate need inside it. The block removes the need along with the risk. The work then reappears somewhere you cannot see.

**The role needs one read out of a broad app.** A billing or ERP connector carries dozens of operations. A support agent may need exactly one of them, the status of an invoice. Block the connector for the Support role and the lookup goes away. The lookup does not stop happening. It moves to a chat message to finance, or to somebody pasting an invoice PDF into a personal assistant account. Block the write and delete operations instead, and leave the read in place.

**Only the destructive part is the problem.** Deletes are the subset you can actually enumerate, and MCP marks them. A read-only hint sits on reads and a destructive hint on deletes. A plain write carries no annotation, because the protocol has no hint for changing something without destroying it. If your objection to the connector is three delete operations, write three block rules. A connector-level block is a much larger claim than the one you meant to make.

**Two roles need different slices of the same app.** Finance reads billing records in the CRM. Sales updates contact details in the same CRM. One connector-level rule cannot describe both jobs. Restriction targets are roles and users, so you write two tool-level rule sets, one per role. The alternative is a single blunt rule that is wrong for one of the two teams.

The cost of all three is the same. A per-tool rule set is a list you now own. Every tool added to that connector later is a decision you have deferred to nobody.

## Three cases where naming individual tools is the wrong rule

Naming tools is wrong when the list you are naming is not the list that will exist next quarter. It is also wrong when the role should not be in the app at all.

**The role has no business in the app.** A recruiting system and a support role is the clean example. An enumerated block list against [a connector like Ashby](/connectors/ashby/) has to be complete on the day you write it, and stay complete forever. A single connector-level rule is complete by construction. It also reads correctly to an auditor, who can see the intent without reconstructing it from twelve tool names.

**The connector's tool list churns.** Custom connectors are authored from JSON config, can be forked from a public connector, and can pull upstream changes through a review surface. That surface separates new tools, safe updates, config diffs, conflicts and upstream removals. New tools are a normal outcome of a pull, not an exception. A block list written in March does not name the tool that arrives in June, and absence of a rule means allow. The connector-level block covers the June tool without anyone remembering it exists.

**Somebody forked the connector.** The `connector:create` permission is flagged high trust for a reason, because a custom connector can be pointed at any destination. A forked connector's identity includes its declared lineage, walked to the root, applied block-only, and failing closed if the chain is truncated or cyclic. A block on the parent connector reaches the fork. The host a connector dials is deliberately not an identity signal, so do not plan your rules around hostnames.

The cost here is bluntness. A connector-level block generates exception requests, and the exception is a user-targeted rule, which replaces that member's role rules rather than adding to them.

## The same intent, written as a block list and as an allowlist

Take one intent. The Support role may read helpdesk tickets and may not delete anything in the helpdesk.

As a block list, you block the delete operations on that connector for the Support role. Reads and plain writes stay. A tool added next quarter is reachable the day it lands.

As an allowlist, you allow the ticket read operations for the Support role. the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything. Everything else on that connector is denied, including tools that do not exist yet.

Two consequences follow. The allowlist fails closed on churn and the block list fails open. And an allow rule that names nothing denies everything. That is the strictest rule the system can express, and the one that looks least strict in a console list.

Pick the allowlist when the boundary is narrow and the app is broad, such as a rule that lets a team create tasks in [Asana](/connectors/asana/) and reach nothing else there. Pick the block list when the role needs most of the app and you are removing a handful of operations.

## Why a block matches the name and an allow matches only the operation

A rule is written against a connector and a tool, but the canonical resource and method are pinned against the catalog at write time. A block then matches on the tool name or the pinned operation. An allow matches on the pinned operation only.

The reason is worth repeating to anyone who asks. A tool's advertised name can be changed by whoever edits the connector's documentation, so the name is a token the governed party controls. Governance binds the operation, never the label. The longer version, with the cases where the asymmetry changes an outcome, is in [names versus pinned operations](/blog/block-matches-name-allow-matches-operation/).

## When the risk is the argument, not the tool

Some risks do not live in a tool at all. Two Notion workspaces, one of which is the board's. One production ledger and one sandbox. The tool is fine. The target is not.

Freeze the parameter on the toolbox entry rather than writing a restriction. A frozen key is stripped from the advertised schema, so the model never sees it. The frozen value is merged over caller arguments at execution, so passing the key cannot un-freeze it. Precedence runs entry defaults first, then caller or model arguments, then frozen parameters last.

Restrictions and frozen parameters answer different questions. A restriction decides which tool the agent may call. A frozen parameter decides what that call is allowed to point at.

## Breadth of the connector against churn in its tool list

Two questions decide the shape of the rule. How much of this connector does the role legitimately need, and how often does the connector's tool list change.

- Needs most of it, stable list. Block the handful of destructive tools. Short, readable, easy to defend.
- Needs a slice, any churn rate. Write an allowlist of the pinned operations. New tools stay outside it until a person puts them inside.
- Needs none of it. One connector-level block. Forks of that connector are covered through declared lineage.
- Needs most of it, and the list churns. No rule shape solves this. Block the destructive operations, then put the connector's pull review on a cadence, because new tools land allowed by default.

The fourth row is the honest one. Breadth plus churn is a review problem wearing a permissions costume, and writing more rules does not convert it into a permissions problem.

One trap is worth naming before you start. If a member needs a single exception to a role rule, the user-targeted rule you write replaces the role rules for that member entirely. Restate everything from the role rule that still needs to hold, or the exception quietly widens more than the one tool.

## What happens after you save the rule

A restriction change takes effect within about two minutes, on every surface, MCP and console and REST alike. Role membership resolves the same way. Only grant revocation, member removal and suspension are effective on the next call. The grant's revocation state is re-read from the organization store on every single call, and removing or suspending a member revokes every live grant in the same transaction.

The rule is then checked at four points against the same resolver: browse, connect, advertise and execute, plus a final check on the fully substituted outbound URL. A final check runs on the fully-substituted outbound URL. A tool withheld by a restriction is also excluded from the count that triggers dynamic tool discovery, and `search_tools` cannot surface it, because it was handed to nobody. `execute_tool` is only a naming indirection. It unwraps to the same name and arguments and falls through the identical gates. The ranking that decides what `search_tools` returns, and why it has a relevance floor, is covered in [the piece on search ranking](/blog/search-tools-ranking-floor-idf/).

Afterwards you get one entry per tool-call attempt, succeeded or failed. Both name the account actually reached, taken from the execution rather than from the intent. Argument names and counts are recorded. Argument values never are, and the audit record carries an error code rather than the third party's error text.

## When neither rule is worth writing

Often the right rule is no rule. If one team uses one connector, and everyone on it has the same trust and the same job, the role assignment plus the audit trail already answers the question you are trying to answer. Restrictions are how you split an app between people who should see different parts of it. With nothing to split, they add review burden and nothing else.

Three roles need no restriction at all. Guest, Auditor and Billing Admin lack `tool:execute`, which gates the whole endpoint ahead of every scope. For them `tools/list` is empty and a call returns an in-band error naming the permission. A connector block written against the free read-only Auditor seat governs nothing that was reachable.

If the wider question is whether any of this is needed yet, [the case for waiting](/blog/when-you-dont-need-an-mcp-gateway/) is worth reading before you write your first rule. For a worked example of a single team set up end to end, see [Salesforce access for a sales team](/blog/sales-team-chatgpt-salesforce-accounts/). More on rule design sits under [governance](/blog/category/governance/), the apps you can write rules against are in the [connector catalog](/connectors/) of 450+ connectors, and the per-team starting points are on the [use cases page](/use-cases/).

## FAQ

### What is the difference between a per-tool and a per-connector restriction?

A per-connector restriction targets an entire app, so every tool that connector exposes is covered, including tools added to it later. A per-tool restriction names individual tools, so the rest of the connector stays reachable and any new tool arrives outside the rule. In Elaichi both are written against a role or a user, and blocks always beat allows inside the layer that wins.

### Does blocking a connector also cover tools added to it later?

Yes. A connector-level block covers every tool that connector exposes, including tools added after the rule was written, because the rule names the connector rather than a list of tool names. A per-tool block list does not. The organization default is the absence of a rule, and absence means allow, so a newly added tool is reachable until somebody adds it to the list.

### What happens if an allow rule names no tools?

It denies everything on that target. the allowlist stage engages on the presence of an allow rule, not its contents, so an allow rule that names nothing denies everything, so an allow rule with nothing in it is the strictest rule the system can express. It is also the easiest one to write by accident, because an empty list does not look restrictive in a console.

### How long does a restriction change take to take effect in Elaichi?

about two minutes. Restrictions and role membership resolve through a 60 second cache plus edge propagation, and reach every surface, MCP and console and REST alike, within roughly that window. Only grant revocation, member removal and suspension are effective on the next call, because the grant's revocation state is re-read from the organization store on every call.

### What is the smallest scope a restriction can target?

No. Restriction targets are roles and users only. There is no organization target, because the organization default is the absence of any rule, and absence means allow-all. To cover everyone, write the rule against the roles people actually hold, remembering that a user-targeted rule replaces that member's role rules rather than adding to them.

## Read next

- [How to narrow to least privilege MCP tool calls](/blog/least-privilege-tool-calls-without-breaking-automation/) — Narrow to least privilege MCP tool calls using the audit rows your pilot already produced, then plan the two-minute wait and the verification call that proves the rule landed.
- [SOC 2 evidence for AI agents: CC6 and CC7](/blog/soc2-evidence-ai-agents-cc-controls/) — SOC 2 evidence for AI agents maps onto CC6.1, CC6.2, CC6.3 and CC7.2. Here is the artifact for each, plus the criteria a governed MCP endpoint does not touch.
- [MCP tool name vs pinned operation restriction](/blog/block-matches-name-allow-matches-operation/) — MCP tool name vs pinned operation restriction: a block rule matches a tool's label or its operation, and an allow rule matches only the operation. Here is why.
