A tool is a named, permission-gated capability an agent can invoke. They live in one shared registry with two consumers: the copilot’s run loop, and the MCP endpoint.
That is deliberate. A tool added for either is available to both, and neither can acquire a private set of rules.
The catalogue
Content, read
| Tool | Does |
|---|---|
admin_content_types | The content types available, with their filterable fields |
admin_content_search | Search, filter, sort, page, locale, sparse fields |
admin_content_get | One entry |
admin_content_revisions | An entry’s version timeline |
admin_content_diff | The changed fields between two versions |
Content, write
| Tool | Does |
|---|---|
content_propose_create | Draft a new entry |
content_propose_update | Draft an edit to one entry |
content_propose_bulk_save | Draft edits across several entries as one change |
Localization and media
| Tool | Does |
|---|---|
i18n_locales_list, i18n_translations_get | Read locale state |
i18n_propose_translation, i18n_propose_bulk_translation | Draft a translation |
media_assets_search, media_asset_read, media_folders_list | Read the library |
media_propose_alt_text, media_propose_file | Draft an asset change |
Notice what is absent: there is no publish tool, and no bulk delete. See the authority model.
Three enforcement points
A call passes three gates, and they are not redundant.
- Offer time. The capability profile is resolved per run from the caller’s live permissions. A tool the caller could not use is not offered to the model at all.
- Permission prompt. A tool that changes something parks the run and asks, unless this conversation already allowed it.
- Execution. The registry authorises the call against live grants. This is
the analogue of
@RequirePermissionson an HTTP route, and it is the one that actually decides.
Gate 1 shapes what the model tries. Gate 3 is the boundary. A model that invents a tool name it was not offered gets an error, not an execution.
content_propose_bulk_save is one change, not a loop
“Translate these eight posts” used to be eight tool calls — eight steps against a bounded run, and eight cards in the transcript for one instruction, none of which said what the other seven were.
The bulk tool takes a list and produces one change with one receipt. It reads every edited entry at propose time so the card carries a real diff, drops fields that would not actually change, and drops an item left with nothing.
That last part matters more than it sounds: writing an entry its own current values still appends a version and takes a live entry back to draft. A model re-sending twenty unchanged records would unpublish twenty live pages.
The applier writes items one at a time and stops at the first failure, reporting how many landed — a proposal is one row with one status, so carrying on would grow the number of entries written under a receipt that then reports failure.
An edit that reaches other locales says so
On a localized type, a field the type does not mark localized is shared, so
writing it propagates to every sibling in the translation group.
The write tools ask the localization plugin what a change would reach — against the patched values, so the disclosure names what will actually be written — and fold the answer into the change summary. That summary is the card’s title, the audit row, and the receipt the model sees, so one string reaches the person, the log, and the model.
The model correcting itself — “that touched every language; a translation wants
i18n_propose_translation” — is worth as much as the card.
Surfaces
A tool declares which surfaces it is offered to: copilot, mcp, or both.
Omitting the field means both. So adding a tool anywhere means deciding who it is for — an internal admin tool that leaks onto the MCP endpoint is a tool an external agent can call with a bearer token.
The admin_* tools are copilot-only. The MCP surface gets its own generic set;
see the MCP endpoint.
Untrusted content is fenced
Content the model reads — entry bodies, tool output — is passed inside a fence marking it as data rather than instructions.
This raises the cost of an injection. It does not eliminate it, and it is not claimed to. See the warning on the authority model.