Dotsy
by dotsy.ai in Other
Build and publish static sites on Dotsy with draft-first MCP tools, OAuth Connect, and API keys.
https://mcp.dotsy.ai/mcp- Tools
- 91
- open to any client
- Uptime
- 100%
- last 30 days
- Response time
- 470 ms
- 993 ms slowest 5%
- Last check
- Passed
- 3 h ago, next in 3 h
Reliability
Status and outage history · Atom feed · Watch with other listings
How to connect
Add it to any MCP client that supports remote servers.
{
"mcpServers": {
"dotsy": {
"type": "http",
"url": "https://mcp.dotsy.ai/mcp"
}
}
}91 tools
- 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.
- 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…
- update_brief
Update `_intent/site.md` (site brief) or a page brief when `page` is set. See field descriptions for rules, notes, and head enums.
- get_analytics
Read-only traffic overview (default) or full breakdowns via include[]; optional bot id for crawler page drill-down.
- update_site
Update site settings: title, keyConvention, or editingMode ('live' = each editor save publishes immediately; 'staged' = saves stay drafts until publish_site). Slug is the hostname — change it with rename_site, not this tool. Set 'staged' before handing the editor to a person via…
- rename_site
Rename the site slug (public hostname {slug}.dotsy.site). Owner-only. After success: use the returned slug in every later tool. Published site: the old slug redirects on the API (301 for reads, 308 for writes) while it stays reserved; the old host 301s and stays reserved until…
- publish_site
Publish draft to live. feedback and handoff required (use dummy feedback + one-line handoff if clean).
- get_draft_status
Pending draft changes: content keys and routes with status. May include requiredDecision (publish_confirm) before publish_site.
- discard_drafts
Discard unpublished drafts: all (omit key/keys/routes), one content key (key), or a selection (keys, routes). Destructive — check get_draft_status first.
- delete_site
Permanently delete site; confirmSlug must equal slug.
- 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.
- 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.
- 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.
- search_content
Find pages containing a phrase (grep without reading bodies). Requires do-sqlite — graduate_site first if search_unavailable.
- 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)…
- 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…
- import_site_from_url
Import URL to draft. On complete, response may include requiredDecision — preview then ask mirror vs editable before structure_*.
- get_structure_status
Flat vs structured page counts; informs user — do not auto-run analyze/apply while requiredDecision pending.
- structure_site_analyze
Propose shared layout + fragments; persist:false first. Wait for mirror-vs-editable answer if requiredDecision pending.
- decompose_analyze
Deprecated — use structure_site_analyze.
- structure_site_apply
Rewrite flat pages to layout + fragments (draft). Do not call while requiredDecision pending — user must pick editable first. It extracts header/footer only: afterwards share_section with no arguments lists the other repeated blocks (banner, CTA).
- get_structure_result
Last structure apply job result (structuredKeys, conflicts, partial).
- 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…
- 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).
- 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.
- 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…
- 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.
- put_content
Stage 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.
- stage_content_chunk
Append 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.
- patch_content
Edit one content key via ops[] (selector ops or replace-string; wrap/unwrap/move restructure siblings). Stages draft; op shapes in schema.
- 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.
- 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.
- rename_content
Re-key a page by slug (draft or published static). Server-side hash copy — no body round-trip. Default deletes static routes (obscure-URL); movePath:true repoints the route, rewrites menu refs and other redirects aimed at the old path, and — only for an already-PUBLISHED page…
- put_post
Stage 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.
- 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 =…
- 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…
- update_collection
Rename 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…
- new_post_template
Read-only scaffold for a new post — suggested key/path, membership meta, blank or duplicate body. Then put_post (+ optional put_route).
- reindex_collection
Build/finish collection indexes after publish returns collectionDataPending or collectionSqlPending.
Security scan
No findings
We scan names, descriptions and tool definitions for hidden instructions and other prompt-injection patterns.
Recent checks
| When | Result | HTTP | Time |
|---|---|---|---|
| 3 h ago | Passed | 200 | 140 ms |
| 12 h ago | Passed | 200 | 394 ms |
| 22 h ago | Passed | 200 | 470 ms |
| 31 h ago | Passed | 200 | 2.3 s |
| 40 h ago | Passed | 200 | 672 ms |
Show 10 older checks
| 2 days ago | Passed | 200 | 393 ms |
| 2 days ago | Passed | 200 | 647 ms |
| 3 days ago | Passed | 200 | 270 ms |
| 3 days ago | Passed | 200 | 679 ms |
| 4 days ago | Passed | 200 | 383 ms |
| 4 days ago | Passed | 200 | 404 ms |
| 5 days ago | Passed | 200 | 492 ms |
| 5 days ago | Passed | 200 | 603 ms |
| 5 days ago | Passed | 200 | 434 ms |
| 6 days ago | Passed | 200 | 326 ms |