Manage your AI setters programmatically.
SetterFlow ships a remote Model Context Protocol server so you — or an AI agent — can list, create, and edit your own AI setters from Claude Code, Cursor, or any MCP client. Every request is scoped strictly to the account that minted the key.
POST https://www.setterflow.com/api/mcpStreamable HTTPStatelessMint a key, then call the endpoint
Three steps from zero to a live tool call. Most people skip curl and point Claude Code or Cursor at the same URL.
- 1Mint a key
In the dashboard, open Settings → API Keys and create a key with a read, read + write or read + inbox scope. The full
sf_…token is shown once — copy it immediately. - 2Send Bearer auth
Send it on every request as a Bearer token:
Authorization: Bearer sf_… - 3Call JSON-RPC
Speak JSON-RPC over Streamable HTTP: initialize, list tools, then call one. The transport is stateless — each request is authenticated on its own.
# 1) Initialize the session (handshake)
curl -sS https://www.setterflow.com/api/mcp \
-H "Authorization: Bearer sf_your_key_here" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize",
"params":{"protocolVersion":"2025-06-18",
"capabilities":{},
"clientInfo":{"name":"curl","version":"1.0"}}}'
# 2) List the tools your key can call
curl -sS https://www.setterflow.com/api/mcp \
-H "Authorization: Bearer sf_your_key_here" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
# 3) Call a tool (list your own chatbots)
curl -sS https://www.setterflow.com/api/mcp \
-H "Authorization: Bearer sf_your_key_here" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call",
"params":{"name":"list_chatbots","arguments":{}}}'Client config snippets live in docs/mcp.md.
Three coarse scopes. Nothing in between.
A write key does not implicitly grant read — grant both if a single key should do everything. A key can also be limited to some of your setters.
30 tools
Read-only tools — list and inspect your data. Safe to hand to something that should only look, never change.
32 tools
Every mutating tool (create / update / delete / configure). A write key can change everything you own — treat it like a password.
12 tools
Work the inbox from a staff app: read threads and leads, reply as a person, pause or resume the bot, translate, set lead status. Never settings, documents or deletes.
64 tools, grouped by area
Generated directly from the live server registry — it always matches what your key can call.
Account
3 toolsWho you are and your account posture.
whoamireador inboxReturn the authenticated caller identity (userId, granted scopes, and the setters this key is limited to: chatbotIds, or null for all of them). No database access.
No arguments
get_accountreadGet the caller's own account (identity + subscription posture).
No arguments
update_profilewriteUpdate the caller's own profile (full_name only).
| Arg | Type | Required |
|---|---|---|
full_name | string | required |
Chatbots
5 toolsCreate, read, update, and delete your AI setters.
list_chatbotsreadList the caller's own chatbots (AI setters).
No arguments
get_chatbotreadGet one chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
create_chatbotwriteCreate a chatbot (AI setter) owned by the caller. owner_id is forced server-side. Recommended: set `playbook` (see list_playbooks) and `business_profile` (see update_business_profile); with a playbook, system_prompt holds only the business's own notes and may be short.
| Arg | Type | Required |
|---|---|---|
name | string | required |
website_url | string | required |
business_context | string | required |
system_prompt | string | required |
model | string | optional |
status | enum(active | inactive) | optional |
playbook | string | optional |
business_profile | record | optional |
update_chatbotwriteUpdate a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
name | string | optional |
website_url | string | optional |
business_context | string | optional |
system_prompt | string | optional |
model | string | optional |
status | enum(active | inactive) | optional |
playbook | string | optional |
business_profile | record | optional |
delete_chatbotwriteDelete a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
Appearance & widget config
2 toolsThe widget customization blob — colors, launcher, proactive teaser, Articles tab, and the invitation layer — plus the logo URL.
get_bot_configreadRead a chatbot's widget config (customization JSONB + logo_url) for a bot the caller owns. Null sub-objects mean unset (not default-filled).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
update_bot_configwriteUpdate a chatbot's widget config (read-merge-write). Send only the top-level customization keys you want to change; omitted top-level keys are preserved. WARNING: a sub-object you include (proactive / articlesTab) REPLACES the stored one wholesale, so send the FULL sub-object with all its fields. logo_url is a separate column (http/https URL, or null to clear) — not part of customization.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
customization | object — see docs/mcp.md | optional |
logo_url | string (http/https URL) | optional |
Setter config (lead capture)
2 toolsLead-capture settings — industry template, qualification questions, and collected fields.
get_lead_settingsreadRead lead-capture settings for a chatbot the caller owns (null if unconfigured).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
configure_lead_settingswriteConfigure lead-capture for a chatbot the caller owns. Expands the named industry template server-side; overrides are optional.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
industry | enum(aesthetics | dental | real_estate | home_services | coaching | custom) | required |
enabled | boolean | optional |
qualification_questions | array | optional |
collect_fields | array | optional |
notification_email | string | optional |
notification_webhook_url | string | optional |
Knowledge base
5 toolsPlain-text documents that your setter can answer from.
add_knowledge_documentwriteAdd a plain-text knowledge document to a chatbot the caller owns. Live in the bot's knowledge base on the next chat turn; counts against the document quota.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
title | string | required |
content | string | required |
list_documentsreadList knowledge-base documents for a chatbot the caller owns (crawler-projected docs excluded; document text not included).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
get_documentreadGet one knowledge-base document (including its text content) on a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
documentId | string | required |
delete_documentwriteDelete a knowledge-base document on a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
documentId | string | required |
update_knowledge_documentwriteEdit a knowledge-base document's text. mode 'replace_text' swaps an exact passage (target) for replacement; 'append' adds text at the end; 'rewrite' replaces the whole content. Every edit records a revision that can be undone. Editing a crawled page creates an override document instead, so the next crawl cannot erase the correction.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
documentId | string | required |
mode | enum(replace_text | append | rewrite) | required |
target | string | optional |
replacement | string | optional |
text | string | optional |
content | string | optional |
instruction | string | optional |
Website & crawl
7 toolsRegister website sources, trigger background crawls that feed the knowledge base, and curate which crawled pages appear in the widget Articles tab.
add_website_sourcewriteAdd a website source to a chatbot the caller owns (idempotent on URL). The URL must be an http/https address. This only registers the source; call trigger_crawl to start crawling (which runs in the background — poll get_crawl_status).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
url | string (http/https URL) | required |
configure_website_sourcewriteConfigure an existing website source's crawl behavior for a chatbot the caller owns. `refresh_interval_minutes` sets the auto-recrawl cadence. `url_filter` (with `include` and/or `exclude` arrays of URL substrings/patterns) limits which pages are crawled. Only the fields you send are changed; omitted fields are preserved. The sourceId must belong to the chatbot, else 'not found'. Returns the source's config after the update. (Use add_website_source to create a source, trigger_crawl to start a crawl.)
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
sourceId | string | required |
refresh_interval_minutes | number | optional |
url_filter | object — see docs/mcp.md | optional |
trigger_crawlwriteTrigger a crawl for a chatbot the caller owns. Provide a sourceId to crawl one source (it must belong to the chatbot, else 'not found'), or omit it to crawl all of the chatbot's sources. Crawling runs in the background — poll get_crawl_status for progress.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
sourceId | string | optional |
list_website_sourcesreadList the website sources for a chatbot the caller owns (each with its seed URL, refresh cadence, and current crawl status).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
get_crawl_statusreadPoll the crawl status for a chatbot the caller owns — one status row per source (last crawl status/time, latest job status, page counts). Use this to track a crawl started by trigger_crawl.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
list_source_articlesreadList a crawled source's article/content pages for a chatbot the caller owns — each with its storage_path (the id used by set_article_curation), title, url, and current show_in_article_tab flag. Paginated (limit/offset) and optionally filtered by search. Use this to discover which pages exist before curating the widget Articles tab.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
sourceId | string | required |
limit | number | optional |
offset | number | optional |
search | string | optional |
set_article_curationwriteShow or hide ONE crawled page in the widget's public Articles tab, for a chatbot the caller owns. Pass the page's storage_path (from list_source_articles) and enabled (true = show, false = hide). NOTE: the Articles tab itself must also be enabled via update_bot_config (customization.articlesTab.enabled) for curated pages to render to visitors.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
storage_path | string | required |
enabled | boolean | required |
Follow-ups
4 toolsAutomated follow-up message templates.
list_followupsreadList follow-up message templates for a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
create_followupwriteCreate a follow-up template on a chatbot the caller owns. Requires the followUpSequences feature. delay_minutes is 5..1380 (defaults to 120).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
trigger | enum(no_reply_2h | hot_lead_stall | appointment_reminder) | required |
message_template | string | required |
delay_minutes | number | optional |
is_active | boolean | optional |
update_followupwriteUpdate a follow-up template on a chatbot the caller owns. Send only the fields you want to change.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
followupId | string | required |
trigger | enum(no_reply_2h | hot_lead_stall | appointment_reminder) | optional |
message_template | string | optional |
delay_minutes | number | optional |
is_active | boolean | optional |
delete_followupwriteDelete a follow-up template on a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
followupId | string | required |
Integrations
12 toolsCRM, calendar, and social connections (read + disconnect — connecting a channel is OAuth-only).
list_crm_connectionsreadList CRM connections for a chatbot the caller owns. Secret api_key is never returned.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
create_crm_connectionwriteCreate a CRM connection on a chatbot the caller owns. Requires the crmIntegration feature.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
crm_type | enum(gohighlevel | hubspot | slack | webhook | kommo | monday) | required |
api_key | string | required |
auto_push_enabled | boolean | optional |
push_on_status | enum(hot | warm | any) | optional |
update_crm_connectionwriteUpdate an existing CRM connection's push behavior on a chatbot the caller owns: auto_push_enabled (on/off), push_on_status (hot | warm | any — which leads get pushed), and is_active. The api_key credential can't be changed here — rotate it by deleting and re-creating the connection. Only the fields you send change. The secret api_key is never returned.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
connectionId | string | required |
auto_push_enabled | boolean | optional |
push_on_status | enum(hot | warm | any) | optional |
is_active | boolean | optional |
delete_crm_connectionwriteDelete a CRM connection on a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
connectionId | string | required |
list_calendar_connectionsreadList calendar connections for a chatbot the caller owns. Access/refresh tokens are never returned.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
delete_calendar_connectionwriteDelete calendar connections for a chatbot the caller owns (calendar create is OAuth-only, not available via MCP).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
configure_availabilitywriteSet booking availability on a chatbot's ACTIVE calendar connection (a bot the caller owns) — the write side of the availability list_calendar_connections returns. `days` REQUIRES all seven keys (mon,tue,wed,thu,fri,sat,sun), each { start, end (24-hour "HH:MM"), enabled }; a disabled day is closed. slotDuration and bufferMinutes are minutes; timezone is an IANA name (e.g. "Europe/Nicosia"). This REPLACES the stored availability wholesale. Requires a calendar already connected via OAuth — a bot with no active calendar returns 'not found'.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
availability_config | object — see docs/mcp.md | required |
list_social_connectionsreadList social (Facebook Messenger / Instagram) connections for a chatbot the caller owns. The Meta page access_token is never returned.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
disconnect_social_connectionwriteDisconnect (delete) a social connection on a chatbot the caller owns. Connecting a channel is Meta OAuth and not available via MCP.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
connectionId | string | required |
set_social_auto_replywriteTurn auto-reply on or off for one social (Messenger / Instagram) connection on a chatbot the caller owns. When off, the bot stops answering that channel automatically so a human can take over the inbox. Returns the updated connection (access_token never included).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
connectionId | string | required |
enabled | boolean | required |
list_social_conversationsreador inboxList a setter's Messenger, Instagram and WhatsApp conversations, newest first, with the bot's state on each (paused, a person replied, waiting for a reply and why). needs_reply: true lists only customers waiting on a person.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
limit | number | optional |
offset | number | optional |
needs_reply | boolean | optional |
get_social_conversationreador inboxRead one Messenger, Instagram or WhatsApp conversation (up to 100 messages). Each outbound message says who sent it: bot, human, auto (the business app's own auto-reply) or followup; actor_name is set when a person replied through the API. attachments lists media on a message (path, url, mime_type), [] when none.
| Arg | Type | Required |
|---|---|---|
conversationId | string | required |
Analytics
1 toolAccount-level and per-bot usage counters and daily stats.
get_analyticsreadRead analytics. Omit chatbotId for account-level usage (messages, documents, chatbots, social connections for the current period). Provide a chatbotId you own for that bot's message count, last message time, and recent daily stats.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | optional |
Inbox
5 toolsWork the inbox from another app: the merged list, replies as a person, translation, and a signed ids-only webhook. Replies and translation need the inbox scope.
list_inboxreador inboxOne setter's inbox, website chat and Messenger, Instagram and WhatsApp merged, newest activity first, the same list as the SetterFlow inbox. Each row has the channel (platform), the bot's state (handled_by_human, human_replied_at, bot_resumes_at) and, for social threads, whether a customer waits on a person (needs_reply_since, handoff_reason). needs_reply: true lists only those. Paginated: limit 1..100 (default 20), offset; total is the full count.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
limit | number | optional |
offset | number | optional |
needs_reply | boolean | optional |
platform | enum(widget | facebook_messenger | instagram | whatsapp) | optional |
send_conversation_replyinboxReply as a person in one conversation (needs the inbox scope; write is not enough). actor_name says who replied and shows in the SetterFlow inbox as "Team (<actor_name>)". Messenger, Instagram, WhatsApp: sent through Meta now, the bot pauses for the setter's pause window, an open handoff closes, queued follow-ups are cancelled. A WhatsApp reply more than 24 hours after the customer's last message fails with code whatsapp_window_closed and nothing is stored. Website chat: stored for the visitor's open widget and the bot is paused (handled_by_human) in the same call. Errors come back as {"error","code"}.
| Arg | Type | Required |
|---|---|---|
conversationId | string | required |
text | string | required |
actor_name | string | required |
translate_conversationinboxTranslate a website-chat conversation into English for the person reading it (needs the inbox scope). Detects each message's language, translates the ones not in English and caches both on the message, so a second call is free. Returns spokenLanguage, the visitor's browser language and per-message {id, source_language, translated_text}. Messenger, Instagram and WhatsApp threads return supported: false.
| Arg | Type | Required |
|---|---|---|
conversationId | string | required |
get_inbox_webhookreadRead the account's inbox webhook: url, enabled, events, last delivery time and status. The signing secret is never returned.
No arguments
set_inbox_webhookwriteSet where SetterFlow POSTs inbox events for this account, or pass url: null to turn it off. Events: conversation.message_received, conversation.needs_reply. The body carries ids, channel, timestamps and flags only, never message text or names. Each request is signed: header X-SetterFlow-Signature: t=<unix seconds>,v1=<hex HMAC-SHA256 of '<t>.<raw body>' with the secret>; reject timestamps more than 5 minutes off. url must be public https. secret (32 to 256 characters) is required the first time and never returned. Keys limited to specific setters can not change it.
| Arg | Type | Required |
|---|---|---|
url | string (http/https URL) | required |
secret | string | optional |
enabled | boolean | optional |
events | array | optional |
Conversations
3 toolsRead website chat and Messenger, Instagram and WhatsApp conversations, and pause or resume the bot on one.
list_conversationsreador inboxList widget (website chat) conversations for a chatbot the caller owns (newest first). Returns id, session_id, attribution (the owner's own marketing metadata), and created_at. For Messenger, Instagram and WhatsApp use list_social_conversations; for both merged use list_inbox.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
limit | number | optional |
offset | number | optional |
get_conversationreador inboxGet one widget conversation and its messages (capped at 100, oldest first) — resolved only after verifying the caller owns the chatbot the conversation belongs to. A conversation you do not own returns forbidden/not found. Widget conversations only.
| Arg | Type | Required |
|---|---|---|
conversationId | string | required |
set_conversation_botwriteor inboxControl the setter on one conversation. pause: the bot stays quiet until resumed (on Messenger, Instagram and WhatsApp it also cancels queued follow-ups, like Pause bot in the inbox). resume: the bot answers again (also ends the pause after a person replied). mark_handled: the customer waiting on a person has been dealt with (social only).
| Arg | Type | Required |
|---|---|---|
conversationId | string | required |
action | enum(pause | resume | mark_handled) | required |
Leads
3 toolsRead the leads your setters have captured.
list_leadsreador inboxList leads across the caller's own chatbots (or scoped to one chatbot). Cross-tenant leads never appear.
| Arg | Type | Required |
|---|---|---|
chatbot_id | string | optional |
status | enum(hot | warm | cold | converted | lost) | optional |
limit | number | optional |
offset | number | optional |
get_leadreador inboxGet one lead by id, only if the caller owns the chatbot the lead belongs to.
| Arg | Type | Required |
|---|---|---|
leadId | string | required |
update_leadwriteor inboxUpdate a lead's status (hot | warm | cold | converted | lost) and/or notes — the only mutable fields (everything else is captured from the conversation). Only if the caller owns the chatbot the lead belongs to. Pass notes as a string to set it, or null to clear it. Send at least one field.
| Arg | Type | Required |
|---|---|---|
leadId | string | required |
status | enum(hot | warm | cold | converted | lost) | optional |
notes | string | optional |
Widget
2 toolsThe ready-to-paste embed snippet, plus the origin allowlist that controls which sites may embed a bot.
set_allowed_originswriteSet the widget origin allowlist for a chatbot the caller owns — which website origins may embed and talk to this bot. Pass an array of http/https ORIGINS (scheme://host[:port], no path), e.g. ["https://www.example.com","https://example.com"]; list www and apex separately (exact match, no wildcards). An EMPTY array clears the allowlist and makes the widget embeddable from ANY origin (the default). Entries are canonicalized server-side; an invalid entry rejects the whole call. Read the current value via get_chatbot (allowed_origins).
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
allowed_origins | array | required |
get_widget_snippetreadGet the ready-to-paste HTML embed snippet for a chatbot's widget (a bot the caller owns). Paste it before </body> on the target site.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
Other
10 toolslist_custom_actionsreadList Custom Actions (tenant-configured HTTP tools the bot can call mid-conversation) for a chatbot the caller owns. The encrypted secret is never returned — only has_secret.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
create_custom_actionwriteCreate a Custom Action on a chatbot the caller owns. Define name (snake_case), description (drives when the model calls it), kind (read|write), parameters (JSON Schema for the args the model extracts), and request ({method,url,headers,body} — {{args.x}} and {{secret}} are interpolated at call time). secret is encrypted at rest and injected into headers, never shown to the model. response_map whitelists which response fields reach the model (everything else, including PII, is dropped). Optionally set allowed_hosts (host allowlist) and timeout_ms.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
name | string | required |
description | string | required |
kind | enum(read | write) | optional |
parameters | record | optional |
request | object — see docs/mcp.md | required |
secret | string | optional |
allowed_hosts | array | optional |
response_map | record | optional |
confirmation_template | string | optional |
timeout_ms | number | optional |
is_active | boolean | optional |
update_custom_actionwriteUpdate a Custom Action on a chatbot the caller owns (double-fenced on id + chatbot_id). Only the fields you send change. Pass secret to rotate the credential (re-encrypted); pass is_active:false to disable it without deleting.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
actionId | string | required |
name | string | optional |
description | string | optional |
kind | enum(read | write) | optional |
parameters | record | optional |
request | object — see docs/mcp.md | optional |
secret | string | optional |
allowed_hosts | array | optional |
response_map | record | optional |
confirmation_template | string | optional |
timeout_ms | number | optional |
is_active | boolean | optional |
delete_custom_actionwriteDelete a Custom Action on a chatbot the caller owns.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
actionId | string | required |
list_playbooksreadList the industry playbooks a setter can follow (salon, clinic, restaurant, hotel, real_estate, tours, b2b, generic): each one's know-how, shared by every setter in that industry. Facts never live in a playbook; they go in the business profile.
No arguments
get_business_profilereadRead a setter's playbook and business profile (structured facts: summary, location, hours, services and prices, team, links, contacts with a share rule, policies, what it offers and does not). Also returns facts_preview, exactly what the setter reads before its knowledge base, and notes_warnings from the prompt checker.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
update_business_profilewriteSet a setter's business profile and/or playbook. profile fields: summary, location, service_area, languages[], hours[] (one line each), services[{name, description?, price?, currency?, duration?, notes?}], team[{name, role?, specialties?}], links[{purpose: booking|website|menu|pricing|shop|directions|other, url, label?}], contacts[{type: phone|whatsapp|email|address|other, value, label?, share: always|when_asked|urgent_only|never}], policies[{topic, text}], offers[], does_not_offer[], checked_at. mode 'merge' (default) replaces only the sections you send; 'replace' swaps the whole profile. playbook: an id from list_playbooks, or null for a legacy prompt-only setter.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
profile | record | optional |
mode | enum(merge | replace) | optional |
playbook | enum(salon | clinic | restaurant | hotel | real_estate | tours | b2b | generic) | optional |
check_setter_promptreadCheck a setter's prompt or notes for conflicts before saving: leftover placeholders, sending customers to contact details while lead capture is on, markdown requests, language or date rules the platform already sets, and (for playbook setters) prices, phones or emails that belong in the business profile. Pass text to check a draft, or omit it to check what is saved.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
text | string | optional |
list_knowledge_suggestionsreadList answers people on the team gave customers in social threads that could teach the setter (a price, what a service includes). status: pending (default), approved or dismissed.
| Arg | Type | Required |
|---|---|---|
chatbotId | string | required |
status | enum(pending | approved | dismissed) | optional |
decide_knowledge_suggestionwriteApprove (optionally with an edited question/answer) or dismiss a knowledge suggestion. Approving appends it to the setter's "Answers from the team" document, which it reads from its next reply on.
| Arg | Type | Required |
|---|---|---|
suggestionId | string | required |
action | enum(approve | dismiss) | required |
question | string | optional |
answer | string | optional |
Turn on the invitation layer
The ambient, page-aware invitation is part of the widget customization, so a write key configures it through update_bot_config — no new tool. Auto-detect finds your prices and cards; smart copy writes a line per element. Flip it on with one call.
# Turn on the invitation layer for one of your chatbots.
# It lives in the widget customization, so you set it with the existing
# update_bot_config tool — no special endpoint. Sub-objects replace wholesale,
# so send the FULL invitation object (read get_bot_config first to preserve
# any custom elementTypes).
curl -sS https://www.setterflow.com/api/mcp \
-H "Authorization: Bearer sf_your_key_here" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","id":4,"method":"tools/call",
"params":{"name":"update_bot_config","arguments":{
"chatbotId":"YOUR_CHATBOT_ID",
"customization":{"invitation":{
"enabled":true,
"rolloutPercent":100,
"autoDetect":true,
"smartCopy":true
}}}}}'Sub-objects replace wholesale — send the full invitation object, and read current state with get_bot_config first if you're preserving custom elementTypes.
A few capabilities are deliberately partial
Known edges, called out so you don't discover them mid-build.
OAuth connect is not available
Establishing a new Google Calendar or Facebook/Instagram connection needs an interactive browser consent screen (human OAuth), so there is no connect tool. You can read and disconnect existing connections, but the initial connect happens once in the dashboard.
Logo is a URL, not a file
update_bot_configacceptslogo_urlas an http/https URL string only — there is no binary/image upload over MCP.Conversations are widget-only
list_conversationsandget_conversationreturn widget conversations only; social (Messenger / Instagram) transcripts are not exposed via MCP yet.
Ready to mint a key?
Operators: full deploy and security reference in docs/mcp.md. Everyone else — open the dashboard and create an API key.