Noon Docs · Getting Started · Concepts · Guides · Reference

Every administrative action in Noon is an MCP tool call. This page tells you what each tool is for, which arguments matter, and what it gives back.

Reads all go through one tool, query. Writes are separate typed tools, one per kind of change. Schemas are discoverable at runtime: call describe_schema to get the live collections, the page block schemas, and the post frontmatter schema for the install you are connected to.

Tools at a glance

Core tools are always present. Plugin tools appear only when their plugin is enabled on the install. Call tools/list on your connection to see exactly what this install offers.

ToolScope neededWhat it is for
describe_schemacontent:read or content:writeDiscover collections, fields, and block schemas
queryper collectionRead anything
create_pagecontent:writeCreate a page draft
update_pagecontent:writeReplace a page's draft
create_postcontent:writeCreate a post draft
update_postcontent:writeReplace a post's draft
publishcontent:writeTake a draft live, take content off site, batch, or schedule
discard_draftcontent:writeThrow away a pending draft
list_versionscontent:read or content:writePublished version history
diff_versionscontent:read or content:writeWhat changed between two versions
rollbackcontent:writeRestore an old version as a draft
manage_templatecontent:writeCreate, update, or unpublish a region template
explain_template_resolutionquery:read or content:readFind out which template renders at a path, and why
manage_sitecontent:writeReplace the site settings document
manage_connectionsecrets:writeCreate, update, rotate, or revoke a stored credential
manage_content_typecontent:writeDefine types, write entities, assign terms, move a site spine
revoke_tokenrootRevoke a session token by id
manage_geo_rulecontent:writeCountry rules (needs the geo plugin)
create_productcontent:writeAdd a shop product (needs the shop plugin)
update_productcontent:writeChange a shop product (needs the shop plugin)
manage_themecontent:writeSite design tokens and fonts (needs the theme plugin)
manage_pollcontent:writePolls and tallies (needs the vote plugin)

A token with the root scope passes every scope check.

Discovery

describe_schema

Ask the server what is valid before you write. It returns the live query collections with the where operators each field accepts, the orderable fields, the selectable JSON subpaths, the JSON Schema for page blocks and post frontmatter, and a compact list of the user-defined content types on the install.

ArgumentTypeNotes
typestring, up to 64 charsOptional. Name a content type to get only that type's field schema and its where-capable paths
{ "name": "describe_schema", "arguments": { "type": "recipe" } }

Prefer this over any list frozen into documentation. It always describes the install you are actually talking to, including the plugins it has enabled.

Reading

query

One tool reads every collection. The request goes in a single document argument.

FieldRequiredNotes
collectionyesCollection name, from describe_schema
selectyesArray of field names or JSON subpaths. At least one
wherenoMap of field name to a value, or to {op, value}
orderBynoArray of {field, dir}, dir is asc or desc
limitnoDefaults to 20
cursornoOpaque cursor from a previous response, to get the next page

Operators are eq, ne, in, gt, gte, lt, lte and contains. A bare value means equality. in takes an array. contains takes a string.

{
  "name": "query",
  "arguments": {
    "document": {
      "collection": "posts",
      "select": ["id", "slug", "title", "updatedAt"],
      "where": { "isPublished": true, "title": { "op": "contains", "value": "release" } },
      "orderBy": [{ "field": "updatedAt", "dir": "desc" }],
      "limit": 10
    }
  }
}

See Reading data with query for the collections, the pagination rules, and the limits.

Writing pages and posts

Every write lands as a draft. Nothing reaches the live site until you call publish.

create_page

Creates an unpublished page draft.

ArgumentRequiredNotes
slugyesThe page address. Slug home serves /
titlenoPage title
layoutno{blocks: [...]}, see Blocks
upsertnotrue creates the page or updates the existing one with that slug

Returns {id, version, revision, previewUrl}. Open previewUrl to see the draft before it is live.

{
  "name": "create_page",
  "arguments": {
    "slug": "pricing",
    "title": "Pricing",
    "layout": {
      "blocks": [
        { "type": "HeroSection", "props": { "headline": "Simple pricing" } },
        { "type": "RichText", "props": { "markdown": "Three plans. No contract." } }
      ]
    }
  }
}

update_page

Overwrites the page's pending draft with a complete {title, layout}. This is a replace, not a merge: send the whole layout, not just the block you changed.

