---
title: Drive the site with MCP tools
description: Run real operations through the MCP server, in the right order, with the right wrappers, without turning fifty items into fifty round-trips.
updated: 2026-08-19
---

[Connecting an agent](/en/docs/connect-agent-mcp) gives you the tools. This page is about using them: the sequence a session follows, the write shapes, and the batching that decides whether an import takes two minutes or twenty.

<div class="q-callout q-callout-note"><i class="fa-solid fa-flask lead"></i>
  <div><b>Live example: Oscilla.</b> The sequences below are the ones used on <b>Oscilla</b>, a bilingual SaaS demo site with fourteen content-types, a changelog collection with a detail route, and a form.</div></div>

## The opening sequence, every session

1. `get-skills`, then `get-skill` on everything relevant to the task.
2. `get-site-settings` for the types that exist on **this** site.
3. `get-navigations-with-pages` when you are going to touch pages.

Skipping step 1 is what produces plausible YAML that does not match the platform. Skipping step 2 is what produces a call against a type that does not exist here.

## Read before you write

| You want | Call |
|---|---|
| The site's types | `get-site-settings`, with `type` to keep the payload small |
| A page and its blocks | `get-page-with-content` |
| A lightweight sitemap | `get-navigations-with-pages` |
| Collection entries | `get-itemset-items` |
| Global field values | `get-global-fields-data` |

## The write shapes

The three rules behind most 422s:

- **Wrapper**: `update-content` writes under `custom:`, `update-itemset-item` under `data:`.
- **References come in two shapes**: media fields (`image`, `file`) take `[{id: '<uuid>'}]`, every reference by id (`items`, `smartselect` on a collection, `page`) takes a flat `['<uuid>']`. Never a bare UUID or a URL.
- **One locale per write**: main data plus one `translations.<locale>`, never a translation alone.

Full catalogue and per-tool notes in [MCP tools](/en/docs/mcp-tools).

## Order of operations

Dependencies are real, and getting them wrong produces errors that look like something else.

1. collections, because a form's `save` and a query both target one by key.
2. Content-types and page-types.
3. Routes.
4. Pages, which freeze their page-type at creation.
5. Content: blocks and items.

<div class="q-callout q-callout-warn"><i class="fa-solid fa-triangle-exclamation lead"></i>
  <div><b><code>update-settings-partial</code> replaces the whole target block.</b> Read the current YAML, merge your change into it, write it back entire. And <code>target</code> must equal the top-level key of what you send, otherwise it fails silently.</div></div>

## Batching

Start from the shape of the work, not from a parallelism number. Most of what looks like a batching decision is actually a fan-out the API has already decided for you:

| Work | What it costs |
|---|---|
| Reading — settings, pages, items, media | One call each, all independent. Fan them out. |
| An alt-text pass over a folder | **One `update-media` per asset.** There is no bulk endpoint. |
| A page or a content block, plus translations | Root data and **one** locale in the same call. N locales, N calls. |
| A collection entry, plus translations | Root and each locale in **separate** calls — the opposite rule. N locales, N+1 calls. |

So a bilingual collection of twenty-six entries is fifty-two writes, not twenty-six, and no amount of batching changes that. Sizing the session on the entry count is how a "quick import" turns into an afternoon.

**The discipline that matters is not the width of the fan, it is what you send into it.** Get one call of a shape to succeed and read what came back, then fan out the other forty-nine. A wrong wrapper or a mis-shaped reference fails identically on the first call and on the fiftieth, and the fiftieth costs you the cleanup.

Serialise on purpose in two cases: when the calls depend on each other, which the order of operations above already tells you, and when you are debugging a shape and want each response attributable to one input.

<div class="q-callout q-callout-warn"><i class="fa-solid fa-triangle-exclamation lead"></i>
  <div><b>A batch that half-lands is the real failure mode</b>, not a rejected batch. There is no transaction across calls: interrupt an import at entry thirty and the collection holds thirty entries, some with translations and some without. Recovery is a read-back and a diff, so keep the list you were working from.</div></div>

## Verify, do not assume

A tool call returning 200 means the write was accepted, not that the site renders. Close every session with a read-back:

- `get-site-settings` to confirm the types you created exist;
- `get-page-with-content` on one page you touched;
- `quilium run` plus a curl on the affected URLs.

## Related

<div class="q-cards">
  <a class="q-card reco" href="/en/docs/mcp-tools"><span class="k">Recommended</span><span class="t">MCP tools</span><span class="d">Every tool, with its wrapper and its gotchas.</span></a>
  <a class="q-card" href="/en/docs/prompting"><span class="t">Prompting well for Quilium</span><span class="d">Getting an agent to follow this sequence on its own.</span></a>
  <a class="q-card" href="/en/docs/skills"><span class="t">MCP skill library</span><span class="d">The library these procedures come from.</span></a>
</div>
