$ integrations
MCP tool reference
The hostdocs MCP server lets Claude or ChatGPT create, update, and publish pages — and build data-driven pages — without leaving the chat.
Connect
The server runs over stdio via npx. Add it to your assistant’s MCP config with an API token from your dashboard:
1{2 "mcpServers": {3 "hostdocs": {4 "command": "npx",5 "args": ["-y", "@hostdocs/mcp"],6 "env": {7 "HOSTDOCS_API_URL": "https://app.hostdocs.io",8 "HOSTDOCS_API_TOKEN": "<your-token>"9 }10 }11 }12}HOSTDOCS_API_URL— the control-plane URL (the dashboard app).HOSTDOCS_API_TOKEN— your personal token, sent as a bearer token on every request.
Workspaces and sites
accountId — omit it to act on your personal workspace, or pass an id from list_workspaces to act on an organization. The site-scoped tools (pages, collections, records) also accept an optional siteId: omit it to use the account’s default site, or pass an id from list_sites to target a specific site (each site is its own subdomain).Page tools
list_workspacesList the workspaces you can publish to — your personal account and any organizations you belong to. Use a returned id as accountId on other tools.
- (none)
list_sitesList a workspace's sites — each is its own subdomain and owns its pages, layouts, collections, and domains. Use a returned id as siteId on the site-scoped tools.
- accountId?
list_pagesList a site's hosted pages (path, status, last updated).
- accountId? — workspace id; omit for personal
- siteId? — omit for the account's default site
get_pageGet a page including its current published HTML — load an existing page to re-render as an editable preview before update_page.
- id — the page id
- accountId?
create_pagePublish a NEW page live at a path on a site's subdomain. Returns the live URL.
- path — e.g. "/landing"
- html — full self-contained document
- title?
- accountId?
- siteId? — omit for the account's default site
update_pageReplace an existing page's HTML, publishing a new live version (prior version kept for rollback).
- id — the page id
- html — new full document
- accountId?
delete_pageDelete a hosted page (takes it offline).
- id — the page id
- accountId?
Collection & record tools
Forms and collections share one typed-record engine; create_collection’s type picks the primary concept — form (public submissions) or collection (authored content, the default). Define a type, populate it with records, then bind a page to render them.
list_collectionsList a site's collections and forms with their fields, slug field, and record counts. Pass type to list only one.
- type? — 'form' or 'collection'; omit to list both
- accountId?
- siteId? — omit for the account's default site
create_collectionCreate a collection or form (a user-defined data type, like a table) on a site. type 'form' makes it submittable; 'collection' (default) is authored content. Returns its id.
- name — e.g. "Products" or "Contact"
- type? — 'collection' (default) or 'form'
- slug? — derived from name when omitted
- accountId?
- siteId? — omit for the account's default site
set_collection_fieldsDefine (or replace) a collection's field schema. Replaces the entire schema, so include every field each time.
- id — the collection id
- fields — the full field list
- accountId?
set_collection_slug_fieldSet which field's value becomes each record's URL slug. Required before binding a detail page. Pass null to clear.
- id — the collection id
- slugField — a field key, or null
- accountId?
create_recordAdd one record (object) to a collection. data is keyed by field key and must satisfy the schema.
- collectionId
- data — field values, e.g. { "name": "Widget", "price": 9 }
- accountId?
- siteId?
list_recordsList a collection's records (cursor-paginated). Optional search over searchable fields.
- collectionId
- search?
- limit? (max 200)
- cursor?
- accountId?
- siteId?
search_recordsSearch a collection's records by a required full-text query over its searchable fields.
- collectionId
- search — the query
- limit? (max 200)
- cursor?
- accountId?
- siteId?
bind_page_to_collectionPublish a data-driven page bound to a collection. routeMode 'list' renders all records at basePath; 'detail' renders one record per slug.
- collectionId
- routeMode — 'list' or 'detail'
- basePath — e.g. "/products"
- html? — template with {{ token }} / {{#each}} placeholders
- templateId? — use a saved template instead of inline html
- title?
- accountId?
- siteId? — omit for the account's default site
Recommended workflow
The server instructs the assistant to preview before it publishes: build the full HTML as an artifact (Claude Artifacts / ChatGPT Canvas), iterate with you there, and only call create_page / update_page once you confirm. Nothing goes live without your go-ahead.
Walkthrough: a data-driven page, end to end
create_collection— define the type, e.g. “Create a Products collection.”set_collection_fields— declare the shape (e.g.name(text, searchable),price(number),features(list of text)).set_collection_slug_field— pick the field whose value becomes each record’s URL (e.g.name), needed for a per-record detail page.create_record— add each product (one call per object).bind_page_to_collection— publish the page. Provide template HTML that uses{{ name }},{{ price }}, and{{#each features}}…{{/each}}, then chooselist(all products at/products) ordetail(each product at/products/<slug>).
<!-- detail template bound to /products -->
<h1>{{ name }}</h1>
<p class="price">{{ price }}</p>
<ul>{{#each features}}<li>{{ this }}</li>{{/each}}</ul>