dotsy
ai.dotsy/mcpVersion 0.9.17Build and publish static sites on dotsy with draft-first MCP tools, OAuth Connect, and API keys.
Status
Responds452 msAnswered our handshake without sign-in.- Last checked
- Nov 14, 2026, 13:29 UTC
- Latency
- 452 ms
- Remotes responding
- 1 of 1
- Sign-in
- No sign-in
- Hosting
- Hosted outside the EU (detected)
- Registry data as of
- Nov 14, 2026, 22:14 UTC
Data from the official MCP Registry, checked by run.zero. How we check
Connect
Streamable HTTP
https://mcp.dotsy.ai/mcpResponds452 msNo sign-in
Claude Code
claude mcp add --transport http dotsy https://mcp.dotsy.ai/mcpClaude Desktop and claude.ai
Settings > Connectors > Add custom connector
Name: dotsy
Remote MCP server URL: https://mcp.dotsy.ai/mcpCursor
{
"mcpServers": {
"dotsy": {
"url": "https://mcp.dotsy.ai/mcp"
}
}
}VS Code
code --add-mcp '{"name":"dotsy","type":"http","url":"https://mcp.dotsy.ai/mcp"}'Built your own server? run.zero hosts MCP servers on European infrastructure.
Tools
120 tools
Read-only | Idempotent | Open world | ||
|---|---|---|---|---|
adapt_site_analyzePropose nav wiring + blog collectionization for an imported mirror (draft, opt-in). Read-only; returns per-adapter reports + proposalEtag. Nav decline may include nextStep (e.g. mega-menu → edit fragments/header.html). Wait for mirror-vs-editable answer if requiredDecision pending. | No | Yes | Yes | No |
adapt_site_applyApply the adapt proposal (draft): wire nav into the menu store and/or rewrite the blog index to a live <dotsy-collection>. One undo covers the whole apply; a second apply is refused until adapt_site_revert (or force). Queued applies are polled to completion. | Yes | No | No | No |
adapt_site_revertAtomically restore everything the last adapt_site_apply wrote (fragments, the menu doc when the op touched it, index, member configs, routes). | Yes | No | No | No |
add_custom_domainConnect apex and/or www on a paid plan; starts a DNS connect session. | No | No | No | Yes |
add_ideaAdd an idea from outside the site (draft board item or inbox suggestion). Idempotent on externalRef. | No | No | Yes | No |
apply_changesetStage writes[] + deletes[] in one call; attach routes via writes[].route. writes[].ifMatch (hash from get_site_manifest; "" = must not exist) guards each key (a delete takes { key, ifMatch } too); atomic:true makes one stale key write nothing (409 changeset_conflict). At most 10 writes; each body ≤60KB and the call ≤80KB. Larger new pages: stage_content_chunk then writes[].bodyStaging, or dotsy push / PUT content-raw. | Yes | No | No | No |
batch_patch_contentpatch_content on multiple keys; all-or-nothing validation. Preferred edit path for pages over 60KB. replace-string value/replace ≤60KB; whole call ≤80KB. | Yes | No | No | No |
bulk_put_assetsUpload 1–200 CMS assets; key = path after /assets/, or sitePath for an exact URL path (e.g. /.well-known/security.txt, /ads.txt). Each item: exactly one of bodyBase64, bodyText (plain text for .css/.js/.mjs/.json/.svg/.txt/.xml only — not .html pages), or importFromUrl. Optional bodySha256 checks the sent bytes; response sha256 = stored bytes (WebP may differ). JPEG/PNG/static GIF are re-encoded to WebP (response key photo.webp; /assets/photo.jpg keeps serving it) — use the response key in CSS/JS; optimize:false stores the bytes as sent at your key; animated GIFs are always kept. Live in the editor and draft preview at once; on the published site after the next publish. | Yes | No | Yes | No |
bulk_put_contentStage many content keys (pages, layouts, fragments). Content only — not routes or assets. Each body ≤60KB and the whole call ≤80KB; larger pages use stage_content_chunk, dotsy push, or PUT content-raw. May queue above the inline threshold. | Yes | No | Yes | No |
claim_siteMove the guest draft onto your signed-in dotsy account. Requires OAuth Connect; pass the guestToken from start_site. | No | No | No | No |
create_siteCreate empty site; seeds brief. Globally taken slugs auto-suffix to `{slug}-{adjective}-{noun}` (default); pass onSlugTaken:"fail" to get a 409 instead of a renamed site. | No | No | No | No |
delete_assetDelete a static asset by key. The editor and draft preview drop it at once; the published site drops it at the next publish. | Yes | No | Yes | No |
delete_contentDelete content key (tombstone if published). A fragments/* section that pages still place is refused with section_in_use (lists the pages) — detach it or remove it first. | Yes | No | Yes | No |
delete_draft_testRemove a draft A/B test (releases variant bodies; does not publish). | Yes | No | Yes | No |
delete_menu_itemRemove one item from a menu (page stays live). | Yes | No | Yes | No |
delete_routeRemove a route by path. | Yes | No | Yes | No |
delete_sitePermanently delete site; confirmSlug must equal slug. | Yes | No | Yes | Yes |
detach_sectionGive one page its own copy of a shared section; every other page keeps the shared one. A draft — publish_site to go live. A section the layout places is hidden on that page instead (share_section name + hide). | Yes | No | Yes | No |
discard_draftsDiscard unpublished drafts: all (omit key/keys/routes/menus), one content key (key), menu draft only (menus:true), or a selection (keys, routes). Destructive — check get_draft_status first. | Yes | No | Yes | No |
edit_pageOpen the interactive page canvas to change content: the user clicks an element, then you call patch_content. Use when the intent is editing — not for verify-only checks (use preview_page). | No | Yes | Yes | No |
estimate_testEstimate days to reach promote readiness for a page (traffic baseline). Read-only. | No | Yes | Yes | No |
find_replaceCase-insensitive find→replace across pages in one staged commit. Batch all replacements into ONE call — never parallelize find_replace on the same key (concurrent edits surface as per-key conflict). find/replace ≤60KB. | Yes | No | No | No |
form_recipientsWho a site's forms may email. A form's `to` address gets submissions only when it is a verified site member or it confirmed by a one-click link we email it (no account, no sign-in, no site access). action: `list` (confirmed + waiting addresses), `status` (one address: member | confirmed | pending | expired | unconfirmed), `request` (email the confirm link; 7 days, single use; max 3 per address, 20 per site and 50 per account a day), `revoke` (stop form emails to a confirmed address). A publish already sends the link once by itself when a form emails an unconfirmed address. Never ask the user for the link — it goes to that inbox only. | No | No | No | Yes |
get_account_contextAccount, user, memberships[]. Pass workspace on writes when memberships.length > 1. | No | Yes | Yes | No |
get_activityList site activity or fetch one change diff (pass id). Filters: who, state, actor (me), since, limit≤20. Notes from context are visible to everyone on the site — no secrets. | No | Yes | Yes | No |
get_adapt_statusRead adapt state: proposal summary + proposalEtag (+ applied/consumed flag), undo-record presence, active or queued job progress. Use to resume in a fresh session. | No | Yes | Yes | No |
get_analyticsRead-only traffic overview (default) or full breakdowns via include[]; optional bot id for crawler page drill-down. | No | Yes | Yes | No |
get_assetRead one asset (metadata + base64 + stored sha256). sha256 is the stored blob; may differ from upload bodySha256 when IMAGES re-encodes rasters. Live in the editor and draft preview at once; on the published site after the next publish. | No | Yes | Yes | No |
get_boardList board items with status, stamp fields, and baked vote counts (draft overlay included). Live vote totals: site host GET /__dotsy/votes. | No | Yes | Yes | No |
get_collection_schemaRead the site's collection field definitions (`_data/collections.json`, draft view): { schema: { v: 1, collections: { "<key>": { fields[], settings? } } }, hash }. hash is null when no schema exists yet — pass it as put_collection_schema ifMatch. 409 collection_schema_invalid { hash, issues } means the stored file is broken: fix it with put_collection_schema using that hash. | No | Yes | Yes | No |
get_contentRead one content key; optional selector (region) or published=true (live body). Bodies over 40KB without a selector return a truncated summary — use selector, batch_patch_content, or dotsy pull. | No | Yes | Yes | No |
get_custom_codeRead the site-wide custom code: `draft` (what the next publish puts live) and `published` (what visitors get now) for both boxes — head (before </head>) and body (before </body>) — plus `pending`, `runOn` and `maxChars`. | No | Yes | Yes | No |
get_custom_domain_connectCurrent connect session and nextAction (browser URL or manual DNS guide). | No | Yes | Yes | No |
get_draft_statusPending draft changes: content keys and routes with status. May include requiredDecision (publish_confirm) before publish_site. | No | Yes | Yes | No |
get_form_submissionRead one form submission with the full field payload (explicit PII access — use only when needed). | No | Yes | Yes | No |
get_menuRead a menu's draft items and etag; menu rules → get_skill('nav'). | No | Yes | Yes | No |
get_menu_docRead the whole menu doc (all menus + shell/template), etag for put_menu_doc, and issues (by item id) — page_not_routable, page_missing, page_dead_link, page_is_redirect — computed from the draft routes, so a link that won't show or leads nowhere shows up before publish. | No | Yes | Yes | No |
get_planRead-only workspace plan and pooled usage; pass slug for this site's add-ons. Call before a large build. | No | Yes | Yes | No |
get_reportYour dotsy bug reports. Omit id for the list; pass id for one ticket and its public replies. | No | Yes | Yes | No |
get_routeGet one route by path (home is '/'). | No | Yes | Yes | No |
get_siteSite detail, stats, publicUrl, brief head (default-on), and readiness flags. pages[] is a ~25-entry head by default (stats.pages has the true count); pass pages: true for the full array (capped at 1000), or list_content/get_site_manifest. Large sites (200+ pages): list_pages is paginated (cursor) or use get_site_manifest for the full route set. | No | Yes | Yes | No |
get_site_build_progressRead-only build progress view (structure/adapt jobs or after import). structuredContent.forHumans holds the headline and progress. import_site_from_url blocks until done, so this is not needed during an import; get_site has the full state. | No | Yes | Yes | No |
get_site_manifestContent keys + hashes only (optional routes=true) — static files live in list_assets, not manifest. Diff keys+hashes before apply_changeset; stage only changed bodies. | No | Yes | Yes | No |
get_site_outlineSite shape: every layout and shared section (`sections`: fragments/* by name, with page count, whether the file exists and staged-change flag), whether a layout is missing, redirects count, menus grouped by where they show, and collections with their page placements. Answers 'is my layout missing', 'which shared sections exist and where', 'where does this menu show' without listing every page. Read-only; indexing mirrors list_pages (a fresh import may still be indexing). | No | Yes | Yes | No |
get_site_tasksWhat needs fixing on a site, from stored checks. Call after writes, before publish_site. | No | Yes | Yes | No |
get_skillSkill body + optional questions[]. Accepts an id OR a synonym (e.g. 'list', 'menu') — resolves aliases and suggests near-misses. Start with intake when ambiguous. | No | Yes | Yes | No |
get_structure_resultLast structure apply job result (structuredKeys, conflicts, partial). | No | Yes | Yes | No |
get_structure_statusFlat vs structured page counts; chromeCoverage = real per-fragment page counts + missedPages (check before promising sitewide edits). Informs user — do not auto-run analyze/apply while requiredDecision pending. | No | Yes | Yes | No |
graduate_siteEnable site search & collections (kv → do-sqlite), one-way. Unlocks search_content, collection indexes, visitor /__paige/search, and moves any R2 form-submission ledger into SiteDb. 409 blocked: `reason` names the gate — unsupported source backend (never overridable); strictDrafts (default true; false skips it) on unpublished drafts or unrecovered KV rows; or an incomplete-looking KV snapshot (e.g. a page deleted minutes ago), the only gate force:true overrides. `audit` (+ `audit.warnings`) = aggregate counts, no row keys: judge the gap before forcing. Anything outside the frozen snapshot is unreachable afterwards. | Yes | No | Yes | No |
import_site_from_urlImport URL to draft. On complete, response may include requiredDecision — preview then ask mirror vs editable before structure_*. | No | No | No | Yes |
infer_collection_schemaSuggest fields for one collection from a sample of its items' meta.custom values (published data, else drafts) — writes nothing. Returns { sampled, suggestions: [{ field: { key, type, options? }, count, samples, defined }], skipped }. Review, then add the ones you want via put_collection_schema. | No | Yes | Yes | No |
inspect_collectionCollection state — count, server.mode, sample entries, tag (membershipKind, match=) when discovered, name, noun, URL pattern, layout, where listed, post fields used. Pass status/q/cursor/limit (any one, even empty) for a full items[] page instead: status draft = never published; a published post with unpublished edits is status published with hasChanges:true (never draft), showing its staged title/date/tags/author; scheduled = future visibleAt. Drafts come from staged content (no publish needed), published/scheduled from the index. limit defaults to 50 (1-200). Omit all four for just the base inspect. | No | Yes | Yes | No |
list_assetsCMS uploads under assets/ only — not mirrored clone CDN (get_site mirroredAssets or import warmJob). Not content — use list_content. Live in the editor and draft preview at once; on the published site after the next publish. | No | Yes | Yes | No |
list_collectionsCollections on the site — name, noun, item count (or 'not published yet'), URL pattern, and whether any member is staged. Includes a collection only a draft page lists. Returns a bare array (not wrapped in an object) — pass each row's key verbatim to inspect_collection/update_collection. | No | Yes | Yes | No |
list_contentList content keys (HTML/md); not assets — use list_assets. Defaults to 50 keys per page: raise limit (max 1000) or pass cursor (nextCursor). Per-row `size`/`missing` are measured only on pages of ≤100 rows; past that they're ABSENT (never `null`) unless you pass withSize:true (one storage read per row). Only `size: null` + `missing: true` means the page's bytes are gone. | No | Yes | Yes | No |
list_custom_domainsList all custom hostnames and connection status for the site. A connected bare domain with redirectorState "attention" is NOT redirecting (see `attention`). | No | Yes | Yes | No |
list_form_submissionsList form submissions (metadata + bounded field preview — not full PII). Works on kv and do-sqlite backends. | No | Yes | Yes | No |
list_goalsList site conversion goals (pageview paths and form submits). Required before start_test. | No | Yes | Yes | No |
list_ideasSearch draft/published board items and open suggestions by title token overlap. | No | Yes | Yes | No |
list_my_sitesList your dotsy sites. Renders a site-picker for humans; agent reads structuredContent. Use to choose a site — not for editing content (use edit_page) or verify-only checks (use preview_page). Defaults to your active workspace; pass workspace (org id or slug from get_account_context memberships) to list another workspace's sites without switching the dashboard session. | No | Yes | Yes | No |
list_notificationsAccount notification inbox (Needs you · Updates). Summary-first: tab counts plus compact rows with nextAction (MCP tool or dashboard URL). OAuth person only — not API keys. | No | Yes | Yes | No |
list_pagesList pages on a site — route settings (path/title/navLabel/purpose) by default, one row per route. Renders a page-picker for humans (redirect and worker routes left out there — nothing to open in edit_page); agent reads structuredContent. Use after picking a site — not for editing (use edit_page) or verify-only checks (use preview_page). Pass view:'pages' to group by layout instead — adds layout/noLayout/q filters, what each page places, and indexing progress; use that for 'what pages use this layout' or 'is this page indexed yet', not for route settings. Paginated — pass cursor (from nextCursor) for more; partial:true means this page is a window, not the full route set. | No | Yes | Yes | No |
list_skillsPaige build skills (id + whenToUse). Pull get_skill on demand — do not duplicate in tool text. | No | Yes | Yes | No |
list_suggestionsList form suggestions awaiting moderation (duplicate hints against the board). | No | Yes | Yes | No |
list_versionsList the site's published versions, newest first (who, when, pages, live, restorable). Use before restore_version. | No | Yes | Yes | No |
list_votesList voters on one board item (voter id + source only — no email). | No | Yes | Yes | No |
mark_notifications_readMark Update notifications read (ids or all). Needs-you Actions refuse with 422 action_not_markable — fix the cause (it clears itself); only the person can dismiss them in the dashboard. | No | No | Yes | No |
moderate_suggestionDecide one form suggestion from list_suggestions: approve (new draft board item; stages content, does not publish), merge (into an existing board item, subscribes the voter/email) or decline (no board item). | No | No | Yes | No |
new_post_templateRead-only scaffold for a new post — suggested key/path, membership meta, blank or duplicate body. Then put_post (+ optional put_route). | No | Yes | Yes | No |
optimize_assetsShrink heavy images in place (0.98): JPEG/PNG/still GIF → WebP at the same address, so no HTML changes. keys = site paths from verify_page health.assets[].ref — /assets/… uploads or clone paths like /wp-content/… (1–50 per call). Skips animated images, already-small files and non-images (`skipped`); idempotent. The replaced file is kept under .originals (never served). Spends the daily image budget like an upload — dryRun:true reports the saving without spending it. The draft serves the smaller file at once; live after you publish (some imported files sooner). | Yes | No | Yes | No |
patch_contentEdit one content key via ops[] (selector ops or replace-string; wrap/unwrap/move restructure siblings). Stages draft; op shapes in schema. | Yes | No | No | No |
patch_routePartial route update (only sent fields change; an OMITTED field is left alone). On a nullable field (contentKey, redirectTo, redirectStatus, preserveQuery), null CLEARS it to its default — unlike omitting it. To set redirectTo/redirectStatus, send purpose: "redirect" in the SAME call (only what's sent is checked, even on an existing redirect) or it 400s invalid_body. | Yes | No | Yes | No |
preflight_sitePlan check before publish or large build (counts, plan page cap, seo suggestions; imports: form_unwired advisory, webflow_store blocking). When ok is false, blocking lists the failed suggestion codes. Read-only. | No | Yes | Yes | No |
preview_pageVerify-only composed HTML check; home preview may include requiredDecision — ask mirror vs editable before structure_*. | No | Yes | Yes | No |
promote_experimentPromote a winning A/B variant to live — explicit user instruction only; see get_skill('verify') § A/B. | Yes | No | No | Yes |
publish_sitePublish draft to live. handoff required; feedback optional. Warnings (form_unwired, store, SEO) are advisory: tell the user. Site-check errors return a publish_issues decision. A request to publish is not agreement to publish those errors: use its publishWithIssues code only after the user has seen them and said to publish anyway; if you can't ask, fix them or stop and report. If a fix needs text or a link target you don't know, ask the user. | Yes | No | No | Yes |
put_collection_schemaReplace the whole field schema (draft; publish makes it live). Edit what get_collection_schema returns; keys as list_collections gives them ("blog/" or an id). Field: { key, type, label?, help?, required?, unique?, inCard?, default? } — type text (multiline, minLength, maxLength) | number (min, max, integer) | boolean | option (options[] required) | multiOption (options[] required, max) | link | email | phone | color. Keys: letter then letters/digits/_ (≤40), not a built-in post field (author: text, or a reference to authors/ with the Authors feature), not secret-looking. ≤60 fields per collection. settings.defaultSort: date:desc|date:asc|title:asc|slug:asc. Removing a collection's entry drops its definitions (post values stay). Values go in put_post meta.custom (fieldWarnings are soft). 400 invalid_collection_schema lists issues; 409 conflict = stale ifMatch. | Yes | No | Yes | No |
put_contentStage one content key. Body ≤60KB. Larger pages: stage_content_chunk + apply_changeset bodyStaging, dotsy push, or PUT content-raw. Edits to an existing large page: batch_patch_content. | Yes | No | Yes | No |
put_goalsCreate or replace all site conversion goals (≤50). Required before start_test when no goal exists. | Yes | No | Yes | No |
put_menu_docReplace the whole menu doc (ifMatch from get_menu_doc required). Each item may omit menu — the enclosing menu key in doc is used. | Yes | No | Yes | No |
put_menu_itemPartial upsert one menu item: send only the fields to change; every omitted field (parent, sort, label, kind, ref, newTab, html/childTemplate/childShell/attrs/data) keeps its stored value, and parent: null moves it to the top level. A new id needs label, kind and ref (parent defaults to null, sort to the end) and dedupes by (menu, ref): an existing item linking the same target is reused. An existing id always updates that exact item. To remove rich keys, use put_menu_doc. | Yes | No | Yes | No |
put_postStage a blog post via structured meta+body (?format=post). Key e.g. blog/my-post.html. Declared membership: meta.collections; schedule: meta.visibleAt; SEO title override: meta.seoTitle (card always shows meta.title); custom fields: meta.custom (typed per collection by get_collection_schema; the response's fieldWarnings flag values that don't fit — soft, never blocking). | Yes | No | Yes | No |
put_routeCreate/replace route; contentKey derived from path if omitted. On a field that accepts null (contentKey, redirectTo, redirectStatus, preserveQuery), sending null clears it back to its default. | Yes | No | Yes | No |
reapply_custom_domain_oauthRe-apply DNS with stored Cloudflare OAuth grant (no browser). | No | No | Yes | Yes |
refresh_custom_domainPoll one hostname until DNS/cert propagates. | No | No | Yes | Yes |
reindex_collectionBuild/finish collection indexes after publish returns collectionDataPending or collectionSqlPending. | No | No | Yes | No |
remove_custom_domainRemove one custom hostname from the site. | Yes | No | Yes | Yes |
remove_votesRemove one voter's vote and drop their release subscription for that item. | Yes | No | No | No |
rename_contentRe-key a page by slug (draft or published static), server-side hash copy. Default deletes static routes; movePath:true repoints the route, rewrites menu refs, redirects and root-relative / {slug}.dotsy.site hrefs in draft HTML (as rename_page), and for an already-published page leaves a 301 (leaveRedirect, default true). Retry-safe: 409 rename_failed rolls back, resend. On fragments/<name>.html it also rewrites every <dotsy-fragment name> reference and hide marker in one commit. Then publish_site. | Yes | No | No | No |
rename_pageChange a page's URL: moves route `from` to `to`. Menu links and redirects to the old path retarget; a 301 stays at the old path (leaveRedirect). Root-relative and https://{slug}.dotsy.site/ hrefs in draft page, layout and fragment HTML are rewritten (linksRewritten; not custom-domain absolutes or code samples; linksRewriteTruncated when the scan caps at 100 HTML keys, 500 with full content search). Retry-safe. Errors: 404 route_not_found; 400 reserved_route, invalid_body; 422 rename_same_path, rename_pattern_route (:param), rename_redirect_route (edit its redirectTo); 409 rename_experiment_running (end the A/B test), rename_target_exists (200 when to already serves from's content). Then publish_site. | Yes | No | No | No |
rename_siteRename the site slug (hostname {slug}.dotsy.site). Owner-only; use the returned slug afterwards. Published site: the old slug redirects on the API (301 reads, 308 writes) and the old host 301s, both reserved until delete or rename-back. Never published: the old slug 404s and its hostname is released (create_site can reuse it). Stored HTML URLs are not rewritten (use find_replace). | Yes | No | Yes | Yes |
reorder_menuSet final menu order. Pass ifMatch from get_menu; stale → 409 with current items. | No | No | Yes | No |
reply_to_reportAdd information or answer dotsy's question on your own report. | No | No | No | No |
report_bugReport a dotsy bug, or ask a support question (kind question — AI answer from the help centre). Bugs attach recent errors and return a ticket id. | No | No | No | No |
restore_versionBring an earlier published version back as unpublished changes (page content only — routes, menus, images and settings stay). version: a number from list_versions, or "previous". dryRun: show what would change. Then review and publish_site, or discard_drafts to undo; publish:true makes it live at once. | Yes | No | No | Yes |
revert_changeUndo one activity event by staging the prior version as draft only — call publish_site to go live. Respects AI access. | No | No | No | No |
review_changesReview queue: what changed and isn't live yet. list (counts first) → get one item (hidden changes, optional diff, bodyChanged: false means only title/meta/route fields changed — review hidden, not the visible page) → mark_ready / unmark (≤50 ids). Then publish_site onlyReady:true. Drafts-only sites: a person marks. | No | No | Yes | No |
search_contentFind pages containing a phrase (grep without reading bodies). Requires do-sqlite — graduate_site first if search_unavailable. | No | Yes | Yes | No |
set_analytics_providerConnect a third-party analytics provider (GA4, Plausible, Fathom, Umami) or remove it (provider 'none'). dotsy adds the provider's script to the <head> of every live page — live immediately, no publish needed. Replaces any earlier provider (one per site). Use this instead of pasting a GA4 gtag snippet into a layout. Other tags (Google Tag Manager, ads pixels, Clarity, search-console verification <meta>) go in set_custom_code. | Yes | No | Yes | Yes |
set_custom_codeSet site-wide custom code: `head` goes before </head> and `body` before </body> on every page, on every layout. Saved as a draft; goes live with the next publish_site (on a live-mode site the dashboard publishes only the code). Never runs in the editor. ≤20,000 characters per box, stored as sent; `warnings` flags likely mistakes (unclosed <script>, <html>/<head>/<body> tags, canonical or robots tag, GA4 already connected) without rejecting. Send only the boxes you change; "" clears one. `runOn` ('live' default; 'live-and-preview' adds the editor preview) applies at once — agents limited to drafts can't set it. For tag managers (GTM), Clarity, ads pixels, chat widgets, verification tags; plain GA4/Plausible/Fathom/Umami: set_analytics_provider. | Yes | No | Yes | Yes |
set_experiment_noteRecord what was learned from an ended A/B test (≤500 chars; null clears). | No | No | Yes | No |
set_item_statusChange a roadmap/board item status (stamps dates; on release drafts the changelog post and links both ways). Never hand-edit *At, daysToRelease, or votes. | No | No | Yes | No |
set_primary_custom_domainSet the canonical host (301 target). | No | No | Yes | Yes |
set_site_iconSet the favicon from a square image asset. Draft until publish. | Yes | No | Yes | No |
set_up_bare_domainSet up an EXISTING bare domain (example.com) that doesn't open the site (www works). Refuses if dotsy already serves it; deletes nothing. domain.dnsRecords: (1) _acme-challenge CNAME (apex_cert); (2) once issueState is issued, replace the old @ records (action delete) with the A/AAAA rows. cancel:true (while canCancelSetUp) restores everything; 409 too_late_to_stop once @ points at dotsy. Other 409: www_not_connected, already_serving, not_supported, not_needed. 503: retry. | No | No | No | Yes |
share_sectionMake a block that repeats on several pages one shared section, or change where one shows. No arguments: lists blocks repeated on 3+ pages. sourceKey + selector (or selectors: a sibling run, one wrapper): a dry run finds every page with it; dryRun:false shares it. name + scope/hide/show: move an existing section to/from every page, or hide/show it per page. Over the per-call cap (too_many_pages, nothing written): share with keys, then again under the same name from a page that still has a copy; then move with name + scope every_page + keys (max-1 pages a call; all hide on the first) until all are moved. Always a draft (publish_site to go live; undo: revert_change). | Yes | No | Yes | No |
stage_content_chunkAppend one ≤60KB chunk of a large new page. Omit stagingId on seq 0; pass the returned stagingId on later seq. Set finalize:true on the last chunk, then apply_changeset with writes[].bodyStaging. | No | No | No | No |
start_edit_sessionOpen a draft session. Returns preview/edit URLs for the person (see linkGuidance). draftEditorUrl only when the site gives AI agents Full access. path defaults to '/'. | No | No | No | No |
start_siteStart one draft site with no dotsy account. Returns slug + guestToken — pass guestToken on every later tool call until claim_site. | No | No | No | No |
start_testStart a same-URL A/B test (draft or live source). Rules → get_skill('verify') § A/B. | No | No | No | Yes |
structure_site_analyzePropose shared layout + fragments; persist:false first. Wait for mirror-vs-editable answer if requiredDecision pending. | No | No | Yes | No |
structure_site_applyRewrite flat pages to layout + fragments (draft). Do not call while requiredDecision pending — user must pick editable first. It extracts header/footer only; report chromeCoverage counts, not 'sitewide'. Afterwards share_section with no arguments lists the other repeated blocks (banner, CTA). | Yes | No | No | No |
submit_feedbackOptional mid-session feedback (required feedback rides with publish_site). | No | No | No | No |
translate_pageStage draft copies of pages in another language: copied as is, language set, linked to the original as a translation (menus not copied). Then translate the bodies, write them in one apply_changeset, and publish_site. Target path = language folder + source path unless an item sets `path`; an existing path is left untouched. | No | No | Yes | No |
undo_publishTake back the last publish at once: restores the previous version of the pages it changed and publishes them; the undone changes stay as unpublished changes (`restaged`). On a live-mode site nothing is kept (its next save would republish it): the answer has `redo.version` — restore_version with it and publish: true brings it back. publishVersion = what publish_site returned. not_latest if another publish landed since. If its publish fails, the undo stays unpublished — publish_site finishes it. | Yes | No | No | Yes |
update_briefUpdate `_intent/site.md` (site brief) or a page brief when `page` is set. See field descriptions for rules, notes, and head enums. | Yes | No | Yes | No |
update_collectionRename a collection's display name and/or noun (e.g. the generic 'posts' key shown as 'Recipes' / 'recipe') — cosmetic only, stored separately from the tag that defines membership; doesn't need publish. Provide at least one of name/noun. null (or "") resets that field back to its derived default — different from omitting it, which leaves the current value alone. | No | No | Yes | No |
update_siteUpdate site settings: title, keyConvention, editingMode, signature ("Made with dotsy" badge; live immediately), trailingSlash, ownSeoFiles, aiTrain, and the language settings; each field's own description has the details. Slug is the hostname — use rename_site. Set editingMode 'staged' before handing the editor to a person via start_edit_session's draftEditorUrl. | No | No | Yes | Yes |
verify_pagePre-publish lint (tags, assets, layout, SEO, speed and accessibility). Summary first: health issues grouped by code, each with fix:{tool,args,fill?} — supply the fill args, then call. health.summary counts are whole-site (groups/codes filter only issues and assets). Pair with preview_page — see get_skill('verify'). | No | Yes | Yes | No |
wait_for_custom_domainPoll one hostname until it is connected or the timeout is reached. | No | No | Yes | Yes |
Details
- Registry status
- Active
- Published
- Nov 14, 2026
- Updated
- Nov 14, 2026
- Repository
- Not given
- Categories (suggested)
- Data and analyticsCommunicationKnowledge and notesSuggested categories are assigned automatically from the registry text and may be wrong. Verified operators can correct them.
- GDPR
- Not declared