Building with an AI editor
sitepack mcp turns the site you are developing into a live workspace for an AI editor. While sitepack theme:watch is syncing your theme, the MCP server lets an agent fill in the design you are building: create pages, put them in a menu, and manage the online store's categories and products, then check that what it built actually renders.
It speaks the Model Context Protocol, so any MCP client (Claude Code, Cursor, and others) can drive it.
How it works
sitepack theme:watch already knows which site you are building on: it asks you to pick one when it starts. On top of that it now requests a token from SitePack that is scoped to that one site, and stores it locally. sitepack mcp reads that token and serves it to your editor.
The two commands run side by side: the watch keeps your theme in sync in one terminal, and your editor starts the MCP server on its own. Nothing listens on a network port; the server talks to the editor over standard input and output, and the token never leaves your machine.
The token is bound to the single site you picked and lasts a working day (8 hours). Start theme:watch again to refresh it.
Setup
- Steps
-
Log in, if you have not already:
sitepack login -
In your theme directory, start the watch and pick the site to build on:
sitepack theme:watch -
Point your editor at the MCP server. For Claude Code:
claude mcp add sitepack -- sitepack mcpAny MCP client works; the command to run is
sitepack mcp, with the theme directory as its working directory.
If you started your editor somewhere other than the theme directory, sitepack mcp falls back to the most recent watch session. When several watches are running, pass --theme <uuid> to choose one.
Staging by default, live on request
Pages the agent creates default to staging: they are served only by staging-<your-domain> and are invisible to visitors, which is the safe way to build on a site that already has traffic. The agent can publish a page when you ask it to; that is a choice made per page, so nothing goes live by accident. A menu entry that points at a staging page stays hidden on the live site until that page is published.
The online store has no staging: categories and products the agent creates are written to the live shop straight away, so only ask it to create ones that are meant to be seen.
What the agent can do
The MCP server exposes a focused set of tools:
| Area | Tools |
|---|---|
| Context | site_context |
| Company profile | get_company_profile, update_company_profile |
| Social media | get_social_media, update_social_media |
| Pages | list_pages, get_page, create_page, update_page, set_page_elements, check_slug, delete_page |
| Blog | list_blogs, get_blog, create_blog, update_blog, set_blog_elements, set_blog_status, delete_blog |
| Navigation | list_navigation, add_navigation_item, update_navigation_item, remove_navigation_item |
| Categories | list_categories, get_category, create_category, update_category, delete_category |
| Products | list_products, get_product, create_product, update_product, delete_product |
| Translations | list_locales, get_content_translation, set_content_translation, delete_content_translation, translation_coverage, translation_review_queue |
| Media and checks | list_media, check_page_render |
update_company_profile changes only the fields it is sent, so an agent can fill the profile in a few answers at a time; an unknown field or organisation type comes back as an error instead of being dropped. It needs sites:write. The languages and payment methods are not part of the profile: SitePack derives them from the site (see get_company_profile → automatic).
update_social_media links or unlinks the site's social media profiles (facebook, twitter, instagram, youtube, pinterest, tiktok, linkedin): send only the networks to change, and null or an empty string unlinks one. Each URL must be on its network's own domain (get_social_media lists them per network); a wrong one comes back as an error and nothing is changed. The profiles show in the social media element and in the sameAs of the site's Organization JSON-LD. It needs sites:write.
site_context is the one to call first: it reports which site the session points at, the staging URL, and the scopes the session holds. After building a page, check_page_render fetches it over HTTP and reports any Twig or PHP error in the response, because a page the API accepted is not always a page that renders.
A blog post is a separate resource from a page: it feeds the site's blog (its overview and detail pages), not the page tree, and it lives in its own collection. Build one with the blog tools, not create_page with a "blog" type. A blog post uses the very same page-builder element tree as a page, so the get_element_reference catalogue applies unchanged. New posts default to draft (a concept); set_blog_status publishes them. The blog tools need the blogs:read / blogs:write scopes.
The translation tools drive the per-locale overlay: translation_review_queue (or translation_coverage) shows what still needs work in a locale, get_content_translation returns each translatable string keyed by a path with its source text, and set_content_translation saves a values map of those same paths to the translated strings. They cover every translatable content kind: page, blog, product, category, usp, event, the site-wide topbar and footer, legal policy pages (terms, privacy, …) and post for the content of app post types. A legal policy has a single translatable string, its body under field#description; get its uuid from translation_review_queue with type: legal.
Type post covers both an entry of an app post type (a case, a cinema) and a post type's overview page. For an entry, take the uuid from list_post_entries; for an overview page, take it from translation_review_queue with type: post, which lists every entry plus each overview page that has SEO texts. Its title, SEO title and description, and its text and textarea fields translate; numbers, images, dates and the other field types are the same in every language. The public REST endpoints under /api/public/v1/translations/{type}/{uuid}/{locale} and /api/public/v1/translations/review/{locale}?type=post accept post the same way.