Skip to main content
Shareable ships an MCP server so your agent can publish and manage pages directly from your terminal or code editor.
Just want your Claude, ChatGPT, or Gemini app to publish for you — no terminal? See Publish from Claude, ChatGPT & Gemini. This page is the developer setup (Claude Code, Cursor, scripts) plus the full tool reference.

Get your API key

In Shareable, open Settings → Developers and create a key — it starts with sm_. Use it as a bearer token (hosted server) or the SHAREABLE_API_KEY env var (local server). The hosted server lives at one URL:

Hosted server (URL)

Nothing to install — add it as a remote (HTTP) server with the URL and your API key as a bearer token:

Local server (npx)

Works in Claude Desktop, Claude Code, and Cursor. Add to your client’s MCP config:
~/.claude/mcp.json
SHAREABLE_API_URL is optional and defaults to the hosted Shareable. Restart your MCP client after editing the config so it loads the server.

Tools

html | html_base64 | html_url | html_path, sha256?, title?, access?, allowed_emails?, password?
Publish a self-contained HTML page and get a shareable URL. Goes live immediately. With access: "password", pass a password (or one is generated and returned).Provide the HTML one of these ways: inline html, html_base64 (base64 — ASCII, so it can’t be mangled by the token stream; use it to avoid emoji/Unicode corruption), or html_url (a public https URL the server fetches the bytes from, SSRF-guarded — best for large HTML, so it never passes through the token stream). The local npx server also takes html_path — a file it reads from disk, so an agent can write the HTML to a file and never emit it as tokens. Optionally pass sha256 (hex of the HTML bytes) for a byte-perfect integrity check.
files, assets?, entry?, title?, access?, allowed_emails?, password?
Publish a multi-page deck — several HTML files that link to each other (investor deck, docs site, sectioned report, clickable prototype) — under one shareable URL. files is an array of { path, html }; link between pages with relative (team.html) or root-relative (/team.html) paths. Images, CSS, JS, and fonts the pages reference go in assets — { path, file_path } to read a local file, or { path, data_base64 } — no need to inline them. entry picks the landing page (defaults to index.html).
file_base64 | file_url | path?, filename?, mime?, title?, access?, allowed_emails?, password?
Publish a PDF or image (PNG/JPG/WebP/GIF), shown inline — same access control + analytics as any page. Both servers take file_base64 (≤ ~3 MB — the request-body limit) or a public file_url (up to your plan’s per-file cap: Free 5 MB, Pro 50 MB; internal/private hosts are blocked); the local npx server also takes a local path it reads from disk (same ~3 MB ceiling, since it sends the bytes inline). For anything larger than ~3 MB, host the file at a public URL and pass file_url. SVG, Office docs, and spreadsheets aren’t supported — export to PDF first.
id, full?
Read back a page’s current HTML so you can make a small, surgical edit instead of rebuilding it from scratch — html for a single page, or every file’s HTML for a deck. Returns the editable working copy (matches what’s live unless there are unpublished changes). Long inlined images and fonts (data: URIs) come back as short ELIDED-BY-SHAREABLE placeholders by default so they don’t flood the model’s context — an agent never needs those bytes to edit the text around them, and the stored page keeps them. Pass full: true for the raw HTML (only needed before a whole-page update_page; elided HTML is rejected there). Typical flow: get_page_html → edit_page with just the snippets that change → publish_changes.
id, edits, path?, publish?
Change part of a page without resending the whole document. edits is an ordered list of { find, replace, replace_all? }; the server applies them to the page’s current draft and every byte you didn’t name stays exactly as it was — so inlined images and fonts (which an AI can’t reliably retype) never pass through the model. This is the right tool for “update the numbers on my dashboard”, new copy, or swapping a section.Each find is plain text (no regex) and must match exactly once — copy it verbatim from get_page_html, whitespace included — or set replace_all: true. Edits are all-or-nothing: a missing or ambiguous find rejects the batch and the error names which one. Saved as a draft; pass publish: true to go live in the same call. For a deck, path picks the file (defaults to the entry page). The result echoes each edit’s before → after (each side capped at 200 characters and flagged when cut) and the version numbers on either side of the change, so restore_version of the previous one is an exact undo (with publish: true if the edit went live). If the page changed under you between reading and editing, the edit is refused rather than clobbering it — read again and retry.
id, html? | html_base64? | html_url? | html_path?, sha256?, title?, access?, allowed_emails?, password?
Replace a single page’s whole HTML as a draft, and/or change its settings. Call publish_changes to push it live. New HTML can be inline html, html_base64, html_url, or (local npx server) html_path — the same byte-faithful / token-light options as publish_page — with an optional sha256 integrity check. If you’re only changing part of an existing page, use edit_page instead.
id, files, entry?
Replace a deck’s files as a draft. Pass the full set of { path, html } — files not included are removed. Call publish_changes to push it live.
id
Publish a page or deck’s current draft, updating the live URL.
id
Take a page offline — its shared link stops working until you publish again.
limit?, offset?
List the pages in your account (drafts and published), most recently edited first. limit (default 100, max 200) and offset page through a large account so an entire account isn’t dumped into the model context.
id
List a page or deck’s saved versions (one is saved on each publish and each edit), newest first.
id, version, full?
Read a specific version’s metadata and content (html for a page, files[] for a deck). Large content is truncated to a preview by default — pass full: true to return the entire untruncated content (e.g. to patch or diff an old version). To read the current page’s HTML, use get_page_html.
id, version, publish?
Restore a previous version into the draft. Pass publish: true to also push it live.
id
Permanently delete a page.

Example

Once connected, just ask in natural language:
Your agent calls publish_page with access: "people" and the two emails, then hands back the live link.