Skip to content

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.

https://app.trybailey.app/mcp

JSON-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.

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)”
ToolWhat it doesKey params
bootstrapCall 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_promptThe 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_tokensThe resolved brand for a project: design tokens + written guidance, cascaded platform → organization → project. Call before writing any UI/CSS.project, org?
get_integration_guideThe complete SDK guide: primitives, no-code form auto-binding, public reads, analytics, and the data-declaration (manifest) format.
ToolWhat it doesKey params
list_sitesYour sites, each with live address, online/offline status, and submission count.
get_siteFull 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_submissionsEntries a site collected (e.g. form sign-ups), newest first, with timestamps. Owner-only.site, collection?, limit?, offset?
list_metricsA site’s counters (votes, views, clicks…) with their current values.site
read_analyticsTraffic 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_addressWhether a subdomain is free and the address it would get; returns alternatives if taken.subdomain
ToolWhat it doesKey params
create_siteCreate a site at a chosen subdomain, optionally publishing a page right away.name, subdomain, title, html?, description?, brief?, tags?, manifest?
publish_pageReplace a site’s live page with a new single self-contained HTML document.site, html, title, description?, brief?, tags?, manifest?
set_brand_tokensWrite 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_collectionEnd-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_onlineUnpublish a site / bring it back online.site
rename_siteChange the display name (not the address).site, name
change_addressChange the subdomain; returns the new live address (or alternatives if taken).site, subdomain
connect_domainPoint a custom domain at a site; returns the exact CNAME record to create.site, domain
check_domainRe-check a connected domain’s DNS and mark it verified/live if it now points correctly.domain
dismiss_suggestionDecline 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.

  • title is required on create_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. description optionally adds a decision note; brief persists the project’s intent (audience, goal, open items) so a later session re-hydrates it from get_site instead of re-reading a chat.
  • tags declare 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_page and get_site may return a suggestions list: 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 stable id, a plain-words message, the primitive to wire, a doc tutorial link and often a ready-made bucket fragment (structure only; the GDPR answers are deliberately left blank for the user to give). Present the top one as a choice; decline with dismiss_suggestion.
  • Previews: create_site, publish_page and get_site also attach a screenshot of the live page (inline image + a signed public URL) so the user sees the result in the chat.

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. Pass org / scope when 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.

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.


Hosted on Bailey