Flows MCP
Connect the AI you already use — Claude, ChatGPT, Grok, Cursor, or any MCP client — and let it design, preview and publish custom components on your Flows site. One URL, one approval, and your model is part of the team.
01What is Flows MCP
Flows exposes your site to AI models over the Model Context Protocol — an open standard that lets an AI tool call real, permissioned functions. Once connected, the model you already work in can read your brand context, see what your site looks like, and change three things on your Flows site:
- Article components — hero banners, tables of contents, TL;DRs, takeaways, FAQs, sources and related-article blocks, plus your site header, site footer, the whole listing page and the product card every store slider uses.
- Your reader chat — a CSS-only reskin of the concierge chat, covering every region from the welcome pane to the checkout drawer. See Chat skins.
- Your data tables — the tables in Projects → Databases: create them, shape their columns, read and write rows, and choose which ones your site chat may read. See Data tables.
You describe what you want in plain language, in the tool you already work in. Flows handles rendering, sanitising, and serving the result on your real articles — crawlable and fast. Nothing a model designs goes live on your pages without your click; see Going live.
02Requirements
- A Flows account with at least one connected site (connect one in the dashboard first).
- An MCP-capable client — Claude, Claude Code, Cursor, ChatGPT, Windsurf, VS Code, or anything that supports remote MCP servers over Streamable HTTP.
- That's it. Auth is OAuth — your client walks you through it on first use. No API keys to create or paste. (Sites connected through the Wix or Shopify app use a personal link instead — see Site connection links.)
03Connect in a minute
Everything runs through one server URL:
https://www.flowcrews.com/mcp
- Add the URL to your AI tool's MCP / connector settings (see below for where that lives in your client).
- Your tool opens a secure Flows sign-in — approve it once.
- Ask for a component. It appears in your Flows studio, live.
whoami first — if it returns your account email, the connection is working. If you own more than one site, use a site connection link instead and the model always targets the right one.04Any MCP client
Every MCP client connects the same way — there's nothing tool-specific to learn. Claude, ChatGPT, Grok, Cursor, Windsurf, VS Code, and anything else that supports remote MCP servers over Streamable HTTP all point at the one URL:
https://www.flowcrews.com/mcp
Clients with a connectors / MCP settings panel take the URL directly — add a custom connector or server and paste it in. Clients that use a JSON config file add a server entry with the same URL:
{
"mcpServers": {
"flows": {
"url": "https://www.flowcrews.com/mcp"
}
}
}Either way, OAuth is handled for you: your client opens a Flows sign-in the first time it calls a tool — approve it once and you're connected. No API keys, nothing to configure per client.
05Site connection links
A site connection link is the second way in: one credential that belongs to a single site and skips the sign-in step entirely. Every site gets one, whichever way you run Flows — web, Wix App Market or Shopify App Store.
Reach for one when:
- You work inside the Wix or Shopify app. There's no separate Flows sign-in to complete — your identity is the platform session — so OAuth can't identify you and a site link is the only route.
- You own several sites. The link is hard-bound to one of them, so the model can't design into the wrong project. It's the option the Studio recommends for exactly this reason.
Open Crew Studio in the dashboard and choose Setup MCP. It shows the credential for that site in two forms. The URL form goes anywhere the universal URL goes:
https://www.flowcrews.com/mcp?pair=…
The header form is the better one where your client supports custom headers — it keeps the credential out of URLs, and therefore out of request logs and browser history:
{
"mcpServers": {
"flows": {
"url": "https://www.flowcrews.com/mcp",
"headers": {
"Authorization": "Bearer flows_pair_…"
}
}
}
}Once it's in, there is no sign-in step and every tool is locked to that one site — asking the model to target a different site is refused, not silently redirected.
Expiry and revoking
- Web and Wix — the link doesn't expire. Keep it in your client's config the way you'd keep an API key.
- Shopify — the URL form expires after 7 days (Shopify requires it of any credential carried in a URL). The Bearer key form doesn't expire. Reopen Setup MCP whenever you need a fresh URL.
- Regenerate — the button on the Setup MCP page mints a new credential and permanently kills every link and key issued for that site before it. That's the action to take if you think a link has leaked, or when someone leaves the team.
- Disconnecting the site, or uninstalling the Wix or Shopify app, stops every link for that site working.
06Your first component
Once connected, just describe what you want. A good first prompt:
Use Flows to build me a glassmorphic "Key Takeaways" component with staggered reveal animations, matched to my brand accent.
A capable model will typically:
- Call
get_authoring_guideto learn your brand colours, logo and the component token/behaviour palette. - Call
get_site_screenshotto see your site's current look, so the design lands in your visual language rather than a generic one. - Call
get_type_scaffoldif the type it's building is a constrained one (see Component types). - Design and save with
create_or_update_component— or several takes at once withcreate_component_variants.
The save returns a live preview link you can open straight away, no dashboard needed. The design also lands in your Flows studio, where you can compare variants side by side and choose what renders on your articles.
To change an existing design rather than add another, the model reads it
first: get_my_components for the list of ids, then
get_component_source for that design's HTML, CSS and script,
then create_or_update_component with the same
configId. Editing that way builds on what's there instead of
starting over.
07Component types
A design always fills one type — a named slot with its own
data tokens. Call list_component_types for the live list with
each type's exact tokens; this is what's there today.
Hero banner. Tokens: title, category, heroImage, readingTime, wordCount.
Table of contents — a ~240px left rail. The page owns stickiness and the mobile version, so this type is restyle-only: the model must call get_type_scaffold and rework that markup, keeping the scrollspy hooks.
TL;DR summary — a list of points.
Conclusion takeaways — a list of items.
FAQ — questions with rich-text answers. Emits FAQ structured data.
Sources & citations — URL and domain per source.
Related articles — title, category, thumbnail, link.
The full article-library page at your site root — articles, categories, title and subtitle. Its metadata is set separately with configure_listing_page.
The site header wrapping every article and listing page. Designed inside a locked shell — Flows owns stickiness, page width and the mobile-menu wiring; the design owns the look. A desktop nav and a mobile menu are both required, and links come verbatim from your page list.
The site footer. In-flow and static, links verbatim from your page list. Flows always renders its own slim AI-disclaimer strip beneath, so a design never includes one.
The product card every store-product slider uses — one design globally. Add data-fl-buy to a button and Flows wires real checkout on every platform; the design never touches product IDs.
A reskin of your reader chat. No HTML and no tokens — see Chat skins.
Designs are HTML with {{tokens}} plus CSS. Interactivity comes
from first-party data-fl-* hooks — accordion, tabs, carousel,
reveal, scrollspy, lightbox — which the model looks up with
list_behaviors; you write markup and Flows wires the
JavaScript. Light and dark both work when a design styles through the
--fa-* variables. An optional interaction script is available
for logic the hooks don't cover, and runs isolated from your page.
08Going live: proposed, then published
What renders on your real pages is always your call, made from your own signed-in Studio session — never from a connected model. The rule is simple:
- An empty slot — the first design saved into it goes live immediately. There was nothing to protect.
- A slot that already has designs — a new design is saved as an alternate and returns
saved_pending_activation. Your live page doesn't change. - Refining an existing design — pass its
configIdand it keeps whatever standing it had. Edit the live one and your edit is live; edit an alternate and it stays an alternate.
To publish an alternate, open the preview link the save returned, find the
design's folder in the Studio sidebar, and click Set default
(★). set_active_component does not publish — it returns
pending_approval plus that preview link, so the model can hand
you the design to approve rather than push it out itself.
09Chat skins
Your reader chat — the concierge — can be reskinned end to end from your AI
tool, using the conciergeSkin type. One skin paints every place
the chat mounts: the article-page drawer, the universal site embed, and the
Shopify storefront chat. There is no per-surface variant to keep in sync.
A skin is CSS only. The chat's markup and behaviour —
wiring, slide mechanics, sign-in, checkout, virtual try-on — are
first-party and stay locked, which is what lets a skin be safe to ship to
real readers. So html is sent empty, and
cssDark carries the one stylesheet.
Start with the design map
get_chat_design_map is the first call, always. It's generated
live from the chat's own stylesheets, so it can never drift from what's
actually on screen, and it returns every region — tab, header, welcome,
messages, composer, thinking indicator, settings, sign-in and OTP, account,
history, paywall, orders, gallery, shop pane, product sliders — with its
classes and the scope selector each one needs, plus every
--fl-c-* theme variable with its dark and light
defaults. Everything in the map is yours to style; nothing outside it exists.
One sheet, both modes
The chat runs in dark or light depending on the site, marked by
data-mode on its roots. A skin ships one
stylesheet covering both: your base rules, plus a
[data-mode="light"] block. The save gate checks that the light
block is there, so a skin can't go out looking right in one mode and broken
in the other.
/* base — dark */ .fl-concierge-panel { --fl-c-bg: #0b0b0f; --fl-c-accent: #7c5cff; } /* required — the same design in light */ .fl-concierge-panel[data-mode="light"] { --fl-c-bg: #fff; --fl-c-accent: #5b3df5; }
Design roles — the fast path
Instead of hunting every button class, a skin can set
roles: one block of CSS declarations per design role, which
fans out to every member of that role across all views. Style
iconButton once and every header, attach, copy and close button
matches. The roles are title, subtitle,
kicker, body, link,
primaryButton, secondaryButton,
dangerButton, iconButton, input,
bubbleUser, bubbleAi, card,
pill, accent, price,
media, surface, overlay and
ground — the design map is the authoritative list, and it
names every member each one reaches. Note that accent paints
indicators (backgrounds and strokes) while price colours price
text, so a price never ends up looking highlighter-barred.
Colour-bearing roles take a
{ dark, light } pair, and the light value reaches every member
automatically. Per-element exceptions still go in the stylesheet afterwards.
Restructuring views
Three views additionally accept your own markup through
templates: welcome, profile and
orderRow. Each replaces the inner markup of a first-party
wrapper, so the wiring survives — the contract for each (available tokens,
required data-fl-slot placeholders, allowed tags) comes from
the design map. Pass an empty string for a view to restore the stock one.
The conversation core — bubbles, thinking, composer, sign-in — keeps one
shared structure for everyone and is expressed entirely through CSS.
Swapping the two icons
thinkingIcon replaces the glyph inside the thinking indicator
and tabIcon replaces the chevron in the edge tab that opens the
chat. Each takes a single static <svg> with a
viewBox, drawn in currentColor from plain shapes —
no scripts, links, embedded images or SMIL animation. The spin and slide
animations stay first-party; tune their speed and colour from your CSS. Pass
an empty string to restore either default.
Scoping rules
Every selector belongs inside the chat's namespace — the
fl-c-* and fl-concierge* classes from the design
map. Sub-namespace classes must sit under their region's root, so
.fl-concierge-panel .st-row and .fl-c-shop .d-card
rather than the bare class. The save gate enforces this, and it's what keeps
a skin from leaking into the surrounding page.
Coverage feedback
Every save reports which regions your sheet actually touched and which are
still on the stock look, so a model can iterate until the whole chat reads
as one design. Aim for nothing important left in
untouchedRegions — and remember to style states, not just
resting looks: the pre-chat welcome, the paywalled state, the docked shop,
thinking with one agent versus several, hover and disabled on the send
button, focus on the inputs — in both modes.
Reskin my Flows reader chat in warm editorial cream with a serif display face and squared-off bubbles. Read the chat design map first, use roles for consistency, and cover light mode too.
A skin follows the same publishing rule as everything else: the ★ default skin is the live one, and you set it. See Going live.
10Data tables
The tables in Projects → Databases are reachable over MCP too, through the same data layer the dashboard uses — so a table your model creates is a real table, visible and editable in the app straight away.
These are your own tables. They aren't a mirror of a Wix or Shopify catalogue, and MCP has no route to your store's products, orders or customers.
What the model can do
- Read —
list_tablesfor the inventory and your plan's quota,get_tablefor one table's schema and a few sample rows,query_rowsfor the rows themselves with optional keyword search and exact-match filters. - Shape — create and rename tables, add, rename and remove columns.
- Fill — add rows in batches, update a row's fields (a merge, so untouched columns keep their values), delete rows.
- Organise — create, rename and delete folders, and move tables between them. Deleting a folder never deletes tables: they move back to the root.
Column types
text, long_text, number,
price, boolean, date,
select (with an options list),
image, url. A column with no type given is
text.
Synced tables are read-only
A table fed by an external source can be read but not written — writes come
back as synced_readonly naming the provider. Change the data at
its source and re-sync, or delete the table. Connecting a new external
source, and bulk file import, stay in the dashboard: neither is on MCP.
Create a "Store FAQs" table in Flows with question and answer columns, fill it from the FAQ page on my site, and let my site chat read it.
11Site chat access
set_ai_readable is the same switch as Allow AI to read
this table in Databases → Configure. Turned on, your
public site chat may use that table's rows when answering
visitors. That makes it the one data tool worth understanding
before you use it: it changes what strangers on your site can be told.
Turn it on for reference data — FAQs, opening hours, shipping rules, specifications. Leave it off for anything about a person.
Flows checks for you as well. If a table's columns look personal, the first
call comes back as needs_ai_read_confirm with the specific
fields that triggered it, rather than switching anything on. A model should
show you that list and ask; only then does it call again with
confirm: true. An optional aiDescription
gives the chat a short note on what the table is for.
12Confirmations
Anything that destroys data refuses to run on the first call. The model has to come back a second time with proof you agreed — so a misread instruction can't take a table with it.
- Removing a column — the first call returns
needs_confirmationwith a short-livedconfirmToken. The second call passes that token back. - Deleting a table or folder — needs both
confirm: trueandconfirmNamematching the exact name (case doesn't matter). Naming the thing out loud is the safeguard. - Deleting several rows at once — needs
confirm: true. A single row by id doesn't. - Turning on site-chat reading — see Site chat access.
None of this is something you configure — it's how the tools behave. Your part is simply to read what the model is about to delete before you say yes.
13Tool reference
Every tool below takes an optional instanceId and almost never
needs one — see Working across sites. Tools marked
confirm refuse the first call and ask for agreement; see
Confirmations.
Confirms who's connected — your account id and email, or the single site a connection link is bound to. The quickest "is this working?" check.
The Flows sites you own — id, name, domain, platform and niche. A site connection link sees only its own site.
Every buildable type with the data tokens it binds, the behaviours it may use, and whether it's scaffold-constrained. See Component types.
The built-in interactivity library — accordion, tabs, carousel, reveal, scrollspy, lightbox — with the exact markup that activates each and the classes it toggles.
The system scaffold for a constrained type (today: toc), plus what must be kept. Required before designing that type — the model restyles this rather than inventing layout.
The full authoring palette — HTML, CSS, behaviours, theming, token binding, the interaction-script API and the chat-skin guide — opening with your site's brand context so designs come out on-brand.
The reader chat's complete design surface, generated live from its own stylesheets: every region with its classes and scope selector, plus every theme variable with dark and light defaults. Required before a chat skin.
A screenshot of your homepage — above the fold, or fullPage for the whole thing — so the model designs against what's actually there. Cached for 7 days; refresh forces a new capture.
The designs saved on your site — id, name, type, whether it's the live one, its accent, and a preview link. The starting point for any edit.
One design's full source — HTML, CSS for both modes, interaction script, type, name, accent — so an edit builds on what exists instead of replacing it blind.
Saves a design to one of your site's types. Omit configId to create, pass it to refine. Returns a live preview link, and for chat skins a coverage report. Publishing follows Going live.
Two to six takes on one type in a single call, to compare side by side in the Studio.
Proposes a saved design as the live one. Changes nothing on its own — it returns the preview link for you to publish with ★ Set default.
Removes a saved design by id.
Your article-library page's title, subtitle, meta title, meta description and social share image. Send only the fields to change.
Every table on the site — id, name, columns, row count — plus your plan's table and storage quota.
One table: name, column schema with field types, row count, and a few sample rows.
Rows from a table, with optional keyword search (q) and exact field filters. 25 rows by default, 50 maximum; page with offset.
A new table, with optional starting columns and a description. Live in the Databases tab immediately. Plan table caps apply.
Change a table's name and/or description.
Deletes a table and every row in it. Needs confirm plus the exact table name.
Add a column, with a type and — for select — its allowed values.
Rename a column. Existing values move to the new field name.
Removes a column and its values from every row. Needs a confirm token from the refused first call.
The folders on a site, for organising tables.
A new folder.
Rename a folder.
Removes a folder. Tables inside move back to the root — they're never deleted. Needs confirm plus the exact folder name.
Move a table into a folder, or back to the root.
Insert rows as plain objects of column → value. Up to 50 per call.
Update one row by id. A merge — send only the columns to change and the rest keep their values.
Delete one row by id.
Delete up to 50 rows by id. More than one needs confirm.
Your store products, newest first — id, name, price, which store it came from, its collections, whether it's hidden, and how many content sections it has. Where a product id comes from. Optional name search; 25 by default, 50 maximum.
One product's description and content sections in order, plus the limits a write must respect. Read before writing — writing replaces the whole set.
Writes the accordions shoppers open on a product — up to 6 sections of plain text with •, 1., ## and **bold** markers. Replaces every section in one call, so send back the ones you're keeping; an empty array clears them. Live immediately, and editable in Commerce → Your Products → Content.
The paragraph above a product's sections, up to 2,000 characters. Saved straight to Stripe, so it also appears on Checkout, invoices and receipts. Stripe and manual products only — Wix and Shopify descriptions stay on those platforms.
Turns site-chat reading on or off for one table, with an optional description for the chat. Personal-looking columns trigger a confirm step first — see Site chat access.
14Response statuses
Tools answer with a status rather than throwing, so a model can
react instead of stalling. These are the ones you'll see quoted back at you.
It worked.
The design saved as an alternate. Your live page is unchanged until you set it default.
A design is ready to publish and the preview link is waiting for your click.
You own several sites — name the one you mean.
Your account has no connected site yet.
A destructive call was refused pending your agreement.
A table looks personal and site-chat reading wasn't switched on. The response lists which fields triggered it.
A plan allowance is full — custom components, tables or storage. Nothing partial was saved.
Custom component building isn't switched on for this site yet, so nothing was saved.
That table is fed by an external source. Edit it there and re-sync.
The connection isn't authenticated — see Troubleshooting.
No such id, a service was briefly unavailable, or something else went wrong — the message says which.
15Limits
Generous in practice, but worth knowing when a model reports something got refused.
- A design — up to 60 KB of HTML, 40 KB of CSS per mode, and 20 KB of interaction script.
- Variants — two to six per
create_component_variantscall. - Reading rows — 25 by default and 50 at most per call, with up to 20 filter keys. Page with
offset. - Writing rows — up to 50 rows per add or bulk-delete call.
- Columns — up to 100 per table, and up to 50 options on a
select. - Screenshots — cached for 7 days per site; ask for a refresh after you redesign.
- Plan allowances — custom components, tables and storage are all plan-based. Over the line you get
limit_reachedwith an upgrade note, and nothing partial is written.
16Working across sites
Every tool takes an optional instanceId. You almost never need it:
- One site — tools resolve to it automatically. Just ask.
- Several sites — the tool answers
choose_sitewith your site list and the model asks which one you mean. Name the site in your prompt ("…on my cooking blog") and it carries on. - Connected with a site link — that one site is always the target, and naming a different one is refused rather than silently redirected. To work on another site, add its own link.
Reads and writes only ever succeed on sites your account owns — every call re-checks that on the server, whichever way you connected.
17Authentication
There are two ways to authenticate, and both end at the same server-side ownership check.
OAuth — the universal URL
OAuth 2.1 with PKCE and dynamic client registration, the modern MCP auth standard. When your client first connects it opens a Flows sign-in; you approve access to your email and profile, and the client manages tokens from there. There are no API keys to create, store, or leak. Signing out of the connector in your client ends its access.
Site connection links
A signed per-site credential, used as a URL parameter or a bearer header. It carries no account-wide reach: it identifies one site, and every tool is locked to it. Revocation is a live check on every single call, which is why Regenerate takes effect instantly rather than waiting for a token to age out. Full detail in Site connection links.
Whichever route you take, every call is verified server-side against your Flows account. Nothing is trusted because the model said so.
18Permissions & scope
What a connected model can reach:
- Component designs — read, create, refine and delete them, on the types listed in Component types.
- Listing-page metadata — title, subtitle, meta title and description, social image.
- Your data tables — read and write the tables in Projects → Databases, and switch site-chat reading on or off per table.
- Read-only site context — your brand details and a screenshot of your homepage, so designs match your site.
What it cannot reach, by construction:
- Publishing. It can't change what renders on a page that already has a design. That's your click — see Going live.
- Billing, subscribers, orders, account settings, or your articles. There is no tool for any of them.
- Your store. No route to Wix or Shopify products, orders or customers.
- Other people's sites. Ownership is re-checked server-side on every call, and a site link is bound to one site.
And how what it writes is handled:
- Sanitised: designs pass the same sanitising pipeline as everything else in the Studio before they render on your articles, and an interaction script runs isolated from your page.
- Reversible: a design is a saved object you can preview, swap or delete. Destructive data operations require a second, explicit confirmation — see Confirmations.
- Plan-aware: new components and tables count against your plan's allowances. Over the line, the write is declined with an upgrade note and nothing partial is saved.
19Troubleshooting
- "Unauthorized" from every tool — the OAuth handshake didn't finish. Remove and re-add the connector, and complete the Flows sign-in when it opens.
- Your connection link stopped working — it was regenerated, the site was disconnected, or the Wix or Shopify app was uninstalled. Open Crew Studio → Setup MCP and copy the current one. On Shopify, a link older than 7 days has expired by design — take a fresh URL, or switch to the bearer key, which doesn't.
- "No sites" — your Flows account has no connected site yet. Connect one in the dashboard, then try again.
- "Choose a site" — you own several sites; tell the model which one you mean, or connect with that site's own link.
- "This connection is scoped to one site" — you're on a site link and asked for a different site. Add that site's own link as a second server.
- "Limit reached" — a plan allowance is full: custom components, tables or storage. Delete something unused, or upgrade.
- "Coming soon" when saving a design — custom component building isn't switched on for that site yet. Nothing was saved.
- A table refuses writes — it's synced from an external source and is read-only here. Change the data at its source and re-sync.
- The design saved but the page looks the same — that's the propose-then-publish gate, not a bug. Open the preview link and set the design as default; see Going live.
- A chat skin looks wrong in one mode — the light block is missing or incomplete. Ask the model to re-read
get_chat_design_mapand cover[data-mode="light"]for every region it styled. - The model designs something generic — it skipped the context calls. Ask it to run
get_site_screenshotandget_authoring_guidefirst, and for a table of contents,get_type_scaffold. - Client can't find the server — double-check the URL is exactly
https://www.flowcrews.com/mcpand that your client supports remote MCP servers (Streamable HTTP), not just local ones.
Still stuck? Ask Sam — the chat bubble on this page — or reach us from the dashboard.