---
name: unfolder-space
description: Build, edit, and publish a website on unfolder.space — a "space" that goes live on its own isolated Cloudflare Worker at {slug}.unfolder.space. Use when creating or editing an unfolder.space space, or when connected to the unfolder.space MCP server. All file, build, and publish work goes through the MCP server's run_code tool; binary uploads go out-of-band via get_urls.
---

# unfolder.space

unfolder.space is agent-native: you author files, build, and publish a website
entirely through one MCP server — there is no separate CLI or web build step, no
git, and no branches. One space = one site, served at `{slug}.unfolder.space`.

## Connect

The MCP endpoint is `https://unfolder.space/mcp` (Streamable HTTP, OAuth 2.1).
Register once, then:

1. `whoami` — confirm identity and which spaces you can edit.
2. `create_space({ name, subdomain })` — or use an existing space's `slug`.
3. `get_urls({ slug })` — the live site, dashboard, settings, upload page, and a
   session upload URL.

The server's instructions are the `intro` doc; read `unfolder://docs/intro` first.

## Author and publish

All file/build/publish work happens inside `run_code({ slug, code })`, where
`code` is an async arrow function with these namespaces in scope:

- `state.*` — files (`readFile`, `writeFile`, `glob`, `searchText`, …)
- `host.*` — build & publish (`build` validates; `publish` goes live)
- `config.*` — asset config, variables, secrets, egress
- `media.*` — durable uploaded/static assets
- `introspect.*` — probe the live site: `query` (read its SQLite, read-only)

The working tree is the source. Write files, then publish in one call:

```ts
async () => {
  await state.writeFile("/index.html", "<h1>hello</h1>");
  return host.publish(); // goes live at https://{slug}.unfolder.space
};
```

`host.build()` bundles the working tree as a dry-run (validate, no go-live);
`host.publish()` builds and swaps the single live facet, returning the live
`url`. Edits aren't live until you publish.

For plain-text drops with no logic, use `write_files({ slug, files })`. Never
base64 binary (images/video/fonts) through the model — call `get_urls({ slug })`
and PUT the bytes to the returned session upload URL.

## Go deeper

- Docs (read on demand): `unfolder://docs/{topic}` — `workflow`, `run-code`,
  `bundling`, `dynamic-worker`, `media`, `multi-space`, `seo`, `secrets`,
  `custom-domain`, `admin-prep`.
- Patterns (MCP prompts, pick at chat start): `unfolder.routing` (dynamic site —
  Hono + DO), `unfolder.static-site` (files-only content site + Your Terms), and
  `unfolder.auth-basic` / `unfolder.auth-sessions` / `unfolder.auth-accounts`
  (gate by identity — one opinionated pattern each).
