---
title: "MCP tools for Pages"
description: "Build, edit, style, personalize, and take down hosted landing pages from your AI assistant, with every argument, result, and error for the Pages MCP tools."
canonical: "https://rightmessage.com/help/mcp-tools-pages"
last-updated: 2026-10-27
---

# MCP tools for Pages

Build, edit, style, personalize, and take down hosted landing pages from your AI assistant, with every argument, result, and error for the Pages MCP tools.

Available on the Grow, Scale, and Pro plans.

Ask your AI assistant to build a landing page from a brief, tighten its copy, add an audience for an ad campaign, or take it down, and it works on the same [Pages](https://rightmessage.com/help/hosted-pages) you edit in the dashboard. These tools change drafts; your page goes live when you publish.

There's no REST API for Pages. The MCP tools below and the dashboard are the ways to work with them. The REST API's [publish endpoint](https://rightmessage.com/help/rest-api-publishing) publishes page changes along with the rest of the project.

## MCP page access and drafts

Pages is in early access. Every tool here is listed for every connection, but refuses projects without access with `Pages are not available for this project yet.` Projects in the early access program, and RightMessage admins, have access. To ask for it, email <support@rightmessage.com>.

Every tool accepts an optional string `project_id` and follows the [shared MCP authorization and project-selection rules](https://rightmessage.com/help/mcp-authorization-reference). Page IDs look like `pg_…`. An unknown ID returns `Unknown page "<id>". Valid choices: …`, listing up to 20 of the project's pages.

Every page and site style edit is saved as a new draft version, so `get-page-history` and `restore-page-revision` can undo it, and so can **Version history** in the dashboard. No tool here publishes. Use [`publish-config`](https://rightmessage.com/help/mcp-tools-publishing) to make page changes live. Publishing pages needs the Scale or Pro plan; on another plan, the rest of the project publishes and page drafts are kept.

Three things take effect without a publish: `unpublish-page`, `delete-page`, and `update-page-domains`.

Writes that lose a race return a prefixed error and change nothing:

| Prefix                               | What happened                                                                                                                 |
| ------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| `stale_draft`                        | The page changed after the version you sent. Read it again.                                                                   |
| `element_changed`                    | The element changed since `seen_revision_id`. The JSON result includes `current_html`, `current_css`, and `head_revision_id`. |
| `element_missing`                    | The element is no longer on the page.                                                                                         |
| `nothing_to_undo`, `nothing_to_redo` | There's no version to move to.                                                                                                |
| `out_of_scope`                       | Righty was limited to a selected element and the call went beyond it.                                                         |
| `invalid`, `too_large`               | The HTML, CSS, or value was refused. The message lists why.                                                                   |

Page HTML can't contain scripts or event handler attributes such as `onclick`. Forms go on a page through `create-page-widget`, and scripts are added by people in **Page settings**. No tool reads or writes scripts.

Examples are illustrative and use the fictional WorkForge project.

## `list-pages`

Lists the project's pages. Takes only `project_id`.

Each page has `page_id`, `name`, `path`, `status`, `live_url`, and `revision_id`, the current draft version.

| `status`  | Meaning                                                                                   |
| --------- | ----------------------------------------------------------------------------------------- |
| `draft`   | Never published. Goes live on the next publish.                                           |
| `live`    | Published, with no pending changes.                                                       |
| `changed` | Published, with draft changes that go live on the next publish.                           |
| `offline` | Unpublished. Held out of publishes until `publish-config` names it in `include_page_ids`. |

## `get-page`

Reads one page.

| Argument     | Type                          | Notes                                        |
| ------------ | ----------------------------- | -------------------------------------------- |
| `page_id`    | String, required              |                                              |
| `element_id` | String                        | Adds that element's `html` and `css`.        |
| `format`     | `outline` (default) or `full` | `full` adds the whole page `html` and `css`. |

The result includes `revision_id`, `status`, `page_url` (the page's address, known before its first publish), `live_url`, `page_rule` (the exact rule campaigns use for this page), `settings`, `uses_site_styles` and the page's own style tokens, the `outline` of addressable elements, `hidden` elements and unfilled `placeholders`, its form `slots` and `widgets` with their form goal selector, the `campaigns` that change the page, whether `scripts` are set (never their content), and the page's `build`.

## `build-page`

Has Righty build a new page from a brief, the same way **New page** does. It takes a few minutes and returns straight away. Poll `get-page-build` every 20 to 30 seconds.

| Argument               | Type               | Notes                                                                                                                                                                                                  |
| ---------------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `name`                 | String             | New page. 1 to 120 characters.                                                                                                                                                                         |
| `path`                 | String             | New page. `/` or up to five lowercase segments, like `/offer` or `/guides/free-guide`.                                                                                                                 |
| `brief`                | String             | New page. Who it's for and what it should get them to do. Up to 4,000 characters.                                                                                                                      |
| `goal`                 | Object             | New page. `kind` is `form`, `quiz`, `survey`, or `url`. `content_id` picks an existing form (`ofr_…`) or flow (`ofn_…`); omit it to have the build create one. `url` is the `https://` link for `url`. |
| `references`           | Array of URLs      | Up to 3 pages to screenshot for their look. One that can't be captured is skipped.                                                                                                                     |
| `use_site_styles`      | Boolean            | Default `true`. `false` lets the build design the page's own look.                                                                                                                                     |
| `clarifications`       | Object             | The questions `get-page-questions` returned, with the user's answers filled in.                                                                                                                        |
| `page_id` and `resume` | String and boolean | Start an existing page's waiting build, or continue a stopped or failed one.                                                                                                                           |

The result includes `page_id`, `build_id`, `status: "running"`, `page_url`, `page_rule`, and any `skipped_references`. Unlike a build from the dashboard, a build through MCP stops at the page. It doesn't set up audiences or A/B tests, and a new quiz or survey it adds to the page stays empty. Its summary lists the audiences and tests the brief asked for, so you can add them with the tools below and build the flow with the [flow tools](https://rightmessage.com/help/mcp-tools-flows).

## `get-page-questions`

Asks Righty what it would like to know before building a page. It takes the same `brief`, `goal`, `references`, `use_site_styles`, and `name` as `build-page`, and creates nothing.

The result has `questions` and `next`. Show the questions to the user, fill in their answers, and pass the whole object to `build-page` as `clarifications`. Every question is optional. With no questions, `next` says to build without clarifications.

## `get-page-build`

Reads a build's progress. Pass `build_id` from `build-page`, or `page_id` for the page's latest build.

The result has `status` (`running`, `completed`, `stopped`, `failed`, or `failed_system`), the current `stage`, labeled `steps`, the built `sections`, the number of `placeholders` left to fill, and `resumable`. A resumable build can continue with `build-page` `page_id` and `resume: true`.

## `create-page`

Creates a draft page from your own HTML and CSS, or copies a page.

| Argument          | Type             | Notes                                                                             |
| ----------------- | ---------------- | --------------------------------------------------------------------------------- |
| `name`            | String, required | 1 to 120 characters.                                                              |
| `path`            | String, required | `/` or up to five lowercase segments, as for `build-page`. Unique in the project. |
| `html`, `css`     | Strings          | The page body and its CSS. Give sections ids such as `data-rm-id="hero"`.         |
| `copy_from`       | String           | A page to copy instead, with its forms and look. Not with `html` and `css`.       |
| `use_site_styles` | Boolean          | Default `true`. Not with `copy_from`.                                             |

Returns `page_id`, `name`, `path`, `revision_id`, and `uses_site_styles`, plus `widget_ids` for a copy.

## `update-page`

Changes a page's search and sharing settings, or replaces its whole HTML and CSS. Send one or the other.

- `settings` accepts `title` (up to 120 characters), `description` (up to 320), `socialImage` and `favicon` (`usf://` media or `https://`), `canonical` (an `https://` URL), `lang`, and `noindex`.
- `html` and `css` replace the page body, with `expect_revision_id` set to the page's current version.

## `update-page-element`

Changes one element, named by its `data-rm-id`. Every element on a page has one, and campaign changes target elements by it, so ids stay the same across edits.

| `operation`                     | What it does                                                                                             |
| ------------------------------- | -------------------------------------------------------------------------------------------------------- |
| `set_text`                      | Replace the element's text with inline HTML: bold, italic, underline, strikethrough, links, and similar. |
| `set_image`                     | Set `src` (a `usf://` media library image) and `alt`.                                                    |
| `set_css`                       | Replace the element's CSS rules.                                                                         |
| `replace`                       | Replace the element's HTML and CSS.                                                                      |
| `hide`, `show`                  | Hide or show it on the page.                                                                             |
| `remove`, `duplicate`           | Remove or duplicate it.                                                                                  |
| `move`                          | Move it `before` or `after` `target_id`, or `prepend` or `append` it inside. It keeps its ids.           |
| `insert_before`, `insert_after` | Add new HTML just before or after `element_id`.                                                          |
| `prepend`, `append`             | Add new HTML at the start or end of `element_id`, or of the page when you leave `element_id` out.        |

Every operation except the inserts needs `seen_revision_id`, the version you last read. The result has the new `revision_id`, the `before_revision_id`, the `element_id`, and, when the edit removed elements that campaign changes target, `orphaned_changes` listing those changes.

## `generate-page-image`

Generates an image for one element and saves it to the media library. It takes 10 to 60 seconds, and if generation fails nothing changes.

| Argument                                    | Notes                                                                       |
| ------------------------------------------- | --------------------------------------------------------------------------- |
| `page_id`, `element_id`, `seen_revision_id` | Required.                                                                   |
| `prompt`                                    | Required. Up to 900 characters.                                             |
| `alt`                                       | Required. Up to 150 characters.                                             |
| `style`                                     | Required. `photo`, `illustration`, or `abstract`.                           |
| `aspect_ratio`                              | Required. `1:1`, `4:3`, `3:2`, `16:9`, `21:9`, `3:4`, `2:3`, or `4:5`.      |
| `placement`                                 | `hero` (1,600 pixels wide), `beside` (1,200, the default), or `card` (800). |

Generated images never show text, logos, software screens, or people presented as customers.

## `check-page-layout`

Renders a page at 1,280, 768, and 375 pixels wide and reports anything wider than the screen, with the offending element ids and screenshot links. Pass `page_id`, and optionally a `revision_id` to check an earlier version. `rendered: false` means the page couldn't be rendered, not that its layout is wrong.

## `create-page-widget`

Puts a form (`ofr_…`) or flow (`ofn_…`) on a page. Pass `page_id` and `content_id`. It creates an Embedded widget with the **Unstyled** theme that the page owns and styles with its CSS, and that doesn't appear in the Widgets list. Place the returned `slot_html` on the page with `update-page-element`. The widget is a draft change until you publish.

## `get-page-history`

Lists versions of a page (`page_id`) or of the site styles (`site_styles: true`), newest first. `limit` is 1 to 100 (default 20), and `before` pages back from a version number.

Each version has `revision_id`, `number`, `source`, `summary`, and `by` (a person's name or `Righty`). The result also says whether undo and redo are available.

## `restore-page-revision`

Undoes, redoes, or restores a version of a page or the site styles. Send `action` (`undo`, `redo`, or `restore`), `expect_revision_id` (the current version), `revision_id` for a restore, and `page_id` or `site_styles: true`. Each action adds a new version, so nothing is lost. Scripts and the page's address never change.

## `update-page-address`

Renames a page or moves it to a new `path`. If the move means a campaign stops covering the page, or a running A/B test would restart, the result starts `Nothing was saved.` and explains why. Call again with `confirm: true` to go ahead. Campaign page rules that match the page exactly move with it. Once you publish, the old address redirects to the new one.

## `delete-page`

Deletes a page with its version history and the widgets it owns. A published page goes offline at once, and you can't undo it. Pass `delete_campaign_id` to also delete the campaign made for the page. Righty asks you to approve a delete first.

## `unpublish-page`

Takes a live page offline. Its address stops serving within a minute, without a publish. The draft is kept, and the page stays out of later publishes until `publish-config` names it in `include_page_ids`. Returns `status: "offline"`.

## `get-site-styles`

Reads the site styles your pages share: `tokens`, `dark_tokens` (null without a dark palette), the site `css`, and the `revision_id` to send when you update them.

| Token                            | What it sets                                 |
| -------------------------------- | -------------------------------------------- |
| `colorPage`, `colorText`         | Page background and text                     |
| `colorBrand`, `colorAccent`      | Brand and accent colors                      |
| `colorButton`, `colorButtonText` | Button fill and text                         |
| `fontHeading`, `fontBody`        | Heading and body fonts                       |
| `radius`                         | Corner radius                                |
| `logo`, `favicon`                | Images, as `usf://` media or `https://` URLs |

## `update-site-styles`

Changes the site styles. Send exactly one of:

- `tokens`, merged into the current ones. Inside it, `dark: {}` makes a dark palette from the light colors, `dark: {…}` changes some dark colors, and `dark: null` removes it.
- `css_block` (`owner` and `css`) with `seen_revision_id`, to replace one block of the site CSS.
- `css` with `expect_revision_id`, to replace the whole site CSS.

Pages with their own look never use the site styles.

## `update-page-style`

Switches a page between the site styles and its own look. `use_site_styles: false` copies the current site styles into the page's own look, and `true` drops it. `tokens` changes the page's own look, including its `dark` palette.

## `recapture-site-styles`

Reads your website's colors, fonts, and corner radius again into the site styles draft. The logo, favicon, and site CSS stay. It needs a website in your project settings and runs at most once a minute. It returns `status: "capturing"` straight away, including when a capture is already running; read the result with `get-site-styles` about a minute later.

## `get-page-domains`

Reads where your pages live: the `slug`, the `subdomain_host` (like `workforge.rightmessage.page`), the `serving_host`, and any `custom_domain` with its status, problem, the CNAME `dns_record` to add, and check times. Custom domain statuses are `pending_dns`, `pending_certificate`, `active`, and `failed`. This is **Settings › Page domains**, not your website's domains.

## `update-page-domains`

Changes where your pages live, straight away and without a publish. Campaign page rules follow.

| `action`               | Argument   | What it does                                                        |
| ---------------------- | ---------- | ------------------------------------------------------------------- |
| `change_slug`          | `slug`     | Picks a new subdomain. The old one redirects.                       |
| `add_custom_domain`    | `hostname` | Adds a subdomain you own, like `go.workforge.com`. One per project. |
| `check_custom_domain`  |            | Checks DNS and the certificate now.                                 |
| `remove_custom_domain` |            | Disconnects it. Your pages move back to the subdomain.              |

## `create-page-audience`

Adds an audience to a page's campaign, creating the campaign the first time. Pass `page_id` with either `segment_ids` or `link` (`name`, `parameter`, an `operator` of `equals`, `contains`, or `starts with`, and `value`), which makes a new "Visitors from a link" segment. `name` and `campaign_id` are optional.

A new page campaign takes the page's name and address, holds back 10% of visitors to measure lift, and uses the page's form as its goal when there is one. Change the audience's content with [`set-audience-changes`](https://rightmessage.com/help/mcp-tools-campaigns). Without the Scale plan, `plan_note` says the setup is saved but won't go live until the project upgrades.

## `update-page-audience`

Renames an audience on a page (`name`) or retargets it (`segment_ids` or `link`). Pass `page_id` and `audience_id` (`var_…`). An audience whose test is running can't change until the test ends.

## `create-page-test`

Sets up an A/B test of the page for everyone (leave out `audience_id`, or send `"original"`) or of one audience's version. `campaign_id` picks another campaign on the page; it defaults to the audience's campaign, or to the page campaign, created if needed. An existing setup comes back as it is. For a campaign without goals, `form_goal: true` measures form submissions on the page. Start the test with [`start-audience-test`](https://rightmessage.com/help/mcp-tools-campaigns#a-b-test-lifecycle-tools) and publish. Starting a test requires **Pro**; on another plan, `plan_note` says the setup is saved in the draft. A test already running live refuses: `End the running page test first.` for the page, or `End the running test for this audience first.` for an audience.
