Your site can let an AI assistant work inside it: read what is there, build pages from the blocks you already have, change the look, and look at the result. By the end of the first section you will have Claude connected to your site and building a page for you.
The connection uses the Model Context Protocol, or MCP, an open standard, so one switch serves any assistant that speaks it. Claude and ChatGPT are covered step by step below, and other MCP apps connect the same way.
You stay in control:
These steps work for Claude Desktop, claude.ai and the Claude mobile apps. Claude Code has its own commands, further down.
site.config.ts and restart the site:export default defineConfig({
// …
mcp: true,
});mcp: true turns on the connection point at /api/mcp and the sign-in that assistants need. A site created with the --mcp option has it on already, along with the screenshots described below.
https:// address. CMS_SITE_URL in .env must be exactly that address. Run it on a server and Behind a proxy show how to put a site on one.Claude connects from Anthropic's addresses, 160.79.104.0/21. They must get through to /api/mcp, /.well-known/* and /api/auth/*, with no sign-in wall in front of those paths. A proxy that asks every visitor to sign in first, such as Pangolin with single sign-on, stops Claude cold. Turn it off for those paths and leave /admin and the rest protected as before.
The address you give Claude is your site's address with /api/mcp on the end:
https://example.com/api/mcpexample.com.The next page asks “Connect Claude to” and your site's name, and lists what Claude wants to do. Tick or untick the permissions. Check that the address under “After you decide, your browser goes back to” is claude.ai (or localhost for Claude Code on your own computer). Then press Allow. Deny turns the request down.
Add an About page under Home with our opening hours, in the same style as the rest of the site.Claude saves what it builds as drafts. Read them in the admin, and publish when you are happy.
Claude Code is Anthropic's command-line assistant. It can sign in with your browser, the same way as the apps:
claude mcp add --transport http my-site https://example.com/api/mcpThen run /mcp inside Claude Code, choose the site and sign in. Because Claude Code runs on your own computer, it can also reach a site you are developing at http://127.0.0.1:4321 or http://localhost:4321.
Or use a token, which needs no browser and also suits a site that cannot do OAuth sign-in (see “Tokens” below). In the admin, open API tokens, make a token, and run the command the admin shows you. It looks like this, with your own token in place of the placeholder:
claude mcp add --transport http my-site https://example.com/api/mcp \
--header "Authorization: Bearer YOUR_TOKEN"ChatGPT adds your site as a custom MCP server. Custom servers need a paid plan (Plus, Pro, Business or Enterprise). On a Business or Enterprise workspace, an administrator may have to allow them first. Do steps 1 and 2 above first, but note that ChatGPT calls from the address ranges OpenAI publishes at https://openai.com/chatgpt-connectors.json, which change from time to time, and not from Anthropic's. OpenAI renames these menus now and then, so if a name below differs, look for the nearest match.
chatgpt.com/plugins; on some accounts it is Settings → Apps), press + and choose Add custom MCP server. If you only see a Developer mode switch, turn it on first (Settings → Apps → Advanced, or Settings → Security)./api/mcp address.Three things differ from Claude:
Any app that connects to remote MCP servers over HTTP (the “streamable HTTP” transport), such as a code editor with an AI assistant built in, can use the site. Give it your /api/mcp address and one of two ways in:
Authorization: Bearer YOUR_TOKEN. Most apps take this in their MCP settings as a header or an “API key”. Tokens work everywhere, including on Cloudflare Workers.| Area | What it can do there |
|---|---|
| Site and pages | Read the page tree, create and edit pages, check them before saving, publish, move and delete drafts, edit menus |
| Blocks | List the blocks the site has and read the settings each one takes |
| Design | Read and change the theme, the site's head and body markup and the layouts, with a history to undo |
| Media | Look through the media library, add pictures from a web address, write alt text |
| Collections | Define collections and add, change and remove their items |
| Catalog and orders | Products, stock, discount codes and orders (only with the shop on) |
| Forms | Read forms and their submissions (only with forms on) |
| Preview and guides | See a draft at desktop and phone width, and read short guides on building well |
The assistant builds from the blocks the site has. It cannot write code or add blocks. It cannot refund or cancel orders unless you give it that permission, and it cannot delete a page that is published. It must unpublish a page first, and only ordinary pages can be deleted this way.
Besides the tools, the site offers four prompts that tell the assistant which tools to use and in what order: build_site (a whole site from a brief), add_page, restyle_site and review_site (a check of every page against the guides, changing nothing). It also offers short guides that the assistant reads before a task: site-planning, composing-sections, theme, navigation-and-hierarchy, collections-and-iterator, forms, images-and-alt-text, accessibility, workflow and errors. Claude shows the prompts in its prompt menu.
Every connection holds a set of permissions, and the assistant is shown only the tools that set allows. Whatever the permissions say, the assistant can never do more than the person who connected it, because each permission also needs a minimum role. The consent page and the New token dialog start from one of two presets, and you can change the ticks:
The permissions, as they are listed in the admin:
| Permission | What it allows | Needs the role |
|---|---|---|
mcp | Connect to this site's MCP endpoint at all. Every connection has it | editor |
content:read | Read pages, posts, menus, the theme, blocks, collections and media | editor |
content:write | Create pages and save drafts, edit menus and globals, change collections | editor |
content:publish | Publish and unpublish pages | editor |
media:write | Upload and edit media | editor |
catalog:read | Read products, categories and discounts | editor |
catalog:write | Edit products, discounts and stock | editor |
forms:read | Read forms and submissions | admin |
orders:read | Read orders, baskets and the dashboard | admin |
orders:write | Change, cancel and refund orders. No preset includes it | admin |
settings:read | Read the shop and site settings | admin |
site:design | Change the theme, the layouts and the head markup, and restore earlier versions | admin |
The design permission can change every page at once, so only administrators can give it. A permission that belongs to a feature is only offered on a site that has the feature.
By default only administrators can connect an assistant or make a token. On the API tokens screen, under Connected apps, the switch “Editors may connect AI apps” lets editors connect too. An editor's connection is still limited to what an editor can do.
Under Connected apps, each assistant that someone has allowed to act as them is listed: the person, the app's name, its permissions, and when it was first and last used. Revoke signs it out straight away, and it has to ask again. Both ways in check the person's role on every request, so demoting them, or revoking the connection, stops the next request.
A token is the other way in, for scripts, Claude Code and any app that can send a header. In the admin, open API tokens and choose New token. Give it a Name, pick a preset to start from, adjust the permissions, and choose how long it lasts: Never, 30, 90 or 365 days. The token is shown once, so copy it then. If you lose it, revoke it and make another. A token acts as the person who made it, within their role.
Tokens start with wnk_. With sign-in, a connection lasts until you revoke it. With a token, it lasts until it expires or you revoke it.
Settings → Site has a box called “Notes for AI assistants”. Use it for your site's own rules: your tone of voice, British or American spelling, pages to leave alone, words to avoid. It holds up to 4,000 characters of plain text. The assistant reads it each time it connects, after the cms's own instructions.
Only administrators can edit it, and only in the admin. No assistant has a tool that changes it, so a conversation can never rewrite the standing rules for the next one. It is kept with the rest of the site's settings.
Every change to the theme and to the site's markup is kept in a history. Open Settings → Theme or Settings → Site and look at History, where each earlier version has a Restore button. Page changes are kept as revisions in the page editor.
Claude builds better when it can see the result. With a browser service, the preview tool gives Claude pictures of a page at desktop width (1280 px) and phone width (390 px), cut into tiles it can read. Without one it still gets a signed link to the draft, which works for 15 minutes, and a text outline of the page's blocks.
The browser is the official Playwright container, running a Playwright server. The site connects to it at CMS_SCREENSHOT_WS, and the site's own image never contains a browser. Claude cannot ask it to open any address: it only opens the preview link that your site signs for one page. It uses about 1 GB of disk for the image and a few hundred MB of memory while it takes pictures, and it is idle the rest of the time.
A site created with --mcp has all of it set up:
npm create @jamiemcconnell/cms-app@latest my-site -- --mcpTo add screenshots to a site you already have, follow these steps.
pnpm add @jamiemcconnell/cms-screenshot playwright-core@1.63.0site.config.ts, use the object form of mcp. Replace 4321 with your site's port:import { playwright } from '@jamiemcconnell/cms-screenshot';
export default defineConfig({
// …
mcp: {
oauth: true, // the default
screenshots: playwright({ baseUrl: 'http://app:4321' }),
},
});compose.yaml, under services. A site made with the create command already has it at the end of the file, with a # at the start of each line: replace each # with a space. The service publishes no port, so only the site can reach it: browser:
image: mcr.microsoft.com/playwright:v1.63.0-noble
command: npx -y playwright@1.63.0 run-server --port 3000 --host 0.0.0.0
expose:
- '3000'
init: true
mem_limit: 1g
restart: unless-stoppedCMS_SCREENSHOT_WS=ws://browser:3000/docker compose up -d --buildKeep the image tag, the playwright@ version and the playwright-core package at the same version. A server of another version is refused. To remove screenshots, delete the browser service and the screenshots line, then run docker compose up -d --build --remove-orphans. Previews go back to a link and an outline.
The page Claude or ChatGPT sends you to is the site's own sign-in, so any provider you have set up, such as Google or Pocket ID, is offered there (Accounts and sign-in). Only existing accounts can connect, with one exception: with an OpenID provider set to decide staff roles, a person in the admin group is created on their first sign-in and can connect straight away. A site whose provider is set to take admins straight there (autoRedirect.oauth) makes connecting either assistant a passkey tap and the consent page. A connection also ends when the provider's staff session length runs out.
mcp: false, or leaving mcp out, switches the connection point off. mcp: { oauth: false } keeps it but accepts tokens only, which is also all that a site on Cloudflare Workers can do, because OAuth sign-in runs on the Node server. With sign-in on, CMS_SITE_URL must be an https:// address, or http://localhost or http://127.0.0.1 for development. Any other plain-http address stops the site starting, with a message that says to use https or to set oauth: false.
/api/mcp, /.well-known/* and /api/auth/*. ChatGPT says the same in its own words, such as “Error creating connector” or “unable to reach the server”. Check from outside your network, using the commands below.CMS_SITE_URL must be exactly the address you gave the assistant: the same https, the same host and no extra path. Fix it, restart the site, remove the connector (or the ChatGPT server) and add it again. For a token, a 401 also means it was revoked, has expired or belongs to someone who is no longer an administrator./.well-known/oauth-authorization-server. If it still asks, check that this address opens from outside your network and names your CMS_SITE_URL.CMS_SCREENSHOT_WS is set in .env and the site was restarted, that the browser container is running (docker compose ps), that the three versions match (a mismatch is reported as SCREENSHOT_FAILED with reason: version_mismatch), and that mcp.screenshots is in site.config.ts at all.To check the connection yourself from outside your network, run these two commands, with your own domain in place of example.com:
curl -i -X POST https://example.com/api/mcp \
-H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"ping"}'
curl -s https://example.com/.well-known/oauth-protected-resourceThe first should answer 401 with a www-authenticate header that names /.well-known/oauth-protected-resource. The second should answer JSON whose resource is your /api/mcp address. A sign-in page, a 403 or a timeout means something in front of the site is blocking the assistant. A 404 on the second means mcp is off, or oauth is false. Troubleshooting covers problems that are not about assistants.