MCP setup
The Crutan MCP server gives agents tool-level access to the platform. It wraps the same REST API the dashboard uses and authenticates with a workspace key. 65 tools and 11 skills, on every plan. Usage limits and monthly key spend caps apply on every call.
Prerequisites
- A workspace key — mint one at Settings → Agent access. Keys work on every plan.
- Optional monthly spend cap on the key (UTC calendar month) to bound autonomous API spend.
APP_URLpointing at your Crutan app (e.g.https://app.crutan.com).
Local stdio (Claude Desktop, Cursor)
Best for development. The key lives in your MCP client config — never committed to git.
CRUTAN_API_KEY=crt_… \
APP_URL=https://app.crutan.com \
pnpm --filter @crutan/mcp start{
"mcpServers": {
"crutan": {
"command": "pnpm",
"args": ["--filter", "@crutan/mcp", "start"],
"env": {
"CRUTAN_API_KEY": "crt_…",
"APP_URL": "https://app.crutan.com"
}
}
}
}Remote HTTP (production)
Streamable HTTP transport at /api/mcp. Each request must include the caller's workspace API key — the server acts as that key, not a shared service key.
{
"mcpServers": {
"crutan": {
"url": "https://app.crutan.com/api/mcp",
"headers": {
"Authorization": "Bearer crt_…"
}
}
}
}401. Exceeding the key's monthly spend cap returns spend_cap_exceeded from the underlying API.Skills — things you can ask an agent to do
Skills are MCP prompts — invoke by name to receive a step-by-step playbook. Your agent then calls the primitive tools in order. Also available as resource crutan://skills/catalog.
| Prompt | What it does | Example ask |
|---|---|---|
launch-campaign | Picks or builds a template, imports the people, prices the run, generates every page, and reports the links. | Make a page for everyone in this CSV using our pitch template and send me the links. |
research-and-personalize | Reads the company profile, works through the contact list, generates pages, then QAs the weakest ones. | Use our company profile to make pages for my contacts, then tell me which ones read thin. |
weekly-conversion-report | Pulls the signals summary, the hot contacts and the conversions into one short executive read. | Give me last week's Crutan report: what converted and who I should follow up with. |
connect-crm | Registers an outbound connection, fires a test delivery, and confirms the payload landed. | Connect Crutan to this webhook URL and prove a test event arrives. |
onboard-workspace | Reads your website into the company profile, checks the brand, and builds a starter template. | Set up our Crutan workspace from acme.com and build us a first template. |
reactivate-cold-leads | Finds contacts with pages but no engagement, builds a fresh angle, and re-runs pages for them. | Find the contacts who never opened their page and try a new angle on them. |
purpose-template-workflow | Turns a description into a reusable template: what each page needs, what it computes, then builds it. | Design a template for post-call ROI pages and tell me what it will need from me each time. |
purpose-run-workflow | Runs a materials template for one contact: attach materials, answer the questions, generate, publish. | Make Dana's ROI page from this call recording and publish it when it looks right. |
roi-followup | Builds the ROI template one time, then runs it per company with no further template work. | Build our ROI page template, then run it for Acme with these numbers. |
post-call-followup | Ingests the recording or transcript, asks what the buyer asked, and publishes the follow-up page. | Here's the recording from my call with Acme — publish a follow-up page for them. |
Tools
65 tools, generated from the server's own registry — this table is never hand-maintained. Every tool is also reachable under its pre-2.0 name; see deprecated names.
Usage & limits
| Tool | Purpose |
|---|---|
estimate_cost | Preview cost before spend actions. Call before create_template, iterate_template, generate_page_run, build_discovery_page, build_materials_template (type purpose_template_build), or generate_run (type purpose_run). The billing type names are the API's, not the product's: purpose_run maps to recipient_render and purpose_template_build maps to template_create. |
get_entitlements | Read plan limits, usage balance, and lock status. |
get_usage | Read the workspace's remaining usage balances. |
Templates
| Tool | Purpose |
|---|---|
list_templates | List automatic templates in the workspace (templates that personalize from your data and research). Materials templates are listed by list_materials_templates. |
get_template | Fetch a single template by ID. |
create_template | Start async AI template generation. Returns buildId — poll GET /api/templates/builds/{buildId} or list_templates until complete. |
get_template_build | Poll an async create_template build by buildId until status is completed/failed. |
iterate_template | AI-edit a template from a natural-language instruction. Requires acknowledged estimate. |
edit_template | Patch template document directly (no AI). Requires acknowledged estimate. |
clone_template | Clone a page from a public URL into the workspace as a template. |
list_template_versions | List version history for a template. |
restore_template_version | Restore a template to a prior version. |
set_lead_form | Update the capture form and optional booking config on a code template. |
Contacts
| Tool | Purpose |
|---|---|
list_contacts | List contacts in the workspace (v1 API). |
get_contact | Get one contact by ID, including the pages made for them. |
upsert_contacts | Create or update contacts by email. |
import_contacts | Bulk import contacts and optionally attach a template so a run is created for them. |
remove_contact | Soft-remove a contact and their pages. |
Runs from automatic templates
| Tool | Purpose |
|---|---|
list_page_runs | List runs made from automatic templates (a template plus the people you chose). |
get_page_run | Get one run's detail and per-contact member rows (page URL, writeback status). |
create_page_run | Create a run from an automatic template and a set of contacts (all active contacts if prospectIds is omitted). |
get_page_run_status | Per-contact status counts for a run. |
generate_page_run | Queue or sync-render one personalized page per contact in the run. Requires an acknowledged estimate matching quantity. |
regenerate_failed_pages | Retry the contacts whose pages failed in a run. |
verify_page_run_ready | Check whether a run's members have URLs and CRM writeback readiness (local helper, no API call). |
Pages
| Tool | Purpose |
|---|---|
get_page | Get page metadata by page ID (v1). |
create_contact_page | One-shot: upsert a contact, research their company, render a personalized page from a template in this workspace, and return the live URL. Wraps POST /api/v1/prospect-pages. Does not email the contact unless sendEmail:true. |
Signals
| Tool | Purpose |
|---|---|
get_signals_summary | Workspace signals summary — pages live, visits, conversions, click-through. |
get_page_signals | Timeline of what one contact did on their page. |
list_hot_signals | Contacts engaging right now, ranked by intent (v1). |
list_conversions | Form submissions and booked meetings (v1). |
Connections
| Tool | Purpose |
|---|---|
list_connections | List outbound connections (CRM and webhook destinations). |
create_connection | Register an outbound connection so page links and signals flow to your CRM or endpoint (v1). |
test_connection | Send a test payload to a connection. |
Workspace setup
| Tool | Purpose |
|---|---|
get_company_profile | Read the company profile — what you sell, who it is for, and your proof. |
update_company_profile | Update the company profile JSON. |
scrape_company_profile | Read a website and fill the company profile from it. |
get_brand | Read the workspace brand — colors, fonts, logo, voice. |
list_domains | List the workspace's custom domains and their status, plus the CNAME target to point at. |
list_team_members | List the people in this workspace and their roles. |
Media
| Tool | Purpose |
|---|---|
upload_media | Ingest media headlessly into the workspace library and return the asset (use asset.id with attach_run_materials). Provide either a url (server fetches it) or a base64 payload with filename/mime. Accepts images, video, and audio (mp3, m4a, wav, webm) up to 100 MB, and documents (pdf, pptx, docx, xlsx, csv, txt, md) up to 50 MB. Docs and audio are read automatically after upload — poll list_media or get_run for extraction_status/understood_summary before relying on the content. |
list_media | List the workspace media library (newest first, max 80). Filter by kind, page with cursor (an ISO created_at), or list only files marked mandatory on templates. |
delete_media | Delete one media asset from the workspace library by ID. |
Discovery (deprecated)
| Tool | Purpose |
|---|---|
create_discovery_session | DEPRECATED — Discovery is now the 'discovery_followup' materials preset. Prefer create_run + attach_run_materials (purpose-run-workflow). Still works: start discovery ingest from transcript/notes, then poll get_discovery_session until interview_ready. |
get_discovery_session | DEPRECATED (prefer get_run). Poll discovery session status, questions, and template_id when completed. |
submit_discovery_answers | DEPRECATED (prefer answer_run_questions). Save seller answers to contact-voiced follow-up questions. |
build_discovery_page | DEPRECATED (prefer generate_run). Start async discovery page build (202). Poll get_discovery_session until status=completed and template_id is set. |
Materials templates
| Tool | Purpose |
|---|---|
propose_materials_template | Stateless AI proposal for a materials template: returns spec, the checklist of what each page needs, elements, quality checks, and openQuestions. Nothing is persisted — edit the result and pass it to create_materials_template. |
create_materials_template | Create a materials template (status drafting) — a template that personalizes from materials you provide per contact. Pass propose:true with just a description to have Crutan draft the spec, or pass a client-edited purposeSpec + inputContract + elementManifest (+ qualityChecks). Set callIntelligence:true for templates built from calls/meetings — it arms call ingestion on every run (digest of pains/objections/questions, plus contact-voiced content_qa questions whose answers are woven into the page). Omit it and a checklist with a recording/transcript entry auto-arms. Returns {purpose, openQuestions, specWarnings?}. |
update_materials_template | Patch a materials template's name, spec, checklist, element manifest, quality checks, status, or callIntelligence. Invalid specs return 422 with issues; non-blocking notes come back as specWarnings. Use to refine a proposal before building, or to arm/disarm call intelligence on an existing template. |
list_materials_templates | List materials templates in the workspace with run counts. Automatic templates are listed by list_templates. |
get_materials_template | Fetch one materials template including what each page needs, its element manifest, and the call_intelligence flag (true = runs digest their call material and ask contact-voiced content_qa questions). |
build_materials_template | Start async build of a materials template's page (202). Costs an AI edit — call estimate_cost(purpose_template_build) first and pass acknowledgedEditCredits. Poll get_template_build by the returned buildId until completed/failed; the template then becomes status=ready. |
get_materials_checklist | Read what each page needs for a materials template — the checklist a run must supply and the facts each element depends on. Also returns callIntelligence: when true, runs digest their call material and ask contact-voiced content_qa questions. Wraps get_materials_template and returns the checklist portion. |
Runs from materials templates
| Tool | Purpose |
|---|---|
create_run | Create a run of a materials template for one contact (status draft). Provide prospectId or an inline recipient (or both). Set consentAttested:true when a recording will be attached. The template must be status=ready. |
attach_run_materials | Attach one checklist entry's material to a run and (re-)trigger ingest (202). Supply exactly one source: mediaId (upload large files with upload_media first), url, content (raw text), or structured (JSON payload). Recordings require consentAttested. Then poll get_run. |
get_run | Fetch a run's full state: status, attached materials, extracted facts, elements (with provenance/validation), questions, what is still missing, callDigest, and the page (url/token) once generated. Materials attached as a doc or audio file carry extraction_status (queued/done/failed/unsupported) and understood_summary from media.ingest — if extraction_status is 'queued', wait and re-poll before assuming the file's content is missing. Each question carries kind: 'fact_gap' questions supply a missing fact and BLOCK the run in needs_input until answered or overridden; 'content_qa' questions are contact-voiced (the buyer asking about your offering) and are OPTIONAL enrichment — they never block generate_run, and answering them only makes the page better. callDigest (present on call-intelligence runs) holds the call summary, pains, objections, questions asked, and commitments. Poll this after attach_run_materials/generate/regenerate. If status=failed, read run.error, fix the materials, and re-call generate (idempotent). |
answer_run_questions | Answer a run's open questions — works for both kinds returned by get_run. kind='fact_gap': answered questions with a target fact become user-override facts and the run advances to ready when nothing is missing. kind='content_qa': the question is voiced as the CONTACT asking about your offering, so answer in the SELLER's voice, as you would reply to them (these answers become page narrative, never a FAQ list); they are optional and never block generation — send status:'skipped' to pass on one. |
override_run_fact | Pin one or more facts to explicit values (user_override). Calc elements recompute synchronously; dependent AI elements are marked stale. The response lists staleElements and any calcFailures. |
generate_run | Generate the run's page (202): calc engine → generative fill → QA gate → render. Requires a satisfied checklist and an acknowledged estimate — call estimate_cost(purpose_run) first. Poll get_run until status=review (or failed). Re-calling after a failure is idempotent (no double-charge once a page exists). |
regenerate_run_element | Regenerate a single AI element on a run in review (202) through the QA gate; the existing page is re-rendered without re-charging. Only ai-source elements can be regenerated — override facts + recompute for calc elements. Poll get_run. |
run_quality_check | Summarize a run's current validation state without regenerating: per-element status/provenance, failed/stale/resolved counts, and what is still missing. Wraps get_run. |
publish_run | Publish a generated run's page (pages→rendered, run→completed). Blocking element failures return 409. Returns the live url and page token. |
fork_run_to_template | Fork a run into a new editable template with its resolved values baked in as locked copy. Returns the new templateId for structural edits in the editor. |
list_runs | List runs of a materials template (newest first). purposeTemplateId is required (runs are listed per template). Pass status to filter client-side. |
estimate_cost first, then pass the exact acknowledgedEstimateCents or acknowledgedDiscoveryCredits to spend tools. Async operations (create_template, build_materials_template, default generate_page_run) return immediately — poll the matching status tool until complete.Deprecated names
The 2.0 vocabulary renamed 38 tools. Every old name is still registered and calls the same handler with the same arguments — the only change is one deprecation line at the top of the result naming its replacement. Old names are supported for at least 90 days.
| Old name | Call this instead |
|---|---|
get_credits | get_usage |
list_prospects | list_contacts |
get_prospect | get_contact |
upsert_prospects | upsert_contacts |
import_prospects | import_contacts |
remove_prospect | remove_contact |
list_batches | list_page_runs |
get_batch | get_page_run |
create_batch | create_page_run |
batch_status | get_page_run_status |
generate_recipient_batch | generate_page_run |
regenerate_failed | regenerate_failed_pages |
verify_batch_ready | verify_page_run_ready |
get_analytics | get_signals_summary |
get_page_detail | get_page_signals |
list_hot_leads | list_hot_signals |
list_connectors | list_connections |
create_webhook | create_connection |
test_connector | test_connection |
get_business_profile | get_company_profile |
update_business_profile | update_company_profile |
scrape_business_context | scrape_company_profile |
get_brand_kit | get_brand |
propose_purpose_template | propose_materials_template |
create_purpose_template | create_materials_template |
update_purpose_template | update_materials_template |
list_purpose_templates | list_materials_templates |
get_purpose_template | get_materials_template |
build_purpose_template | build_materials_template |
get_input_contract | get_materials_checklist |
create_purpose_run | create_run |
attach_run_input | attach_run_materials |
get_purpose_run | get_run |
submit_run_clarifications | answer_run_questions |
generate_purpose_run | generate_run |
publish_run_page | publish_run |
list_purpose_runs | list_runs |
create_prospect_page | create_contact_page |
Notes that save a round-trip
create_templatereturns202 { buildId, status: "building" }— pollget_template_build(orlist_templates) untilstatusiscompletedorfailed.get_page_runreturns each contact'surlandwriteback_status(ok/missing/pending/not_required) — feed those intoverify_page_run_readybefore you send anything.- Runs from materials templates answer questions of two kinds:
fact_gapblocks the run,content_qanever does. Both go back throughanswer_run_questions, in the seller's voice. - Discovery tools still work but are retired — use a materials template with the follow-up preset instead.