Roles & Permissions
The ladder, briefly
Four roles, each including everything below it: viewer < commenter < editor < owner. A viewer can read a canvas's state but never change it. A commenter can read and can write, but its writes never apply directly — they become proposals for someone else to act on. An editor and an owner can both apply a write immediately; the distinction between those top two matters for administrative actions rather than for day-to-day drawing. The full ladder, and exactly what each role returns from a write call, is in Canvas Roles — this page is about what the ladder means for how you actually work with it.
There is no default
An agent with no explicit grant on a canvas is not treated as a viewer, and it is not treated as having no access in a way that fails silently. It gets a clear error the moment it calls any canvas_* tool against that canvas. Nothing about being in the same workspace, having a role on a different canvas, or having called canvas_list successfully changes this — each canvas's grants are its own.
This is deliberate, not an oversight: see Explanation: Canvas Model for why an ambient default was rejected in favor of requiring every grant to be a decision someone actually made.
Getting a role onto a canvas
This is the part the tool surface doesn't cover. No canvas_* tool grants or changes a role — check MCP Tools's table and you won't find one — and that means a role has to already be in place by the time an agent makes its first call. If you're integrating a new agent against a canvas and its very first call comes back refused, that is the first thing to confirm: not whether the call itself is malformed, but whether anyone has actually granted this agent a role on this specific canvas at all.
What each role changes in practice
| Role | Reading | Writing |
|---|---|---|
viewer | Full read access — canvas_list, canvas_get_state, canvas_query_region all work | Every write tool returns rejected |
commenter | Same as viewer | A write is accepted but never applied directly — it comes back as proposed, pending someone else's approval |
editor | Same as viewer | A write applies immediately, subject to the same revision check every role's writes go through |
owner | Same as viewer | Same as editor for ordinary writes; administrative actions (where they exist) are reserved for this level |
Every write, at every role, still has to carry a valid expectedRevision and a clean, single-line reason — role only decides whether an otherwise-valid write applies, proposes, or is refused outright. See Revisions & Conflicts for the revision side of that, and Proposals & Approval for what happens after a commenter's write is accepted as a proposal.
Debugging a rejected outcome
A rejected outcome carries a reason. Two causes produce it, and they're fixed differently:
- Role too low — the calling agent's role doesn't allow this action at all (a
viewerattempting any write, most commonly). Fix: get the role raised, then retry the same call unchanged. - Malformed
reasonargument — the write's ownreasonfield contained a newline or a control character and was rejected outright rather than cleaned up. Fix: resend with a single clean line; nothing about role is at issue here.
Neither of these is the same problem as a conflict outcome, which is about a stale revision, not about permission — see Revisions & Conflicts for that distinction in more detail.
Where to go next
- Canvas Roles — the authoritative ladder and outcome contract.
- Creating & Sharing — where a canvas's visibility comes from, separate from its roles.
- Proposals & Approval — what a
commentercan actually accomplish without ever holdingeditor.