ArgumentRequiredNotes
idyesThe page id
expectedRevisionyesThe revision you last read
slugnoChanging the slug applies immediately, not on publish
titleno
layoutno

Returns {id, version, revision, previewUrl}.

If someone else wrote first, the call fails with revision_conflict and the error carries currentRevision. Read the page again, reapply your change, and retry with the new revision.

create_post and update_post

The same pair for posts. A post carries a raw MDX body and an optional frontmatter object instead of a layout.

create_post takes slug (required), title, body, frontmatter and upsert. update_post takes id and expectedRevision (both required) plus slug, title, body and frontmatter, and it replaces the whole draft.

{
  "name": "create_post",
  "arguments": {
    "slug": "shipping-v2",
    "title": "Shipping v2",
    "body": "We shipped it. Here is what changed.\n\n## Faster builds\n\n...",
    "frontmatter": {
      "description": "What changed in v2.",
      "tags": ["release", "engineering"],
      "author": "Marcus"
    }
  }
}

Call describe_schema for the frontmatter fields this install accepts.

Lifecycle

publish

One tool covers going live and coming off site.

ArgumentNotes
entityTypepage, post, template or custom
idThe entity id
expectedRevisionRequired for publish and unpublish
actionpublish (the default), unpublish, batch or schedule
opsFor action: 'batch'. 1 to 50 operations
runAfterMsFor action: 'schedule'. Epoch milliseconds

action: 'publish' re-validates the stored draft, increments version, clears the draft, and stores a version snapshot you can diff and roll back to.

action: 'unpublish' takes the entity off the site. The draft, the published fields and the version history are all kept, and the URL stays reserved.

action: 'batch' runs 1 to 50 operations in one transaction, all or nothing.

action: 'schedule' queues the publish instead of doing it. runAfterMs is the earliest instant, not a deadline. A later background pass publishes whatever the draft is at that moment, so an edit made after scheduling is the one that goes live. Scheduling again replaces the pending schedule rather than adding a second one.

{
  "name": "publish",
  "arguments": { "entityType": "page", "id": "pg_01H...", "expectedRevision": 4 }
}

discard_draft

Drops the pending draft and leaves the published content alone. Takes entityType, id and expectedRevision.

list_versions

Returns the published version headers for an entity, ascending, as [{versionNo, createdBy, createdAt}]. An entity that has never been published returns an empty list. Takes entityType and id.

diff_versions

Returns [{path, before, after}] for every changed leaf between two stored versions. An empty array means the two versions are identical. Takes entityType, id, from and to.

{
  "name": "diff_versions",
  "arguments": { "entityType": "post", "id": "po_01H...", "from": 3, "to": 4 }
}

rollback

Restores a stored version as the entity's pending draft. The live site does not change. Review the preview, then publish to make the restored content live.

Takes entityType, id, versionNo and expectedRevision. Returns {id, version, revision, previewUrl}.

Structure and settings

manage_template

Templates hold the furniture that repeats across pages: the header, the footer, the sidebar, and the body layout of a blog post. A template body is the same {blocks: [...]} shape as a page.

ActionArguments
createslug, title, type, body
updateid, expectedRevision, title, body
unpublishid, expectedRevision

conditions is optional on create and update. It scopes where a template renders, as {pathGlob?, country?}, and it applies immediately rather than waiting for a publish.

unpublish keeps the published body so you can put it back later. It returns an outcome plus regionBecameEmpty, which tells you whether that slot now has nothing left to render.

Call describe_schema for the template types this install accepts. Read templates with query.

explain_template_resolution

Read-only. Ask which template would render at a path, and why.

Takes {path, country?, type?}. It returns the raw and normalized request, and per template type: the winner or none, every published candidate, the result of each condition clause, the specificity of each candidate, and for each loser the first thing that decided against it. A malformed path or a corrupt stored condition still returns a definite answer instead of an error.

{
  "name": "explain_template_resolution",
  "arguments": { "path": "/docs/getting-started", "country": "DE" }
}

manage_site

Replaces the site settings singleton. Send the complete document: any optional value you omit resets to its default.

ArgumentNotes
settingsThe complete settings document
expectedRevisionOmit only on the very first write. Required afterwards

Read the current settings with query on the site_settings collection first, so you can send back a full document rather than accidentally clearing a key.

