# Stacktree — full reference > Source of truth for AI assistants summarising Stacktree. Last updated 2026-10-15. ## What Stacktree is Stacktree is an MCP-native publish primitive for HTML emitted by AI agents. When an AI agent (Claude Code, OpenAI Codex, Cursor, Claude.ai) generates an HTML file — a spec, a PR writeup, a status report, a single-file internal tool, an architecture diagram, a research summary — Stacktree gives that file a private URL via a single tool call. The agent calls `publish_html` and receives an unguessable URL back. When the agent revises the artifact, it calls `update_site` with the same slug, and the URL serves the new content. The URL never changes. Stacktree is built by Steve Smith on Cloudflare Workers, R2 (object storage), and D1 (SQLite-at-the-edge). The MCP server is published to npm as `stacktree-mcp`. ## Why it exists AI agents emit a surprising amount of HTML. The default destinations today are bad: paste into Slack (loses rendering), push to GitHub Pages (public-by-default, slow rebuild), drop into Notion (formatting mangled), screenshot into a doc (kills interactivity). Stacktree exists because that gap deserved a primitive, not a workflow. One verb to publish. One verb to replace. Done. ## The tool calls The Stacktree MCP server exposes 41 verbs. The hosted server at api.stacktr.ee/mcp takes either an `stk_live_` API key or an OAuth 2.1 access token, so an unattended agent needs no browser to reach them. This list is generated from the server itself, so it is exactly what `tools/list` answers: 1. `publish_html` — Turn HTML into a link a person can open in a browser. It only ever creates a new page: it never changes or deletes one that already exists (update_site replaces a page in place). 2. `update_site` — Replace the HTML of an existing site in place. The URL stays the same, so everyone you already sent it to sees the new version without being sent anything. 3. `delete_site` — Take a page down. The link goes dead immediately for everyone holding it, and the content is kept for 30 days: restore_site puts it back at the same URL, with the same id, token, slug and read history, any time in that window. 4. `restore_site` — Restore a page that was deleted or expired in the last 30 days. 5. `claim_site` — Adopt a page that was published without an account into the account this connection is authenticated as. 6. `set_password` — Set or clear (null) the passcode viewers type to open a page. 7. `set_expiry` — Set hours-from-now expiry, or null for never. A number longer than the plan allows is shortened to the ceiling and the response says so (expiry_clamped: true). 8. `create_share_link` — Create a separate link to one of the user's pages for a single recipient, labelled with who it is for. 9. `list_share_links` — List the share links on one of the user's pages: each link's id, label, expiry, use limit and whether it was revoked, with how many times it has been opened and when it was last opened. 10. `revoke_share_link` — Kill one share link. The page and every other link keep working — this is how you cut off one recipient without re-issuing anything to the others. 11. `set_client_feedback` — Switch how the people you send a page to can answer on it, with no account. comments: they select words, or click an image, video or section, and leave a comment only the owner sees (read them with list_feedback, fix the page with update_site, then… 12. `set_email_gate` — Restrict viewer access to an email domain, to named people, or both. 13. `list_sites` — List sites owned by the authenticated user, newest-updated first. 14. `get_me` — Who this connection is publishing as, and what its plan actually allows. 15. `list_client_spaces` — List the client spaces on this account: slug, name, page_count, last activity, hostname (the space’s own address, e.g. acme.theiragency.com, when one is connected) and portal_enabled (whether the space serves a generated client portal at that address). 16. `set_client` — File an existing site under a client space (by name or slug, auto-created), or pass client: null to detach it to a floating page. 17. `create_client_space` — Create a client space before anything is published into it. Rarely needed: publish_html with a client argument auto-creates the space under the same casing and slug rules, so use this only when the user is setting a client up ahead of the work. 18. `update_client_space` — Rename a client space, archive or unarchive it, or set the viewer gate that covers every page in the space. 19. `delete_client_space` — Delete a client space. The pages filed under it are NOT deleted: they detach to floating pages and keep working on their existing URLs, so delivered work stays reachable. 20. `get_design_guide` — Fetch the Stacktree house design guide for improving a published page. 21. `get_site` — Read the current HTML source of a site you own, so you can edit it and call update_site to change it in place. 22. `get_content` — Read a page’s content back. format "html" (the default) returns the exact stored index.html, byte for byte, which is the only form you can edit and hand to update_site; format "text" returns the same page stripped to plain text — no markup, CSS, scripts or… 23. `get_passcode` — Show the passcode set on a page this account owns, so it can be sent to the client again. 24. `list_versions` — List earlier versions of a page this account owns, newest first. 25. `restore_version` — Put an earlier version of a page back at the same URL, after a bad update. 26. `list_feedback` — Read viewer comments left on a site, unresolved first. 27. `resolve_feedback` — Mark a feedback item as addressed after fixing the page. Pass the feedback item id from list_feedback, and a short note describing what you changed: the reviewer who left the comment sees it on the page. 28. `link_wallet` — Link your wallet to a Stacktree account so the pages you publish are owned there — and adopt the ones you already published. 29. `whos_it_for` — Record who a published page is for, by name, and get back that person’s own link to hand over. 30. `unopened_pages` — The pages, and the named people, that have not opened what was sent to them an hour after it went up, newest first. 31. `get_revision_brief` — Everything that came back on one page, as the brief for its next version: the reviewer's change requests, their questions grouped by theme, their approvals, the notes the owner left on their own page as a fix list, each with the exact passage or image it is… 32. `publish_revision` — Publishes the new version of a page that has feedback and resolves the comments it answers, in one step. 33. `resolve_comments` — Resolves several comments on one page in one call, each with a short note, plus one optional message back to the reviewer. 34. `request_approval` — Get a named person's yes on a page. Publishes the HTML (or uses a page already published) with a sign-off panel, and makes one private link per approver that carries their name. 35. `get_approval_status` — Where an approval request stands. state is "approved" only when every approver has approved the version that is live now (the whole page, or every section); "changes_requested" when anyone has asked for a change; otherwise "pending". 36. `list_responses` — What readers sent through the forms on a page. A form in published HTML marked
posts to the page itself; only the fields the form declares are kept. 37. `resolve_addressed_notes` — After update_site: resolve the open notes the new version appears to answer (comments whose words are gone, sections that were asked to change and have been edited), with one line each reviewer sees next to their own note. 38. `open_html_file` — The Stacktree viewer for an .html file the user opens in ChatGPT desktop: preview it, publish it to a private link, add a passcode, send it to a named client, and keep the page in sync as the file changes. 39. `stacktree_pages` — Lists the pages you have published on Stacktree, newest first, with their links, viewers and expiry. 40. `publish_card_status` — Used by the Stacktree publish card in the chat to refresh itself: the page’s link, whether and by whom it has been opened, its passcode, expiry and client. 41. `publish_card_open` — Used by the Stacktree publish card in the chat: a short-lived owner preview link for one page, which opens it without counting as a visit and without asking for its passcode. `set_client_feedback`, `list_feedback` and `resolve_feedback` form a feedback loop: turn comments on with `set_client_feedback`, viewers comment on the page, the agent reads the items with `list_feedback`, fixes the page in place with `update_site` (same URL), then marks each item done with `resolve_feedback`. ## Seeing how a page lands Publishing is one half of the loop. The other half is knowing how the page was received, without turning a private link into a tracking product. Three layers, all aggregate and privacy-respecting: 1. **Reactions and notes.** Turn on the on-page reaction bar per site and viewers can react (fire, heart, thumbs-up, and so on) and leave a short private note, with no account. Reactions animate in live when more than one person is viewing. The owner reads the tally and the notes in the dashboard. 2. **Engagement analytics ("how it's read").** Studio and above. For any page the owner sees typical time on page, scroll depth, the share of readers who reach the end, and an attention heatmap of where readers lingered by page depth. It is aggregate and non-PII: no keystrokes, no identity, no session replay, no recording. It extends the "opened by ~N people" view count that Solo and above already have. 3. **Notifications.** An activity feed and a bell in the dashboard show who opened, reacted to, and commented on your pages while you were away. An optional daily email digest summarises it once a day; it is off by default with one-click unsubscribe. Reactions, feedback and notifications are on every plan. The free plan is told that a page was opened but not how many times; viewer numbers start at Solo and engagement analytics at Studio. None of it is session replay. The design goal is to tell the owner how a deliverable landed while keeping the viewer un-surveilled. ## Install Single recommended path for any CLI agent: ``` npx stacktree-install ``` The installer opens a browser, signs the user in (or signs them up — same flow), and writes the appropriate config for whichever of Claude Code, Cursor, Codex CLI, OpenCode, or Amp the user picks during the prompts. Under the hood every config points at the same npm package (`stacktree-mcp`) over stdio. For Claude.ai's hosted custom connectors, paste `https://api.stacktr.ee/mcp` into the connectors dialog instead — that path uses streamable HTTP with OAuth 2.1 + DCR. ## Privacy model Three independent gating layers, each opt-in per link: 1. **Unguessable URL** (default, every plan). The link contains enough entropy that it's not discoverable by guessing or enumeration. The link itself is the credential. 2. **Shared passcode** (Solo and above). A second factor on top of the unguessable URL. 3. **Email-domain gate** (Solo and above). Magic-link verification against a specific email domain. The gate survives URL forwarding. Layers 2 and 3 are paid. Free pages already carrying one keep working, but a free account cannot add a new one. Additionally: - **End-to-end encryption** (`e2e: true` on upload). AES-GCM in the browser; key in the URL fragment; Stacktree only stores ciphertext. - **CSP defaults**. Sensible Content-Security-Policy on every served page so a careless `