AI assistants (MCP)
Bailey ships a built-in MCP (Model Context Protocol) server. An AI assistant connects to it once over OAuth and can then drive a user’s sites: create them, publish pages, read submissions, manage domains. Everything is scoped to the authenticated user: strict A≠B isolation, same as the rest of the platform.
If you just want to connect Claude or ChatGPT, the Connect your AI assistant guide is all you need. This page is the reference.
Endpoint
Section titled “Endpoint”https://app.trybailey.app/mcpJSON-RPC 2.0 over HTTP POST. The server advertises itself as bailey, protocol version 2025-06-18, and supports the initialize, tools/list, tools/call, prompts/list, prompts/get, resources/list and resources/read methods.
Authentication
Section titled “Authentication”The MCP endpoint is protected; an unauthenticated request gets 401 with a WWW-Authenticate: Bearer challenge pointing at the OAuth metadata. Bailey is the OAuth 2.1 authorization server, but it delegates the actual login to your Bailey identity (Supabase Auth). The access_token the client ends up with is your Bailey JWT, the same one the dashboard uses. There is no separate key to issue or paste.
The discovery flow is fully automatic for any compliant MCP client:
Client → POST /mcp → 401 + WWW-Authenticate (resource_metadata) → GET /.well-known/oauth-protected-resource → authorization server = Bailey → GET /.well-known/oauth-authorization-server → endpoints + capabilities → POST /oauth/register → client_id (Dynamic Client Registration) → GET /oauth/authorize (PKCE S256) → Bailey login + consent → POST /oauth/token (code + verifier) → access_token (your Bailey JWT)Security properties: PKCE S256 is mandatory, authorization codes are single-use with a 60-second TTL, redirect_uri is validated against the registered client (anti open-redirect), and the only scope is mcp. See the Security model.
All tools are bounded to the sites you own, by construction. Returns are actionable JSON (names, live https://… addresses, counts, the exact CNAME to set), never bare internal IDs.
Orient & guides (served live; call before generating)
Section titled “Orient & guides (served live; call before generating)”| Tool | What it does | Key params |
|---|---|---|
bootstrap | Call FIRST on any Bailey task. Returns the up-to-date playbook (sequencing, the three primitives, the data-governance reflex) and checks the installed skill’s freshness. | skill_version? |
get_starting_prompt | The on-brand starting method for a common job, resolved for the caller’s organization. This is the tool twin of the MCP prompts/get primitive (which hosts expose only to the user’s UI). | name (landing-page | product-page | dashboard | report | event-feedback), org?, scope? |
get_brand_tokens | The resolved brand for a project: design tokens + written guidance, cascaded platform → organization → project. Call before writing any UI/CSS. | project, org? |
get_integration_guide | The complete SDK guide: primitives, no-code form auto-binding, public reads, analytics, and the data-declaration (manifest) format. | – |
| Tool | What it does | Key params |
|---|---|---|
list_sites | Your sites, each with live address, online/offline status, and submission count. | – |
get_site | Full status of one site: address, status, data collections + counts (the data contract), metrics, custom domain, the stored brief/tags, recent activity, plus current setup suggestions. | site |
read_submissions | Entries a site collected (e.g. form sign-ups), newest first, with timestamps. Owner-only. | site, collection?, limit?, offset? |
list_metrics | A site’s counters (votes, views, clicks…) with their current values. | site |
read_analytics | Traffic analytics: pageviews over time, top pages, referrers, campaigns, tagged events. Cookieless, owner-only, plan-gated (free plan gets an upgrade note, not figures). | site, days? |
check_address | Whether a subdomain is free and the address it would get; returns alternatives if taken. | subdomain |
| Tool | What it does | Key params |
|---|---|---|
create_site | Create a site at a chosen subdomain, optionally publishing a page right away. | name, subdomain, title, html?, description?, brief?, tags?, manifest? |
publish_page | Replace a site’s live page with a new single self-contained HTML document. | site, html, title, description?, brief?, tags?, manifest? |
set_brand_tokens | Write the brand, the counterpart of get_brand_tokens. Apply a brand the user gives you (a design.md, colors, fonts, a voice) so every future page inherits it. Merges into the existing brand (patch: send only what changes); owner/admin for the organization charter, or project to style one site. | tokens?, guidance?, locked?, project?, org? |
verify_collection | End-to-end check that a form’s collection is wired: writes a test entry through the real path, confirms it landed, removes it (never visible in reads or counts). | site, collection? |
take_offline / bring_online | Unpublish a site / bring it back online. | site |
rename_site | Change the display name (not the address). | site, name |
change_address | Change the subdomain; returns the new live address (or alternatives if taken). | site, subdomain |
connect_domain | Point a custom domain at a site; returns the exact CNAME record to create. | site, domain |
check_domain | Re-check a connected domain’s DNS and mark it verified/live if it now points correctly. | domain |
dismiss_suggestion | Decline a setup suggestion for a site; it won’t be proposed again while the page’s intent is unchanged. Never bypasses governance. | site, suggestion |
site accepts either the display name or the address/subdomain. Quotas (e.g. the free-plan project limit) and reserved/system labels are enforced server-side, so a tool call can legitimately fail with a clear reason.
Intent, versions & suggestions
Section titled “Intent, versions & suggestions”titleis required oncreate_site/publish_page: a few words naming what this version is (“Add contact form”); it labels the version log the user sees in the dashboard.descriptionoptionally adds a decision note;briefpersists the project’s intent (audience, goal, open items) so a later session re-hydrates it fromget_siteinstead of re-reading a chat.tagsdeclare what kind of page it is (landing,waitlist,contact,event,booking,link-in-bio,product,blog,portfolio,docs; a closed taxonomy). They drive setup suggestions and nothing else: no security or access depends on them.- Setup suggestions:
create_site,publish_pageandget_sitemay return asuggestionslist: things this kind of page usually has but this one doesn’t yet (a lead-catcher on a landing, a click counter on a links page). Each carries a stableid, a plain-wordsmessage, theprimitiveto wire, adoctutorial link and often a ready-made bucketfragment(structure only; the GDPR answers are deliberately left blank for the user to give). Present the top one as a choice; decline withdismiss_suggestion. - Previews:
create_site,publish_pageandget_sitealso attach a screenshot of the live page (inline image + a signed public URL) so the user sees the result in the chat.
Prompts & resources
Section titled “Prompts & resources”Beyond tools, the server exposes two more MCP primitives so generated pages come out on-brand instead of being corrected after the fact:
- Prompts:
landing-page,product-page,dashboard,report,event-feedback. Each resolves to your organization’s version if it has one, otherwise the platform default. The guidance (the why, the do’s and don’ts) travels with the prompt. Passorg/scopewhen you belong to more than one organization. - Resources:
bailey://charter: your organization’s brand (design tokens and guidance, with locked keys enforced). Add?org=<slug>if you’re a member of several orgs.bailey://sdk: the persistence / data-collection SDK guide (key-value, counters, collection via the in-page store) and the data-declaration format. Read it before publishing a page that stores or collects anything.
Publishing rule: one self-contained HTML file
Section titled “Publishing rule: one self-contained HTML file”create_site and publish_page take a single self-contained HTML document (CSS/JS inline, up to ~1 MB) and publish it directly. That’s the zero-friction path: the assistant generates an index.html, you publish.
Anything bigger (multiple files, binary assets, heavy images) goes out of band via the dashboard’s drag-and-drop (Upload a folder) or, for advanced setups, the bailey CLI. A site is never streamed as base64 through a tool argument. The MCP serves the verb and the norm, not bulk binary.
Data collection: declared at publish time
Section titled “Data collection: declared at publish time”If a page stores data or collects submissions (via the in-page SDK), the assistant declares its buckets by passing a manifest argument (the bailey.manifest.json shape) to create_site / publish_page. This is reconciled on every publish: buckets are created or updated, never silently deleted.
The governing rule: personal data without a stated purpose is refused, and the publish fails. Key-value and counter buckets work without declaration; an undeclared collect bucket returns 403 at runtime. The exact format lives in the bailey://sdk resource and in Data & privacy.