Tools
Every tool except whoami and get_markup_reference needs a Pro or Pro+ account. Tools marked outward change the public site or send email; they carry the destructive hint, so MCP clients ask before running them. See Safety.
The MICROPAGE_MCP_* switches named below apply to the local server. On the hosted server, the matching per-connection permissions in Connected AI apps play the same role.
Common arguments
project(string): the project's uuid, numeric id, micropage hostname (acmeoracme.micropage.sh), custom domain (www.acme.com), or a full URL.list_projectsshows valid values.build/version: a build number ("v12"or12, aslist_buildsshows) or a build id ("id:4567", assave_pagereturns). A bare number is read as a build number first, then as an id.
Account
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
whoami | read | none | Email, plan tier, subscription, auth mode (session or deploy_token), and the pinned project in deploy-token mode. Returns logged_in: false with a note instead of failing when there is no login. |
Projects
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
list_projects | read | none | Every project with uuid, id, domain, live URL, editor URL, and the active build's status. |
get_project | read | project | Active, latest, and currently deployed builds, failure reason, and read-only custom-domain status (hostname and certificate state, CNAME target). |
get_page_source | read | project, version? | Raw .page source of the active build (or the given build), its stored llms.txt, and the uploaded filenames. Multiple files come back merged into one. |
create_project | write | name, domain? | Creates an empty project and returns a starter .page file to adapt. Counts against the plan's project limit (Pro 5, Pro+ 20). Publishes nothing. |
save_page | write | project, pages: [{name, content}], llms_txt? | Compiles the markup and saves it as a draft build. Overwrites the active build if it is a draft or failed; otherwise creates a new draft and makes it active. Returns the build id, compiler issues, and the editor URL to preview. Never goes live. |
delete_project | outward | project, confirm_domain | Deletes the project and takes its site offline. Only registered with MICROPAGE_MCP_ALLOW_DELETE=1. confirm_domain must equal the project's micropage domain. |
save_page replaces the whole source each call. Pass every .page file; landing.page is merged first and the rest follow sorted by name. Saving also registers the source's forms on the project.
Builds
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
publish_build | outward | project, build?, confirm: true | Deploys a build to the live URL. Defaults to the active build; pass the id save_page returned to be exact, or an older build number to roll back to it (that build becomes active). Refused while another build of the project is publishing. Returns at once with after_event_id and an ETA. |
get_deploy_status | read | project, build?, after_event_id?, wait_seconds? (0–60, default 20) | Build status and deploy events since after_event_id. Waits up to wait_seconds for the deploy to finish, with progress notifications. Call again with the returned after_event_id until done is true. |
list_builds | read | project, limit? (default 20, max 100) | Builds newest first with status, failure reason, and which one is active. |
Deploy timing
- On Free and Pro, a published build waits about 3 minutes in the queue before it starts, then goes live within seconds. Pro+ skips the wait and is live in about 10 seconds.
publish_buildreturns an ETA accordingly. - Right after
deployment.completed, the URL can serve the previous version for up to a minute while Cloudflare's edge caches refresh. - Page paths redirect (308) to a trailing slash. Follow redirects when checking a page, for example
curl -L.
Files
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
upload_asset | write | project, filename, source: {path} | {url} | {base64} | Uploads one image (max 10 MB) and returns the stored name and the img: <- name markup line. Identical content is deduplicated by SHA-256. Different content under an existing name replaces the old file. |
list_files | read | project | Stored files with type, size, and hash, plus storage used and the plan's limit. |
get_file_url | read | project, filename | The URL a stored file is served from. |
Upload images before save_page or upsert_post references them. path reads a file on the machine running the server; url fetches a public https:// URL once, without your credentials.
On the hosted server, upload_asset takes only url or base64, the limit is 4 MB, and url refuses hosts on private or internal networks. Prefer url there whenever the image is already online.
If you replace an image on a live site, the live page keeps the old file until you save and publish again. A new filename avoids that.
Forms
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
list_forms | read | project | Forms on the site with name, page, and submission count (spam excluded). No submission content. |
list_submissions | read | project, form?, id?, include_spam?, limit? (default 20, max 50) | What visitors submitted, newest first. Only registered with MICROPAGE_MCP_SUBMISSIONS=1. |
list_submissions returns field values only in the text content, inside a fenced block marked as untrusted user-submitted data, and never in structured output. Visitors can type anything into a form, including instructions aimed at the assistant.
Posts
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
list_posts | read | project, slug? | Without slug: every post with status, visibility, and email list. With slug: that post in full, using the same field names upsert_post takes, plus its revision. |
upsert_post | write | project, title, body_markdown, slug?, description?, visibility?, hero?, email?, list?, subject?, preview?, date?, revision?, confirm_live_update? | Creates or updates one post by slug. Replaces every field: omitted optional fields are cleared, except date, which keeps the post's current date when omitted. date (YYYY-MM-DD or ISO 8601, no offset meaning UTC; past or today) sets the published date; on a draft it applies at first publish. Never sends email or publishes a draft. Updating an already-published post changes the live page at once and needs confirm_live_update: true. Returns the post's new revision. |
preview_post_send | read | project, slug | What publish_post would do: whether it emails, the list, the active subscriber count, whether it re-sends, whether sending is allowed on this server. Returns the confirmation_token publish_post needs (valid 15 minutes, invalidated by any edit). |
publish_post | outward | project, slug, confirmation_token | Publishes the post under /content and, if it has email enabled with a list, emails the list. Re-publishing re-sends. Email-sending posts are refused unless MICROPAGE_MCP_ALLOW_SEND=1. |
unpublish_post | outward | project, slug, confirm: true | Takes the post off the site and returns it to draft. Sent emails are not recalled. |
delete_post | outward | project, slug, confirm: true | Deletes the post for good. |
Body images in body_markdown must be hosted URLs: upload with upload_asset, then use the URL from get_file_url. hero accepts an https URL or the filename of an uploaded asset. The field meanings match the posts front matter.
To edit a post, read it with list_posts and slug, then pass its revision to upsert_post along with every field. If the post changed since that read (in the editor, the CLI, or another session), upsert_post fails with REVISION_CONFLICT and saves nothing; the assistant should re-read the post, merge its edits into the current values, and save again with the new revision. revision: 0 means the post must not exist yet. Without revision, the post's revision at the moment of the call is used, which still stops a change landing between that read and the write.
Publishing, updating, unpublishing, or deleting a published post rebuilds the site from the build that is live, so an unpublished page draft stays a draft. These tools return build_id and after_event_id to follow the rebuild with get_deploy_status.
A queued rebuild can be cancelled before it runs, and a build.superseded event then ends it. That happens when a site publish of another build replaces it (reason: "publish"), or when the build it targeted is no longer live and the rebuild moves to the live build (reason: "live_build_changed"). The event's payload names the build that carries the change, superseded_by_build_id. get_deploy_status follows that build: its returned build can differ from the one you asked about, and its superseded field lists each hop as {build_id, superseded_by_build_id, reason}. When superseded_by_build_id is null, nothing further deploys; done is true and succeeded is null.
Reference
| Tool | Kind | Key arguments | What it does |
|---|---|---|---|
get_markup_reference | read, local | topic? (grammar, grammar_full, posts_format, agent_guide, examples_index, example), example? | Returns the same text as the resources, for clients that do not read resources. No network call, no account needed. |