Skip to content

Scope and Tool Matrix

Jm Rohmer edited this page Jul 18, 2026 · 5 revisions

Scope and Tool Matrix

Tool IDs are stable API identifiers. Client-facing UX should be improved through title, description, and MCP annotations, not by renaming stable IDs.

The authoritative, up-to-date inventory is docs/tools.md in the repository — this wiki page intentionally does not duplicate the full tool list anymore (it drifted out of sync with reality before, see below) and instead summarizes the current scope model and points there.

Current scope model: 2 tiers (since #450)

As of #450, the server enforces exactly two internal scopes, read and write — the older four-tier model (content.read/content.write/site.admin, described further down as a historical note only) no longer exists in the running server.

  • Anonymous (no scope required at the ACL layer): 9 public read-only tools (list_pages, get_page, search_pages, get_recent_posts, list_tags, list_categories, get_sitemap, get_feed, get_site_information). Not the same as "reachable with zero bearer token" in production — see the correction note below.
  • read: no scope required at the ACL layer beyond holding any valid token — auto-registered/self-service, no client secret needed. Includes every Anonymous tool plus all richer read tools (get_page_for_edit, get_related_content, search_content, get_site_health, diff_page, inspect_rendered, validate_site, etc. — see docs/tools.md for the full current list). This tier grants full source visibility, including drafts — there is no longer a separate restricted "reader" profile.

Correction (2026-07-18, #498). "No auth"/"ungated" above describes the scope-ACL layer only (which tools a token is allowed to call), not whether a bearer token is required to reach /mcp at all. With OAuth enabled (production's actual config), every /mcp request without a bearer gets a 401 challenge, regardless of which tools it would otherwise resolve to — confirmed live. read (including these "Anonymous" tools) is obtained via self-serve DCR + PKCE, never via a bearerless request. See Pitfall Anonymous vs Authenticated Server for the full detail.

  • write: requires a registered OAuth client (secret + entry in oauth-clients.yaml). Implies read plus everything that used to require a separate site.admin tier, with no exceptions — mutation tools (create_page/update_page/delete_page/upload_page_asset/delete_page_asset), build/site-ops tools (build_site, preview_build, create_preview, run_post_build_hooks), and diagnostics (get_runtime_status, get_theme_status, verify_publication, check_sri_versions) are all under this single tier now.

Legacy scope strings from the old model (content.read, content.write, site.admin, system.admin, mcp, reader, admin, and others) are still accepted as compatibility aliases and normalize to read or write — see docs/mcp-contract.md §6.12 for the exact alias table. They are not advertised as canonical tiers anymore.

get_related_content still separates:

  • translations: same content, other language variants
  • related_pages: editorially related content
  • backlinks: structural incoming links
  • suggested_links: editorial link suggestions
  • impact (opt-in via include: ["impact"], #434): taxonomy-orphan check, sitemap/feed presence, redirect aliases — a pre-mutation impact summary

Translations should never be mixed into related_pages or suggested_links.

Required MCP Annotation Rules

  • Read tools: readOnlyHint=true, destructiveHint=false.
  • Create/update/build tools: readOnlyHint=false.
  • Delete tools: destructiveHint=true.
  • openWorldHint=false unless the tool contacts external systems.
  • idempotentHint=true only when repeating the call does not change state.

Regression Checks

Expected smoke behavior:

  • anonymous tools/list: public read-only tools only.
  • read (no scope required): full read surface, no write/admin tools.
  • write: full read surface plus every mutation/build/admin/diagnostic tool.
  • legacy scope aliases (mcp, content.read, reader, etc.): behave like read.
  • legacy scope aliases (content.write, site.admin, system.admin, admin, etc.): behave like write.
  • direct tools/call must enforce authorization even if a client guesses a tool name.

Historical note: the pre-#450 four-tier model

Before #450, this page (and the running server) distinguished four tiers: Anonymous, content.read, content.write, site.admin. That model is gone from the live server — kept here only so old links/discussions referencing "content.read" or "site.admin" as if they were still separately enforced aren't misread as current behavior. If you find another wiki page still describing the four-tier model as active, it's stale; fix it the same way this page was fixed.

Clone this wiki locally