Skip to content

Scopes and tools ​

An API key carries scopes of the form <domain>:<verb>, with read, write or * as the verb, and write covers read. The grammar and the full list of domains are in API scopes. This page says how the MCP server reads them.

A scope never grants more than the member who owns the key: an ordinary member's key with tables:write still cannot create a table, because that member cannot.

The domain of each tool ​

The server derives the required scope from the tool's name and effect: the prefix of the internal name gives the domain, the effect gives the verb.

Tool prefixDomainTools
catalog., docs., workflow.workflowscatalog_describe, catalog_node, docs_search, docs_read, workflow_list, workflow_read, workflow_describe, workflow_validate, workflow_compile, workflow_propose_new, workflow_propose_changes (read); workflow_create_draft, workflow_update_draft, workflow_publish (write)
execution.executionsexecution_list, execution_read (read)
workflow.test_run (exception)executionsworkflow_test_run (write)
mailbox., journal., coverage.mailboxesmailbox_list, mailbox_stats, mailbox_cluster, mailbox_search, journal_unmatched, coverage_simulate (read)
connections.connectionsconnections_list (read)
tables.tablestables_list (read); tables_create (write)

A read tool requires <domain>:read; a write tool requires <domain>:write. One exception: workflow_test_run writes nothing outside, but it creates an execution and makes the AI nodes call their model, which costs money. It requires executions:write, the scope of the matching REST route POST /workflows/{id}/test, so a read-only key cannot spend. A key satisfies a requirement when it holds the exact scope, the write scope of the domain for a read requirement, or the domain's *. The other domains of the API (messages, contacts, admin…) have no MCP tool today.

Each tool's description in tools/list ends with the scope it needs, for example "Requires scope workflows:write.", so an assistant can explain a refusal to you.

How tools/list is filtered ​

tools/list returns only the tools the key may call. A key with workflows:read lists the eleven read tools of the workflows domain and nothing else: no workflow_publish, no mailbox_list. Announcing a tool that would then be refused would send the assistant in circles.

Through a browser session instead of a key, the member has every scope their role allows, and the full list appears.

The shape of a refusal ​

A client can call a tool without listing it, so tools/call checks the scope again. A refusal is not a protocol error: it is a tool result with isError: true, so that the assistant reads it and reacts.

json
{
  "isError": true,
  "content": [
    { "type": "text", "text": "{\"error\":{\"code\":\"api_key.scope_missing\",\"message\":\"this key lacks the scope workflows:write required by workflow.publish\"}}" }
  ],
  "structuredContent": {
    "error": {
      "code": "api_key.scope_missing",
      "message": "this key lacks the scope workflows:write required by workflow.publish"
    }
  }
}

The same shape carries the other refusals. code is stable and meant for programs:

CodeMeaning
api_key.scope_missingthe key lacks the scope the tool requires
tool.not_foundno tool has this name
tool.invalid_inputthe arguments do not match the tool's inputSchema (unknown field, wrong type, bound exceeded)
tool.resource_not_foundthe workflow, mailbox, execution, node type or page does not exist or belongs to another member
workflow.archived, workflow.invalid_graph, and other workflow.… codesa business refusal: an archived workflow cannot be edited, a stored graph is unreadable, a draft cannot be test-run because it is invalid

Two outcomes are not refusals: workflow_publish answering ok: false with the blocking errors, and workflow_propose_changes answering ok: false with a rejected operation. Both are normal results that describe what to fix.

Without a valid key, the request never reaches MCP: the endpoint answers 401 with auth.unauthenticated in the error format of the API. An expired or revoked key gets the same answer.

Example keys ​

A read-only analyst. An assistant that explains a mailbox, proposes automations and diagnoses failed runs, without ever changing anything:

text
workflows:read   executions:read   mailboxes:read   connections:read   tables:read

It can describe the catalog, read every workflow, compile and propose, read executions, search and group emails, and see which connections and tables exist. It cannot run a test run (that takes executions:write), nor create, update or publish a workflow, nor create a table.

A builder. An assistant that builds workflows end to end, with publication:

text
workflows:write   executions:write   mailboxes:read   connections:read   tables:read

workflows:write covers the read tools of the domain: read, propose, create the draft, update it, publish it. executions:write adds the test runs on real emails. Keep tables:read unless the member is an administrator who wants the assistant to create tables, in which case give tables:write.

A key for one job. Scopes are per domain, so a key can be narrower still: mailboxes:read alone for an assistant that only reports on mailboxes, or workflows:read plus executions:read for one that only investigates failed runs.

Give a key an expiry when you create it if it serves a one-off task, and revoke it afterwards: the next call is refused.