Recipes
Worked end-to-end flows over MCP. Each is a sequence of tools/calls — phrased here as what you'd ask an agent, with the tools it uses. All run through the same scopes/auth as REST.
1. Author, test, and run a workflow — entirely over MCP
"Build a workflow that sends a Slack message whenever a deal moves to Won, then test it."
The agent chains:
get_workflow_authoring_guide— learn the YAML authoring spec (workflows:read).list_workflow_nodes/get_workflow_node_schema— find the trigger + Slack node and their config fields.validate_workflow— compile the YAML spec; fix any blocking errors before saving.create_workflow— save it (as a draft — it won't fire until activated) → returnsworkflow_id.test_workflow_nodeorrun_workflow— dry-run it. Both are confirm-gated: the first call returns a confirmation summary; re-call withconfirm: trueto actually execute (real side effects, no sandbox).activate_workflow— once happy, let it fire on its trigger (workflows:author).
There is no sandbox — a run hits live data and integrations. That's why run/test tools require an explicit confirm: true on the second call. Build with workflows:author; keep run rights (workflows:run) on a separate key if you want approve-only agents.
2. Ask your knowledge base (RAG)
"What's our refund policy for annual plans?"
list_knowledge_bases— find the KB id (knowledge:read).ask_knowledge_base—{ kb_id, question }→ returns{ answer, sources }(retrieval + LLM; incurs credits).
Prefer search_knowledge_base when you want the raw relevant chunks (with scores) rather than a synthesized answer.
{
"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {
"name": "ask_knowledge_base",
"arguments": { "kb_id": "…", "question": "What is our refund policy for annual plans?" }
}
}
Add a document first with add_kb_document (raw text/markdown, or a base64 file — pdf/docx/…); it's chunked, embedded, and searchable on return.
3. Natural language → SQL → chart
"What was our total Meta ad spend last quarter, by campaign? Chart it."
get_data_model— the grounded schema: tables, columns, real enum values, join graph, custom-field refs (analytics:read). Read this so the agent uses real names, not guesses.generate_sqlorrun_querywithquestion— the NL→SQL agent grounds + validates read-only SQL and (invalidatemode) returns sample rows + thegenerated_sql.create_dataset— save the SQL as a reusable dataset (analytics:write).create_chart— build a chart on the dataset (chart_type,chart_configwith dimensions/metrics).run_chart— get the server-side aggregated rows to render.
Only SELECT is allowed — writes are blocked and queries are org-scoped.
4. Single-node test before you commit
"Show me exactly what this API Request node returns for this contact."
test_workflow_node runs one node in isolation with sample inputs — no saved workflow needed. Give node_type, an optional config (with {{templates}}), and sample inputs. Confirm-gated: the first call returns the resolved config + node schema to review; re-call with confirm: true to execute and see the real output. Great for debugging a node's config before wiring it into a workflow.
5. Enrich a contact from the CRM
"Find the contact for jane@acme.com and log a note that she requested a demo."
search_contacts—{ q: "jane@acme.com" }(contacts:read).create_note—{ entity_type: "contact", entity_id: "<id>", content: "Requested a demo" }(notes:write).- optionally
create_task— a follow-up task linked to the contact.
Associations work the same way: list_contact_companies, link_contact_to_company, etc. — each requiring read/write on both entities.
6. Bulk update 1,000 records — chunked, with a per-chunk report
"Set lead_status to 'nurture' for these 1,000 contacts, and don't fire my automations."
Batch tools take the entity as a parameter and up to 200 items per call — the agent chunks 1,000 into 5 calls and reports each chunk's outcome:
batch_update_records× 5 —{ entity: "contacts", updates: [ ...200 × { id, lead_status: "nurture" } ], suppress_automations: true }(contacts:write).- Each call is atomic: it returns
counton success, or a per-index error (batch_validation_error/ unknown-id) and nothing in that chunk is written — so the agent always knows exactly which rows are committed:
✅ chunk 1 (rows 1–200): 200 updated ❌ chunk 2 (rows 201–400): rejected — row 237:
lead_scoremust be an integer; no rows in this chunk were written ✅ chunk 3 (rows 401–600): 200 updated ✅ chunk 4 (rows 601–800): 200 updated ✅ chunk 5 (rows 801–1000): 200 updated
- The agent fixes row 237 and resends only chunk 2 — the committed chunks must not be resent.
batch_create_records and batch_delete_records work the same way. suppress_automations: true is the bulk-import switch: records are written and stay searchable, but per-record workflow triggers don't fire (no surprise credit burn). Leave it off when the automations are the point. Full semantics + REST equivalents: Bulk Operations.
Every tool's exact input schema + required scope is in the Tool catalog. tools/list shows the full catalog (plus your org's exposed workflow tools when authenticated); your key's scopes are enforced when a tool is called.