bots.st/dotsy
dotsy
Apply draft-first site changes
3187 ms
answered our call
- State
- Answered
- Protocol
- MCP 2025-06-18
- Tools listed
- 117
- Answered
- 3 of the last 3 calls
How to reach it
- MCP, HTTP
https://mcp.dotsy.ai/mcp
What it can do
| Tool | What it says it does |
|---|---|
adapt_site_analyze | Propose 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. |
adapt_site_apply | Apply 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. |
adapt_site_revert | Atomically restore everything the last adapt_site_apply wrote (fragments, the menu doc when the op touched it, index, member configs, routes). |
add_custom_domain | Connect apex and/or www on a paid plan; starts a DNS connect session. |
add_idea | Add an idea from outside the site (draft board item or inbox suggestion). Idempotent on externalRef. |
apply_changeset | Stage 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… |
batch_patch_content | patch_content on multiple keys; all-or-nothing validation. Preferred edit path for pages over 60KB. replace-string value/replace ≤60KB; whole call ≤80KB. |
bulk_put_assets | Upload 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… |
bulk_put_content | Stage 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. |
claim_site | Move the guest draft onto your signed-in dotsy account. Requires OAuth Connect; pass the guestToken from start_site. |
create_site | Create 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. |
delete_asset | Delete a static asset by key. The editor and draft preview drop it at once; the published site drops it at the next publish. |
delete_content | Delete 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. |
delete_draft_test | Remove a draft A/B test (releases variant bodies; does not publish). |
delete_menu_item | Remove one item from a menu (page stays live). |
delete_route | Remove a route by path. |
delete_site | Permanently delete site; confirmSlug must equal slug. |
detach_section | Give 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). |
discard_drafts | Discard 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. |
edit_page | Open 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). |
estimate_test | Estimate days to reach promote readiness for a page (traffic baseline). Read-only. |
find_replace | Case-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. |
form_recipients | Who 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… |
get_account_context | Account, user, memberships[]. Pass workspace on writes when memberships.length > 1. |
get_activity | List 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. |
get_adapt_status | Read adapt state: proposal summary + proposalEtag (+ applied/consumed flag), undo-record presence, active or queued job progress. Use to resume in a fresh session. |
get_analytics | Read-only traffic overview (default) or full breakdowns via include[]; optional bot id for crawler page drill-down. |
get_asset | Read one asset (metadata + base64 + stored sha256). sha256 is the stored blob; may differ from upload bodySha256 when IMAGES re-encodes rasters. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish. |
get_board | List board items with status, stamp fields, and baked vote counts (draft overlay included). Live vote totals: site host GET /__dotsy/votes. |
get_collection_schema | Read 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 }… |
get_content | Read 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. |
get_custom_code | Read 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`. |
get_custom_domain_connect | Current connect session and nextAction (browser URL or manual DNS guide). |
get_draft_status | Pending draft changes: content keys and routes with status. May include requiredDecision (publish_confirm) before publish_site. |
get_form_submission | Read one form submission with the full field payload (explicit PII access — use only when needed). |
get_menu | Read a menu's draft items and etag; menu rules → get_skill('nav'). |
get_menu_doc | Read 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. |
get_plan | Read-only workspace plan and pooled usage; pass slug for this site's add-ons. Call before a large build. |
get_report | Your dotsy bug reports. Omit id for the list; pass id for one ticket and its public replies. |
get_route | Get one route by path (home is '/'). |
get_site | Site 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 enumerate everything with list_content/get_site_manifest. Large sites (200+ pages)… |
get_site_build_progress | Read-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. |
get_site_manifest | Content keys + hashes only (optional routes=true) — static files live in list_assets, not manifest. Diff keys+hashes before apply_changeset; stage only changed bodies. |
get_site_outline | Site 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. Use for 'is my layout… |
get_skill | Skill body + optional questions[]. Accepts an id OR a synonym (e.g. 'list', 'menu') — resolves aliases and suggests near-misses. Start with intake when ambiguous. |
get_structure_result | Last structure apply job result (structuredKeys, conflicts, partial). |
get_structure_status | Flat 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. |
graduate_site | Enable 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 covers three unrelated gates: an unsupported source backend (no override, ever); strictDrafts — default… |
import_site_from_url | Import URL to draft. On complete, response may include requiredDecision — preview then ask mirror vs editable before structure_*. |
infer_collection_schema | Suggest 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. |
inspect_collection | Collection state — count, server.mode, sample entries, tag (membershipKind, match=) when discovered; plus name, noun, URL pattern, layout, where it's listed, and post fields used. Pass status/q/cursor/limit (any one, even empty) for a full items[] page instead: status draft = never published; a… |
install_product_kit | Add a roadmap, changelog and/or help centre to a site as drafts (never overwrites; rerun finishes a partial install). |
list_assets | CMS uploads under assets/ only — not mirrored clone CDN (get_site mirroredAssets or import warmJob). Not content — use list_content. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish. |
list_collections | Collections 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. |
list_content | List content keys (HTML/md); not assets — use list_assets. Defaults to 50 keys per page — raise limit (max 1000) or pass cursor (from nextCursor) to page through the rest. Per-row `size`/`missing` are measured automatically only on pages of ≤100 rows; past that they're ABSENT (not measured, never… |
list_custom_domains | List all custom hostnames and connection status for the site. |
list_form_submissions | List form submissions (metadata + bounded field preview — not full PII). Works on kv and do-sqlite backends. |
list_goals | List site conversion goals (pageview paths and form submits). Required before start_test. |
list_ideas | Search draft/published board items and open suggestions by title token overlap. |
list_my_sites | List 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)… |
And 57 more tools.
In its maker's words
Build and publish static sites on dotsy with draft-first MCP tools, OAuth Connect, and API keys.
- Website
- dotsy.ai
- Publisher
- dotsy.ai
- Listed from
- the official MCP Registry as
ai.dotsy/mcp - Version
- 0.8.15, updated 7 Nov 2026
- Kinds of work
- Domains and websites, Documents and files, Writing and translation
The domain it lives on
- dotsy.ai
- registered 8 Jun 2026 (5 months ago), at Porkbun LLC, its home page is a working site
From our own crawl of domain names: registry records and the home page as our crawler last saw it.
Every call we made
| When | What happened | Time |
|---|---|---|
| Answered | 3187 ms | |
| Answered | 2688 ms | |
| Answered | 1337 ms |
Next door
Is this your bot? Claim its address to add a verified badge and keep the listing current.