Credentials

manage_connection

A connection is a stored credential plus its configuration, referenced by id from content. A FormBlock points at an SMTP connection to send its notification email, for example.

ArgumentRequiredNotes
actionyescreate, update, rotate or revoke
inputyesThe action's payload

Secrets are write-only. They go in through this tool and never come back out. query on the connections collection returns the metadata only. See Connections and secrets for the kinds and their fields.

Content types and entities

manage_content_type

One tool for user-defined content. action selects the operation and input carries its payload.

ActionWhat it does
define-typeCreate a content type from a definition of fields
update-typeChange a type. Needs expectedRevision
create-entityCreate an entity of a type, as a draft
update-entityReplace an entity's draft
delete-entityRemove an entity. Needs expectedRevision
list-referencesReport what points at an entity, without attempting a write
assign-termsLink entities to taxonomy terms
unassign-termsRemove those links
export-bundleWrite the site spine to a named file on the server
import-bundleRead a named spine file back in

A taxonomy is an ordinary content type, and a term is an ordinary entity of it. Read types and entities with query.

delete-entity only removes a custom entity that nothing references and that has never been published. Once an entity has published it holds a permalink, and that blocks deletion permanently. Call list-references first to find out what is in the way.

Publishing is not an action here. Use the ordinary lifecycle tools with entityType: 'custom': publish (with action: 'unpublish' for the reverse), discard_draft, rollback and list_versions.

{
  "name": "manage_content_type",
  "arguments": {
    "action": "create-entity",
    "input": {
      "type": "recipe",
      "slug": "sourdough",
      "title": "Sourdough",
      "data": { "prepMinutes": 30, "difficulty": "medium" }
    }
  }
}

A bundle moves a site's spine: content types, the taxonomies you name and their terms, templates, the theme and the site settings. It carries no entities, no assets and no version history, so a bundle is not a backup. The tool exchanges a bundle name that refers to a file on the server, and never the bundle bytes. export-bundle requires taxonomies as a list of type names, because nothing stored marks a type as a taxonomy. import-bundle creates drafts and publishes nothing, and on any collision it writes nothing at all and returns a conflict report.

Tokens

revoke_token

Revokes a session token by its id. The id is the non-secret handle, not the token itself. Root only. It is idempotent and returns {tokenId, revoked}, where revoked is false when the token was already revoked or was never known.

Plugin tools

These exist only when the plugin is enabled. See Plugins.

manage_geo_rule (geo)

Manages one geo content rule. action: 'upsert' creates or updates the active rule for a country, given as a two-letter uppercase code, or ** for the default rule. Updating or deactivating a rule needs id and expectedRevision. A country may have at most one active rule. action: 'delete' removes a rule by id. Read the rules with query on geo_rules.

create_product and update_product (shop)

create_product takes slug, name, description, priceCents, currency and active. When Stripe is configured a reusable hosted checkout link compiles automatically. Without it the product still saves, with checkoutStatus set to unconfigured.

update_product takes id and expectedRevision plus the same fields. Changing the price or the content recompiles the checkout link and retires the old one. Set active: false to soft-delete a product, which also deactivates its live link. Calling it again retries a compile that failed.

manage_theme (theme)

action: 'set' replaces the token object. It is a replace and not a merge, so send every token you want to keep. Sending tokens: {} returns the list of valid keys. action: 'clear' deactivates the theme reversibly. Both need expectedRevision once a theme document exists. action: 'register-google-font' self-hosts a libre-licensed Google family, taking family plus optional weights, key and fallback. action: 'widen-font' widens a registered weight to a range.

manage_poll (vote)

action: 'create' takes slug, question, closesAt as an ISO timestamp, and options, plus optional allowSuggestions, multiple, maxOptions, orderBy, lang and captchaConnectionId. action: 'update' edits those, and multiple can only change before the first vote is cast. action: 'close' ends the poll now. action: 'add-option' and action: 'remove-option' change the choices, and removing one drops its votes. action: 'results' returns the tally.

When a call fails

Two failures are worth knowing before you start.

A revision_conflict means someone wrote between your read and your write. The error carries currentRevision. Read the entity again, reapply your change on top of what is there now, and retry.

A validation failure returns a list of violations. Each one names the path that was wrong and, where it can, suggests the correction. Fix the named path and call again rather than guessing at the whole payload.