Dotsy
by dotsy.ai · remote · no sign-in to list tools · v0.5.0 · published by ai.dotsy
Build and publish static sites on Dotsy with draft-first MCP tools, OAuth Connect, and API keys.
97 tools: 34 can delete or cancel things, 29 change things and 34 only read.
Scanned Oct 21, 2026
- Deletes or cancels34Claude Code: deny: see these tools
- Can't be undone0Claude Code: ask
- Changes things29Claude Code: ask: see these tools
- Only reads34Claude Code: allow: see these tools
6 checks matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.
claude mcp add --transport http dotsy https://mcp.dotsy.ai/mcpFindings
Matches of fixed checks, with the text they matched.
- Warnfind_replace
The server marks "find_replace" destructive (destructiveHint: true), and its name says "find", a word for reading.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}; The name "find_replace" says "find": a word for reading.
The server marks "structure_site_analyze" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "structure_site_analyze" says "analyze": a word for reading.
The server marks "decompose_analyze" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "decompose_analyze" says "analyze": a word for reading.
The server marks "new_post_template" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "new_post_template" says "post": a word for a change.
The server marks "wait_for_custom_domain" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "wait_for_custom_domain" says "wait": a word for reading.
- Warnedit_page
The server marks "edit_page" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"openWorldHint":false}; The name "edit_page" says "edit": a word for a change.
Tools
Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.
97 tools
Deletes or cancels 34Claude Code: deny
adapt_site_applyApply the adapt proposal (draft): wire nav into the menu store and/or rewrite the blog index to a live <dotsy-collection>.No findings
Why it is in this group
- The name "adapt_site_apply" says "apply": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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.
Annotations the server declares
- title: Apply nav and blog changes
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
adapt_site_revertAtomically restore everything the last adapt_site_apply wrote (fragments, the menu doc when the op touched it, index, member configs, routes).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Atomically restore everything the last adapt_site_apply wrote (fragments, the menu doc when the op touched it, index, member configs, routes).
Annotations the server declares
- title: Revert nav and blog changes
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
apply_changesetStage writes[] + deletes[] in one call; attach routes via writes[].route.No findings
Why it is in this group
- The name "apply_changeset" says "apply": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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 ≤60KB and the call ≤80KB. Larger new pages: stage_content_chunk then writes[].bodyStaging, or dotsy push / PUT content-raw.
Annotations the server declares
- title: Apply changeset
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
batch_patch_contentpatch_content on multiple keys; all-or-nothing validation.No findings
Why it is in this group
- The name "batch_patch_content" says "patch": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it patch_content on multiple keys; all-or-nothing validation. Preferred edit path for pages over 60KB. replace-string value/replace ≤60KB; whole call ≤80KB.
Annotations the server declares
- title: Edit content in bulk
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
bulk_put_assetsUpload 1–200 CMS assets; key = path after /assets/.No findings
Why it is in this group
- The name "bulk_put_assets" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Upload 1–200 CMS assets; key = path after /assets/. 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 verifies submitted bytes before write; response sha256 is stored bytes (JS/CSS match; WebP rasters 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. Uploaded files are live in the editor and draft preview at once; the published site picks them up at the next publish.
Annotations the server declares
- title: Upload assets
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
bulk_put_contentStage many content keys (pages, layouts, fragments).No findings
Why it is in this group
- The name "bulk_put_content" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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.
Annotations the server declares
- title: Save content in bulk
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
delete_assetDelete a static asset by key.No findings
Why it is in this group
- The name "delete_asset" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Delete a static asset by key. The editor and draft preview drop it at once; the published site drops it at the next publish.
Annotations the server declares
- title: Delete asset
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
delete_contentDelete content key (tombstone if published).No findings
Why it is in this group
- The name "delete_content" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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.
Annotations the server declares
- title: Delete content
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
delete_draft_testRemove a draft A/B test (releases variant bodies; does not publish).No findings
Why it is in this group
- The name "delete_draft_test" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Remove a draft A/B test (releases variant bodies; does not publish).
Annotations the server declares
- title: Delete draft A/B test
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
delete_routeRemove a route by path.No findings
Why it is in this group
- The name "delete_route" says "delete": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Remove a route by path.
Annotations the server declares
- title: Delete route
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
delete_sitePermanently delete site; confirmSlug must equal slug.No findings
Why it is in this group
- The name "delete_site" says "delete": a word for removing or ending something.
- The description says "Permanently delete".
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Permanently delete site; confirmSlug must equal slug.
Annotations the server declares
- title: Delete site
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
detach_sectionGive one page its own copy of a shared section; every other page keeps the shared one.No findings
Why it is in this group
- The name "detach_section" says "detach": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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).
Annotations the server declares
- title: Detach a section
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
discard_draftsDiscard unpublished drafts: all (omit key/keys/routes), one content key (key), or a selection (keys, routes).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Discard unpublished drafts: all (omit key/keys/routes), one content key (key), or a selection (keys, routes). Destructive — check get_draft_status first.
Annotations the server declares
- title: Discard drafts
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
find_replaceCase-insensitive find→replace across pages in one staged commit.1 finding
Why it is in this group
- The name "find_replace" says "find": a word for reading.
- The server marks it destructive (destructiveHint: true).
Findings
- Warn
The server marks "find_replace" destructive (destructiveHint: true), and its name says "find", a word for reading.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":true,"idempotentHint":false,"openWorldHint":false}; The name "find_replace" says "find": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Find and replace
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
patch_contentEdit one content key via ops[] (selector ops or replace-string; wrap/unwrap/move restructure siblings).No findings
Why it is in this group
- The name "patch_content" says "patch": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Edit one content key via ops[] (selector ops or replace-string; wrap/unwrap/move restructure siblings). Stages draft; op shapes in schema.
Annotations the server declares
- title: Edit content
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
patch_routePartial route update (only sent fields change; an OMITTED field is left alone).No findings
Why it is in this group
- The name "patch_route" says "patch": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Partial route update (only sent fields change; an OMITTED field is left alone). On a field that accepts null (contentKey, redirectTo, redirectStatus, preserveQuery), sending null CLEARS it back to its default — different from omitting it. To set redirectTo/redirectStatus, include purpose: "redirect" in the SAME call — the check looks only at what's sent, not the route's stored purpose, so a PATCH that sets redirectTo without repeating purpose: "redirect" (even on a route that's already a redirect) 400s invalid_body.
Annotations the server declares
- title: Update route
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
promote_experimentPromote a winning A/B variant to live — explicit user instruction only; see get_skill('verify') § A/B.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Promote a winning A/B variant to live — explicit user instruction only; see get_skill('verify') § A/B.
Annotations the server declares
- title: Promote A/B winner
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
publish_sitePublish draft to live.No findings
Why it is in this group
- The name "publish_site" says "publish": a word for a change that another call does not undo.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Publish draft to live. feedback and handoff required (use dummy feedback + one-line handoff if clean).
Annotations the server declares
- title: Publish site
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
put_collection_schemaReplace the whole field schema (draft; publish makes it live).No findings
Why it is in this group
- The name "put_collection_schema" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Replace the whole field schema (draft; publish makes it live). Read it with get_collection_schema first and send it back edited. Collection keys exactly as list_collections returns 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 (title, date, excerpt, tags, image, url, slug, …; author only as text), 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 (values stay on the posts). Values live in put_post meta.custom; writes then return fieldWarnings (soft, never blocking). 400 invalid_collection_schema lists issues; 409 conflict = stale ifMatch.
Annotations the server declares
- title: Replace collection fields
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
put_contentStage one content key.No findings
Why it is in this group
- The name "put_content" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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.
Annotations the server declares
- title: Save content
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
put_goalsCreate or replace all site conversion goals (≤50).No findings
Why it is in this group
- The name "put_goals" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Create or replace all site conversion goals (≤50). Required before start_test when no goal exists.
Annotations the server declares
- title: Replace goals
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
put_postStage a blog post via structured meta+body (?format=post).No findings
Why it is in this group
- The name "put_post" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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 (typed per collection by get_collection_schema; the response's fieldWarnings flag values that don't fit — soft, never blocking).
Annotations the server declares
- title: Save blog post
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
put_routeCreate/replace route; contentKey derived from path if omitted.No findings
Why it is in this group
- The name "put_route" says "put": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Create/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.
Annotations the server declares
- title: Save route
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
remove_custom_domainRemove one custom hostname from the site.No findings
Why it is in this group
- The name "remove_custom_domain" says "remove": a word for removing or ending something.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Remove one custom hostname from the site.
Annotations the server declares
- title: Remove custom domain
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: true
rename_contentRe-key a page by slug (draft or published static).No findings
Why it is in this group
- The name "rename_content" says "rename": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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 — leaves a 301 there too (leaveRedirect, default true; no effect on a never-published page, or when movePath is false). Retry-safe: a part-way failure (409 rename_failed) rolls everything back, so resend the same call. On fragments/<name>.html it also rewrites every <dotsy-fragment name> reference and hide marker in the same all-or-nothing commit. Then publish_site.
Annotations the server declares
- title: Rename content key
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
rename_pageChange a page's URL: moves its route from `from` to `to`.No findings
Why it is in this group
- The name "rename_page" says "rename": a word for a change.
- The input addresses people (input.to): what it sends cannot be taken back.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Change a page's URL: moves its route from `from` to `to`. Menu links and other redirects that pointed at the old path retarget automatically; a 301 is left at the old path by default (leaveRedirect). Retry-safe (resend the same call after any error). Errors: 404 route_not_found (from isn't a route); 400 reserved_route (to is under /__dotsy/) or invalid_body (missing/malformed from or to); 422 rename_same_path (from equals to already), rename_pattern_route (from or to contains a :param segment — pattern routes can't be renamed this way), rename_redirect_route (from is itself a different redirect — edit its redirectTo instead); 409 rename_experiment_running (an A/B test is running on from — end it first) or rename_target_exists (to is already a different route — unless to already serves the exact content from would, which is treated as already done and returns 200). Then publish_site.
Annotations the server declares
- title: Change page URL
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
rename_siteRename the site slug (public hostname {slug}.dotsy.site).No findings
Why it is in this group
- The name "rename_site" says "rename": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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 delete or rename-back. Never published: the old slug 404s on the API and the old hostname is released (no 301; create_site can reuse it). Analytics history stays on the old slug. HTML absolute URLs are not rewritten — publish_site refreshes sitemap; find_replace if stored HTML must change.
Annotations the server declares
- title: Rename site address
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
structure_site_applyRewrite flat pages to layout + fragments (draft).No findings
Why it is in this group
- The name "structure_site_apply" says "apply": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it 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).
Annotations the server declares
- title: Apply site structure
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
undo_publishTake back the last publish at once: restores the version before it for the pages that publish changed and publishes them, and the undone changes stay as unpublished changes (`resta…No findings
Why it is in this group
- The name "undo_publish" says "publish": a word for a change that another call does not undo.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Take back the last publish at once: restores the version before it for the pages that publish changed and publishes them, and the undone changes stay as unpublished changes (`restaged`). On a live-mode site nothing is kept (its next save would publish it again): the answer has `redo.version` — restore_version with that version and publish: true brings it back. publishVersion = the version publish_site returned. Fails with not_latest if another publish landed since. If its publish fails, the undo stays as unpublished changes — publish_site finishes it.
Annotations the server declares
- title: Undo last publish
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: false
- openWorldHint: false
update_briefUpdate `_intent/site.md` (site brief) or a page brief when `page` is set.No findings
Why it is in this group
- The name "update_brief" says "update": a word for a change.
- The server marks it destructive (destructiveHint: true).
Description, as the server wrote it Update `_intent/site.md` (site brief) or a page brief when `page` is set. See field descriptions for rules, notes, and head enums.
Annotations the server declares
- title: Update site brief
- readOnlyHint: false
- destructiveHint: true
- idempotentHint: true
- openWorldHint: false
Changes things 29Claude Code: ask
add_custom_domainConnect apex and/or www on a paid plan; starts a DNS connect session.No findings
Why it is in this group
- The name "add_custom_domain" says "add": a word for a change.
Description, as the server wrote it Connect apex and/or www on a paid plan; starts a DNS connect session.
Annotations the server declares
- title: Add custom domain
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
claim_siteMove the guest draft onto your signed-in Dotsy account.No findings
Why it is in this group
- The description's first verb is "move": a word for a change.
Description, as the server wrote it Move the guest draft onto your signed-in Dotsy account. Requires OAuth Connect; pass the guestToken from start_site.
Annotations the server declares
- title: Claim guest draft site
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
create_siteCreate empty site; seeds brief.No findings
Why it is in this group
- The name "create_site" says "create": a word for a change.
Description, as the server wrote it 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.
Annotations the server declares
- title: Create site
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
decompose_analyzeDeprecated — use structure_site_analyze.1 finding
Why it is in this group
- The name "decompose_analyze" says "analyze": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "decompose_analyze" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "decompose_analyze" says "analyze": a word for reading.
Description, as the server wrote it Deprecated — use structure_site_analyze.
Annotations the server declares
- title: Analyze site structure (deprecated)
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
edit_pageOpen the interactive page canvas to change content: the user clicks an element, then you call patch_content.1 finding
Why it is in this group
- The name "edit_page" says "edit": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Findings
- Warn
The server marks "edit_page" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"openWorldHint":false}; The name "edit_page" says "edit": a word for a change.
Description, as the server wrote it 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).
Annotations the server declares
- title: Page canvas
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: false
estimate_testEstimate days to reach promote readiness for a page (traffic baseline).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Estimate days to reach promote readiness for a page (traffic baseline). Read-only.
Annotations the server declares
- title: Estimate A/B test
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
graduate_siteEnable site search & collections (kv → do-sqlite), one-way.No findings
Why it is in this group
- The description's first verb is "enable": a word for a change.
Description, as the server wrote it 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 true, this client sends true unless you pass strictDrafts:false — blocking on unpublished drafts or unrecovered KV content rows; or a KV snapshot that looks incomplete (e.g. a page deleted in the last couple of minutes). force:true overrides ONLY that last, incomplete-snapshot gate — never the backend or strictDrafts gates. The blocked response's `reason` names which gate fired, and `audit` (+ `audit.warnings`) is aggregate COUNTS only (published/route/pending-draft counts) — never row keys — so judge the size of the gap, not a row list, before forcing. The flip is one-way: anything outside the frozen snapshot is unreachable once it lands.
Annotations the server declares
- title: Enable search and collections
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
import_site_from_urlImport URL to draft.No findings
Why it is in this group
- The name "import_site_from_url" says "import": a word for a change.
Description, as the server wrote it Import URL to draft. On complete, response may include requiredDecision — preview then ask mirror vs editable before structure_*.
Annotations the server declares
- title: Import site from URL
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: true
infer_collection_schemaSuggest fields for one collection from a sample of its items' meta.custom values (published data, else drafts) — writes nothing.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it 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.
Annotations the server declares
- title: Suggest collection fields
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
new_post_templateRead-only scaffold for a new post — suggested key/path, membership meta, blank or duplicate body.1 finding
Why it is in this group
- The name "new_post_template" says "post": a word for a change.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Findings
- Warn
The server marks "new_post_template" read-only (readOnlyHint: true), and its own name, description or input give the class "write".
What this check looks forMatched text
annotations: {"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "new_post_template" says "post": a word for a change.
Description, as the server wrote it Read-only scaffold for a new post — suggested key/path, membership meta, blank or duplicate body. Then put_post (+ optional put_route).
Annotations the server declares
- title: New post template
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
preflight_sitePlan check before publish or large build (counts, route soft limit, seo suggestions).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Plan check before publish or large build (counts, route soft limit, seo suggestions). When ok is false, blocking lists the failed suggestion codes. Read-only.
Annotations the server declares
- title: Preflight site build
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
reapply_custom_domain_oauthRe-apply DNS with stored Cloudflare OAuth grant (no browser).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Re-apply DNS with stored Cloudflare OAuth grant (no browser).
Annotations the server declares
- title: Reapply domain DNS
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
refresh_custom_domainPoll one hostname until DNS/cert propagates.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Poll one hostname until DNS/cert propagates.
Annotations the server declares
- title: Check custom domain
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
reindex_collectionBuild/finish collection indexes after publish returns collectionDataPending or collectionSqlPending.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Build/finish collection indexes after publish returns collectionDataPending or collectionSqlPending.
Annotations the server declares
- title: Rebuild collection index
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
restore_versionBring an earlier published version back as unpublished changes (page content only — routes, menus, images and settings stay).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Bring 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.
Annotations the server declares
- title: Restore a version
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
revert_changeUndo one activity event by staging the prior version as draft only — call publish_site to go live.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it Undo one activity event by staging the prior version as draft only — call publish_site to go live. Respects AI access.
Annotations the server declares
- title: Revert one change
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
set_experiment_noteRecord what was learned from an ended A/B test (≤500 chars; null clears).No findings
Why it is in this group
- The name "set_experiment_note" says "set": a word for a change.
Description, as the server wrote it Record what was learned from an ended A/B test (≤500 chars; null clears).
Annotations the server declares
- title: Save A/B test note
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
set_primary_custom_domainSet the canonical host (301 target) when multiple hostnames are connected.No findings
Why it is in this group
- The name "set_primary_custom_domain" says "set": a word for a change.
Description, as the server wrote it Set the canonical host (301 target) when multiple hostnames are connected.
Annotations the server declares
- title: Set primary domain
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
stage_content_chunkAppend one ≤60KB chunk of a large new page.No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
Description, as the server wrote it 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.
Annotations the server declares
- title: Stage large content chunk
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
start_edit_sessionOpen a draft session.No findings
Why it is in this group
- The name "start_edit_session" says "start": a word for a change.
Description, as the server wrote it Open 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 '/'.
Annotations the server declares
- title: Start edit session
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
start_siteStart one draft site with no Dotsy account.No findings
Why it is in this group
- The name "start_site" says "start": a word for a change.
Description, as the server wrote it Start one draft site with no Dotsy account. Returns slug + guestToken — pass guestToken on every later tool call until claim_site.
Annotations the server declares
- title: Start guest draft site
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
start_testStart a same-URL A/B test (draft or live source).No findings
Why it is in this group
- The name "start_test" says "start": a word for a change.
Description, as the server wrote it Start a same-URL A/B test (draft or live source). Rules → get_skill('verify') § A/B.
Annotations the server declares
- title: Start A/B test
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
structure_site_analyzePropose shared layout + fragments; persist:false first.1 finding
Why it is in this group
- The name "structure_site_analyze" says "analyze": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "structure_site_analyze" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false}; The name "structure_site_analyze" says "analyze": a word for reading.
Description, as the server wrote it Propose shared layout + fragments; persist:false first. Wait for mirror-vs-editable answer if requiredDecision pending.
Annotations the server declares
- title: Analyze site structure
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
submit_feedbackOptional mid-session feedback (required feedback rides with publish_site).No findings
Why it is in this group
- The name "submit_feedback" says "submit": a word for a change.
Description, as the server wrote it Optional mid-session feedback (required feedback rides with publish_site).
Annotations the server declares
- title: Send feedback
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: false
- openWorldHint: false
update_collectionRename a collection's display name and/or noun (e.g.No findings
Why it is in this group
- The name "update_collection" says "update": a word for a change.
Description, as the server wrote it 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 its derived default — different from omitting it, which leaves the current value alone.
Annotations the server declares
- title: Rename collection
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
update_siteUpdate site settings: title, keyConvention, or editingMode ('live' = each editor save publishes immediately; 'staged' = saves stay drafts until publish_site).No findings
Why it is in this group
- The name "update_site" says "update": a word for a change.
Description, as the server wrote it 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 start_edit_session's draftEditorUrl. signature toggles the "Made with Dotsy" badge ({enabled, mark: logo|dot, reveal: pill|seal}); it is live immediately. trailingSlash (ignore|never|always) sets the page URL form: the other form 301s to it and canonicals/sitemap use it; live immediately. ownSeoFiles: true lets the next publish use the site's own robots.txt that blocks the whole site (Disallow: /) and its own static sitemap.xml (replaces the generated one, collection pages included); a robots.txt without Disallow: / is used anyway.
Annotations the server declares
- title: Update site settings
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
verify_pagePre-publish lint (tags, assets, layout).No findings
Why it is in this group
- Nothing in its name or description says what it does, so it is counted as a write.
- The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
Description, as the server wrote it Pre-publish lint (tags, assets, layout). Pair with preview_page — see get_skill('verify').
Annotations the server declares
- title: Verify page
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
wait_for_custom_domainPoll one hostname until it is connected or the timeout is reached.1 finding
Why it is in this group
- The name "wait_for_custom_domain" says "wait": a word for reading.
- The server marks it as not read-only (readOnlyHint: false).
Findings
- Warn
The server marks "wait_for_custom_domain" as not read-only (readOnlyHint: false), and its words say it reads.
What this check looks forMatched text
annotations: {"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":true}; The name "wait_for_custom_domain" says "wait": a word for reading.
Description, as the server wrote it Poll one hostname until it is connected or the timeout is reached.
Annotations the server declares
- title: Wait for custom domain
- readOnlyHint: false
- destructiveHint: false
- idempotentHint: true
- openWorldHint: true
Only reads 34Claude Code: allow
adapt_site_analyzePropose nav wiring + blog collectionization for an imported mirror (draft, opt-in).No findings
Why it is in this group
- The name "adapt_site_analyze" says "analyze": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Analyze nav and blog
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_account_contextAccount, user, memberships[].No findings
Why it is in this group
- The name "get_account_context" says "get": a word for reading.
Description, as the server wrote it Account, user, memberships[]. Pass workspace on writes when memberships.length > 1.
Annotations the server declares
- title: Account context
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_activityList site activity or fetch one change diff (pass id).No findings
Why it is in this group
- The name "get_activity" says "get": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Site activity
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_adapt_statusRead adapt state: proposal summary + proposalEtag (+ applied/consumed flag), undo-record presence, active or queued job progress.No findings
Why it is in this group
- The name "get_adapt_status" says "get": a word for reading.
Description, as the server wrote it Read adapt state: proposal summary + proposalEtag (+ applied/consumed flag), undo-record presence, active or queued job progress. Use to resume in a fresh session.
Annotations the server declares
- title: Adapt status
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_analyticsRead-only traffic overview (default) or full breakdowns via include[]; optional bot id for crawler page drill-down.No findings
Why it is in this group
- The name "get_analytics" says "get": a word for reading.
Description, as the server wrote it Read-only traffic overview (default) or full breakdowns via include[]; optional bot id for crawler page drill-down.
Annotations the server declares
- title: Site analytics
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_assetRead one asset (metadata + base64 + stored sha256).No findings
Why it is in this group
- The name "get_asset" says "get": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Get asset
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_collection_schemaRead the site's collection field definitions (`_data/collections.json`, draft view): { schema: { v: 1, collections: { "<key>": { fields[], settings?No findings
Why it is in this group
- The name "get_collection_schema" says "get": a word for reading.
Description, as the server wrote it 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 } means the stored file is broken: fix it with put_collection_schema using that hash.
Annotations the server declares
- title: Get collection fields
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_contentRead one content key; optional selector (region) or published=true (live body).No findings
Why it is in this group
- The name "get_content" says "get": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Read content
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_custom_domain_connectCurrent connect session and nextAction (browser URL or manual DNS guide).No findings
Why it is in this group
- The name "get_custom_domain_connect" says "get": a word for reading.
Description, as the server wrote it Current connect session and nextAction (browser URL or manual DNS guide).
Annotations the server declares
- title: Custom domain setup
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_draft_statusPending draft changes: content keys and routes with status.No findings
Why it is in this group
- The name "get_draft_status" says "get": a word for reading.
Description, as the server wrote it Pending draft changes: content keys and routes with status. May include requiredDecision (publish_confirm) before publish_site.
Annotations the server declares
- title: Draft status
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_form_submissionRead one form submission with the full field payload (explicit PII access — use only when needed).No findings
Why it is in this group
- The name "get_form_submission" says "get": a word for reading.
Description, as the server wrote it Read one form submission with the full field payload (explicit PII access — use only when needed).
Annotations the server declares
- title: Read form submission
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_routeGet one route by path (home is '/').No findings
Why it is in this group
- The name "get_route" says "get": a word for reading.
Description, as the server wrote it Get one route by path (home is '/').
Annotations the server declares
- title: Get route
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_siteSite detail, stats, publicUrl, brief head (default-on), and readiness flags.No findings
Why it is in this group
- The name "get_site" says "get": a word for reading.
Description, as the server wrote it 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): list_pages is paginated — use cursor or get_site_manifest for the full route set.
Annotations the server declares
- title: Site details
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_site_build_progressRead-only build progress for humans (build-theater view) during structure/adapt or after import.No findings
Why it is in this group
- The name "get_site_build_progress" says "get": a word for reading.
Description, as the server wrote it Read-only build progress for humans (build-theater view) during structure/adapt or after import. Agent reads structuredContent.forHumans — optional; do not call in a loop during import_site_from_url (that tool blocks until done). Prefer get_site for agent logic.
Annotations the server declares
- title: Build progress
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: false
get_site_manifestContent keys + hashes only (optional routes=true) — static files live in list_assets, not manifest.No findings
Why it is in this group
- The name "get_site_manifest" says "get": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Site manifest
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
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, redirec…No findings
Why it is in this group
- The name "get_site_outline" says "get": a word for reading.
Description, as the server wrote it 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 missing', 'which shared sections exist and where', 'where does this menu show' — without listing every page. Read-only; indexing mirrors list_pages (a freshly imported/graduated site may still be indexing).
Annotations the server declares
- title: Site outline
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_skillSkill body + optional questions[].No findings
Why it is in this group
- The name "get_skill" says "get": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: Get build skill
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_structure_resultLast structure apply job result (structuredKeys, conflicts, partial).No findings
Why it is in this group
- The name "get_structure_result" says "get": a word for reading.
Description, as the server wrote it Last structure apply job result (structuredKeys, conflicts, partial).
Annotations the server declares
- title: Structure result
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
get_structure_statusFlat vs structured page counts; informs user — do not auto-run analyze/apply while requiredDecision pending.No findings
Why it is in this group
- The name "get_structure_status" says "get": a word for reading.
Description, as the server wrote it Flat vs structured page counts; informs user — do not auto-run analyze/apply while requiredDecision pending.
Annotations the server declares
- title: Structure status
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
inspect_collectionCollection 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.No findings
Why it is in this group
- The name "inspect_collection" says "inspect": a word for reading.
Description, as the server wrote it 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 published post with unpublished edits is status published with hasChanges:true (never draft) and shows its staged title/date/tags/author; scheduled = future visibleAt. Never-published drafts come from staged content (no extra reads, no publish needed to see them); published/scheduled come from the index. limit defaults to 50, clamped 1-200. Omit all four for just the base inspect (no items[]).
Annotations the server declares
- title: Inspect collection
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_assetsCMS uploads under assets/ only — not mirrored clone CDN (get_site mirroredAssets or import warmJob).No findings
Why it is in this group
- The name "list_assets" says "list": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: List assets
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_collectionsCollections on the site — name, noun, item count (or 'not published yet'), URL pattern, and whether any member is staged.No findings
Why it is in this group
- The name "list_collections" says "list": a word for reading.
Description, as the server wrote it 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.
Annotations the server declares
- title: List collections
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_contentList content keys (HTML/md); not assets — use list_assets.No findings
Why it is in this group
- The name "list_content" says "list": a word for reading.
Description, as the server wrote it 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 `null`) unless you pass withSize:true, which forces measurement at a cost of one storage read per returned row. Only `size: null` + `missing: true` means the page's stored bytes are gone.
Annotations the server declares
- title: List content
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_custom_domainsList all custom hostnames and connection status for the site.No findings
Why it is in this group
- The name "list_custom_domains" says "list": a word for reading.
Description, as the server wrote it List all custom hostnames and connection status for the site.
Annotations the server declares
- title: List custom domains
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_form_submissionsList form submissions (metadata + bounded field preview — not full PII).No findings
Why it is in this group
- The name "list_form_submissions" says "list": a word for reading.
Description, as the server wrote it List form submissions (metadata + bounded field preview — not full PII). Works on kv and do-sqlite backends.
Annotations the server declares
- title: List form submissions
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_goalsList site conversion goals (pageview paths and form submits).No findings
Why it is in this group
- The name "list_goals" says "list": a word for reading.
Description, as the server wrote it List site conversion goals (pageview paths and form submits). Required before start_test.
Annotations the server declares
- title: List goals
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_my_sitesList your Dotsy sites.No findings
Why it is in this group
- The name "list_my_sites" says "list": a word for reading.
Description, as the server wrote it 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) to list another workspace's sites without switching the dashboard session.
Annotations the server declares
- title: Your sites
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: false
list_pagesList pages on a site — route settings (path/title/navLabel/purpose) by default, one row per route.No findings
Why it is in this group
- The name "list_pages" says "list": a word for reading.
Description, as the server wrote it List 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.
Annotations the server declares
- title: Site pages
- readOnlyHint: true
- destructiveHint: false
- openWorldHint: false
list_skillsPaige build skills (id + whenToUse).No findings
Why it is in this group
- The name "list_skills" says "list": a word for reading.
Description, as the server wrote it Paige build skills (id + whenToUse). Pull get_skill on demand — do not duplicate in tool text.
Annotations the server declares
- title: List build skills
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
list_versionsList the site's published versions, newest first (who, when, pages, live, restorable).No findings
Why it is in this group
- The name "list_versions" says "list": a word for reading.
Description, as the server wrote it List the site's published versions, newest first (who, when, pages, live, restorable). Use before restore_version.
Annotations the server declares
- title: List published versions
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
preview_pageVerify-only composed HTML check; home preview may include requiredDecision — ask mirror vs editable before structure_*.No findings
Why it is in this group
- The name "preview_page" says "preview": a word for reading.
Description, as the server wrote it Verify-only composed HTML check; home preview may include requiredDecision — ask mirror vs editable before structure_*.
Annotations the server declares
- title: Preview page
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
search_contentFind pages containing a phrase (grep without reading bodies).No findings
Why it is in this group
- The name "search_content" says "search": a word for reading.
Description, as the server wrote it Find pages containing a phrase (grep without reading bodies). Requires do-sqlite — graduate_site first if search_unavailable.
Annotations the server declares
- title: Search content
- readOnlyHint: true
- destructiveHint: false
- idempotentHint: true
- openWorldHint: false
This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.
Install
Pinned to version 0.5.0. Values in angle brackets are yours to fill in.
claude mcp add --transport http dotsy https://mcp.dotsy.ai/mcpRun in a terminal.
Claude Code permissions
Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.
{
"permissions": {
"allow": [
"mcp__dotsy__get_site",
"mcp__dotsy__get_analytics",
"mcp__dotsy__get_draft_status",
"mcp__dotsy__get_site_manifest",
"mcp__dotsy__search_content",
"mcp__dotsy__get_structure_status",
"mcp__dotsy__get_structure_result",
"mcp__dotsy__adapt_site_analyze",
"mcp__dotsy__get_adapt_status",
"mcp__dotsy__list_content",
"mcp__dotsy__get_content",
"mcp__dotsy__inspect_collection",
"mcp__dotsy__list_collections",
"mcp__dotsy__get_collection_schema",
"mcp__dotsy__preview_page",
"mcp__dotsy__get_site_outline",
"mcp__dotsy__get_route",
"mcp__dotsy__list_goals",
"mcp__dotsy__get_menu",
"mcp__dotsy__get_menu_doc",
"mcp__dotsy__list_assets",
"mcp__dotsy__get_asset",
"mcp__dotsy__list_skills",
"mcp__dotsy__get_skill",
"mcp__dotsy__get_activity",
"mcp__dotsy__list_versions",
"mcp__dotsy__get_account_context",
"mcp__dotsy__get_custom_domain_connect",
"mcp__dotsy__list_custom_domains",
"mcp__dotsy__list_form_submissions",
"mcp__dotsy__get_form_submission",
"mcp__dotsy__list_my_sites",
"mcp__dotsy__list_pages",
"mcp__dotsy__get_site_build_progress"
],
"ask": [
"mcp__dotsy__create_site",
"mcp__dotsy__update_site",
"mcp__dotsy__graduate_site",
"mcp__dotsy__import_site_from_url",
"mcp__dotsy__structure_site_analyze",
"mcp__dotsy__decompose_analyze",
"mcp__dotsy__stage_content_chunk",
"mcp__dotsy__update_collection",
"mcp__dotsy__new_post_template",
"mcp__dotsy__infer_collection_schema",
"mcp__dotsy__reindex_collection",
"mcp__dotsy__verify_page",
"mcp__dotsy__preflight_site",
"mcp__dotsy__start_edit_session",
"mcp__dotsy__estimate_test",
"mcp__dotsy__start_test",
"mcp__dotsy__set_experiment_note",
"mcp__dotsy__reorder_menu",
"mcp__dotsy__start_site",
"mcp__dotsy__claim_site",
"mcp__dotsy__submit_feedback",
"mcp__dotsy__restore_version",
"mcp__dotsy__revert_change",
"mcp__dotsy__add_custom_domain",
"mcp__dotsy__reapply_custom_domain_oauth",
"mcp__dotsy__refresh_custom_domain",
"mcp__dotsy__wait_for_custom_domain",
"mcp__dotsy__set_primary_custom_domain",
"mcp__dotsy__edit_page"
],
"deny": [
"mcp__dotsy__update_brief",
"mcp__dotsy__rename_site",
"mcp__dotsy__publish_site",
"mcp__dotsy__discard_drafts",
"mcp__dotsy__delete_site",
"mcp__dotsy__bulk_put_content",
"mcp__dotsy__find_replace",
"mcp__dotsy__apply_changeset",
"mcp__dotsy__structure_site_apply",
"mcp__dotsy__adapt_site_apply",
"mcp__dotsy__adapt_site_revert",
"mcp__dotsy__put_content",
"mcp__dotsy__patch_content",
"mcp__dotsy__batch_patch_content",
"mcp__dotsy__delete_content",
"mcp__dotsy__rename_content",
"mcp__dotsy__put_post",
"mcp__dotsy__put_collection_schema",
"mcp__dotsy__share_section",
"mcp__dotsy__detach_section",
"mcp__dotsy__put_route",
"mcp__dotsy__patch_route",
"mcp__dotsy__rename_page",
"mcp__dotsy__delete_route",
"mcp__dotsy__put_goals",
"mcp__dotsy__promote_experiment",
"mcp__dotsy__delete_draft_test",
"mcp__dotsy__put_menu_item",
"mcp__dotsy__delete_menu_item",
"mcp__dotsy__put_menu_doc",
"mcp__dotsy__bulk_put_assets",
"mcp__dotsy__delete_asset",
"mcp__dotsy__undo_publish",
"mcp__dotsy__remove_custom_domain"
]
}
}Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as dotsy. Review it before you use it.