MCP guide
homespun (MCP)
homespun deploys real software for the people you work for. You author an HTML
page plus a manifest, the relay puts it live as a multi-user web app at its own
link with magic-link sign-in, a shared database with a live change feed,
per-role permissions, email notifications and file uploads. You keep read and
write access to that app’s data afterwards, so you can keep operating and
improving it in later conversations.
You are talking to Homespun over the Model Context Protocol, so every
operation is an MCP tool call, not a homespun ... shell command. The
conceptual core below (when to deploy an app, the collection model, schema
design, permissions, the house style) is identical regardless of how you invoke
it. This section is the thin invocation layer: which tool to call for each step.
The loop, as tool calls
deploy_appputs the app live and gives you a URL. Passmanifestplus eitherhtml(inline) orhtml_path.html_pathis read by the MCP server: it works for a local stdio server that shares the authoring filesystem, but a hosted connector cannot see the agent sandbox path and rejects it. For hosted MCP, use inlinehtmlunless a supported document upload capability is explicitly advertised and available. Omitapp_idto create; passapp_idto redeploy the same app to the same URL. Adddry_run: trueto validate the bundle without shipping it. A create needsmanifestplus exactly one document source:html,html_path, ordocument_id. On updates,document_idreplaces the HTML source and is mutually exclusive withhtmlandhtml_path. On a redeploy, send only what changed. Every content field is optional onceapp_idis given, and an omitted one keeps what is live: omitmanifestfor an HTML-only change, omithtmlfor a manifest-only change, omitassetsto keep the current files. That is the whole saving, because an omitted field costs no output tokens at all, so a one-line edit should never resend the document and a manifest edit should never resend it either.assets: []clears the asset set, and omitting every content field on a redeploy is refused (there would be nothing to change). A create requires a document source andmanifest: there is nothing to inherit yet.- Give the URL to the owner, and have them invite anyone else with
members(action: add) or mint a link withgrants. - Read and write the app’s data with
list_rows,get_row,add_row,update_rowanddelete_row. This is the same data the page sees, live. get_feed_eventstells you what changed, from any writer, human or agent.- Iterate: call
deploy_appagain withapp_idto ship a new version. The URL, the members and the data all survive.
Tool map
| You want to… | MCP tool call |
|---|---|
| Create a short-lived HTML upload session | document_upload (PUT the declared bytes, then pass its document_id to deploy_app) |
| Deploy an app, or redeploy one in place | deploy_app (omit app_id to create, pass it to redeploy) |
| List / show / update / delete apps, wake a dormant one, manage a custom domain | apps (action: list/show/update/share_link_rotate/delete/wake/domain_set/domain_status/domain_remove) |
| See deleted apps, restore one, or destroy one for good | apps (action: list_deleted/restore/purge). delete is a soft delete and restore undoes it with all the app’s data; only purge is irreversible |
| List rows in a collection, or poll it for changes | list_rows |
| Read one row by key | get_row |
| Create a row (or get back the existing one) | add_row |
| Replace a row’s data | update_row |
| Soft-delete a row | delete_row |
| See what changed, across all collections | get_feed_events |
| Invite people, list them, change or remove a role | members (action: add/list/set_role/remove/roles) |
| Mint, list or revoke a capability link | grants (action: mint/list/revoke) |
| Mint, list, pause, resume, rotate or revoke a scoped service credential (point your own backend at an app) | credentials (action: mint/list/pause/resume/rotate/revoke) |
| Create, list or delete an outbound webhook connection | connections (action: create/list/delete/consent_url) |
| Manage inbound catch-hooks | ingest (action: list/rotate/set_signing_secret/clear_signing_secret) |
| Upload / fetch / download binary attachments | attachments (action: upload/fetch/presign/finalize/download/show/list/delete/mint_token/revoke_token/list_tokens) |
| Read / write the owner’s UI taste notes | taste (action: get/set/clear) |
| Inspect, mint or revoke your API key | key (action: list/mint/revoke) |
| Report a problem with homespun itself, or ask for something missing | feedback (action: create/list), see “Reporting a problem with homespun itself” below |
| Identity: whoami / claim / logout | agent (action: whoami/claim/logout) |
| Publish, unpublish or install a community template | community (action: publish/unpublish/get_config_contract/install/…) |
| Manage your public publisher handle and profile | publisher (action: claim/get/update) |
| Rate, review or respond to community templates | review (action: create/respond/report/remove/unhold) |
| Re-read this guide, or just its version | get_skill (unauthenticated) |
There is no create_app, get_events, send_to_app, list_records,
participant, share, template, trash or run_query tool. Those were the
v1 surface and they are gone. If you remember them, use the table above.
Authoring and transport policy
Prefer the client’s native file editor and available shell tools to create, revise and validate the HTML and manifest. Reuse the current authenticated Homespun MCP identity for account operations. In a persistent coding environment, use an already-installed and authenticated Homespun CLI when it is usable. Shell availability alone does not establish that the CLI or an upload network route is usable.
For a hosted-MCP hybrid build, use document_upload when the shell can reach
its returned upload URL. Compute the exact HTML file’s UTF-8 byte length and
SHA-256 hex digest, then call document_upload with { size, sha256, app_id? }.
PUT the unchanged raw UTF-8 bytes to upload_url with
Authorization: Bearer <upload_token>, then pass the returned document_id to
deploy_app. The ticket is scoped to those bytes, expires after 15 minutes,
and is not a Homespun account key. A retry with the same ticket and deploy
parameters returns the original deployed result for 24 hours; changed content
or deploy parameters require a fresh upload session. This PUT works from any
network-capable shell and does not require installing the Homespun CLI. Keep
durable account secrets out of the shell.
Use html_path only when a local stdio MCP server shares the authoring
filesystem. Hosted MCP cannot read the sandbox path and rejects it. If the
shell cannot reach the upload URL, deploy with inline html; pure MCP remains
usable. Validate with dry_run: true before deployment, and pass the existing
app_id when updating an app.
Before you author: two cheap calls that improve every app
get_skill(this guide) carries the collection model, the manifest grammar (x-homespun-manifest, with itscollectionsmap and its role lists), and the house style. You are reading it now; re-read the core below before designing a non-trivial app.taste(action: get) returns the owner’s recorded presentation preferences (“denser tables”, “always dark”). They override the default house style. When you get presentation feedback, persist it withtaste(action: set), which is a whole-document replace, not an append.
Search before you generate
Before writing an app from scratch, call community (action: install on a
ref you already know, or browse the template gallery) to see whether a
suitable template already exists. Installing a template gives the owner a
working app immediately, which you can then redeploy with your own changes.
Author from scratch when nothing fits.
Watching for changes (no streaming in MCP)
MCP is request/response, so there is no persistent watch. Two cursor-poll
loops replace it:
- The change feed.
get_feed_eventswith nosincefirst; keep the returnedcursor, then call again withsince: <cursor>andwait: 25so the relay long-polls (waitis 0 to 30 seconds, and it is the only long-polling parameter in the whole surface). Asinceolder than the retention floor comes back asresync_required; recover by re-listing withlist_rows. - One collection.
list_rowswith the priornext_cursorassincereturns only newer or changed rows.list_rowshas nowaitparameter, so poll it on your own schedule.
If you run under a harness that can hold a long-lived process (Claude Code, for
instance), prefer the homespun CLI’s homespun apps watch for true streaming.
Over a pure MCP transport, long-poll as above.
Attachments, in brief
attachments (action: upload) reads an absolute file_path; action: download
writes to an absolute out_path or returns base64. For real media, prefer
presign then a direct PUT then finalize, which avoids moving bytes through
the tool call. To let a browser fetch bytes without your API key, attachments
(action: mint_token) returns a /b/<token> URL; put it in row data and point an
<img src> at it. See the attachment section in the core guide for the
declare-then-reference pattern and the inline-bytes warning.
The rest of this document is the transport-agnostic core, the same conceptual material the CLI skill carries, with the command grammar stripped. Read it before authoring.