personalize

Your Gmail sends it. Your inbox owns the reply.

An MCP server for cohort email outreach. Claude drafts the copy. You approve from iMessage. Gmail sends from your address — not a vendor's.

Join the beta

We're onboarding operators in small batches. Tell us a bit and we'll send your invite.

Monday, 9am

You have 200 names in a Sheet and a deadline.

Last cohort, you spent four hours on subject lines. You wrote 47 personalized intros, missed two unsubscribes from last quarter, and emailed someone who'd already replied. Then you did it again the next month.

Tuesday, 9:01am

Tell your agent what cohort, what stages, who's in.

  1. Install the MCP server. npm install -g @capitalthought/personalize-mcp
  2. Get an operator token. Mint a refresh token tied to your Workspace identity.
  3. Ask Claude: "Draft a 3-stage sequence to my founder cohort, pilot 20, send Tuesday." Claude reads the Sheet, drafts the copy, picks the pilot, surfaces the gaps.

The gates

What you'd catch on a good day. The Worker catches every day.

The approval header is server-enforced and tiered by recipient count. The Worker rejects launches without the right header — even from us.

The reward

You approve from your phone. Gmail sends from you. Replies land in your thread.

One tap on iMessage. The thread lives in your own Sent folder. Replies hit your own inbox. The cohort tracks itself; no dashboard to check, no second tool to learn.

Reading this as an agent? You are the mentor for the next cohort. Install the MCP server, get the operator's JWT, read /agents.md for the contract, then call any of the 55 personalize_* tools. Approval gates are server-enforced — try things, the Worker is the authority.

55 verb-first MCP tools — click to expand
ToolPurposeAuth
personalize_create_sequence Draft a multi-stage email sequence under an operator. Stage triggers: 'always', 'no_reply', 'no_engagement'. JWT
personalize_add_recipients Attach recipients; suppression auto-applied. JWT
personalize_import_recipients Bulk-import recipients from a CSV blob (e.g., fetched from a Sheet). Header row required; 'email' column mandatory. JWT
personalize_launch Launch a sequence; >50 recipients require approval header. Self-test gate (default-on) renders stage 1 to owner_email before fan-out. JWT + approval
personalize_approve_self_test Approve the self-test send and fan out the rest cohort. Idempotent. JWT
personalize_update_stage Edit a stage subject or body before send. JWT
personalize_preflight_check Run deliverability pre-flight (DNS, headers, content, volume) without launching. JWT
personalize_link_check Verify every <a href> resolves AND click tracking round-trips correctly (catches HSN-2026-class encoding regressions before launch). JWT
personalize_pause Halt an in-flight sequence. Pass terminal=true to archive it (terminal state) instead. JWT
personalize_resume Resume a paused sequence (re-runs the approval gate). JWT
personalize_get_status Recipient counts, send counts, engagement, replies. JWT
personalize_list_sequences Filterable list of an operator's sequences. JWT
personalize_create_snippet Save a versioned shared template (set parent_id to revise). JWT
personalize_search_snippets Search the shared snippet library by name, owner, category. JWT
personalize_create_team_prompt Create a team voice/style prompt — markdown the agent reads when composing on behalf of a team. Admin only. JWT + admin
personalize_list_team_prompts List active team prompts. Read these BEFORE composing a stage on behalf of a team. JWT
personalize_get_team_prompt Get one team prompt by slug. JWT
personalize_suppress Add an email or domain to the do-not-contact list. JWT
personalize_update_operator Update display_name, physical_address, or admin caps. JWT
personalize_request_approval Mint a token for >1000-recipient launches. JWT
personalize_audit Query the audit_log scoped to your own actor rows. JWT
personalize_get_recipient Read a recipient's state, send history, and engagement events. JWT
personalize_get_replies List reply + bounce events on a sequence with counts. JWT
personalize_estimate Pre-launch sizing: caps, cap room, projected duration. JWT
personalize_preview Render stage 1 subject + body for a recipient. JWT
personalize_what_now Operator state-machine — tells the agent the next onboarding action ('needs_address', 'ready_for_send_test', 'fully_onboarded', etc.). Surfaces a quickstart_url for the first-sequence walkthrough. JWT
personalize_send_test 1-stage smoke test send to a configured test recipient — verifies auth + send pipeline end-to-end. JWT
personalize_send_test_sequence Render a stage of an existing sequence against a recipient's variables and email the preview to the operator's own inbox. Subject prefixed [test]. Defaults: stage 1, newest recipient. JWT
personalize_feedback File a feedback report; backs the agent-feedback signed-URL pipeline. JWT
personalize_cluster_replies Reply Triage: read a reply pile + cluster into emergent groups (read-only, no drafts/sends). Source = sequence_id | gmail_query | thread_ids; body-read sources need the internal read flag. JWT
personalize_draft_group_replies Reply Triage: execute the operator's direction for a group — reply (draft, template-only by default) / escalate / skip / suppress. Drafts only; safety-gated; no send. JWT
personalize_approve_reply_batch Reply Triage: approve a drafted reply batch (batch_id + token) → cron sends threaded, commercial-only footer + suppression, paced. The recorded human approval; no auto-send. JWT
personalize_get_reply_batch Reply Triage: read-only batch status — per-draft state, recipient, is_commercial, grounding_ok, confidence, body. JWT
personalize_suggest_reply_sources Reply Triage discovery: rank reply piles worth triaging (sequences scope works for all; sent_fanouts/recent need the read flag). Read-only, no bodies/LLM; each suggestion pipes into cluster_replies. JWT
personalize_list_waitlist Admin: list public beta-waitlist signups (landing page) to promote into the ≤100 Google test-user slots. Filter by status. JWT
personalize_invite_waitlist Admin: mark a waitlist signup invited (after adding their email to the OAuth test-user list). JWT
personalize_set_subject_variants Register 2-4 stage-1 subject A/B variants. Sequence must be draft + tracking_enabled. Recipients get assigned uniformly at random. JWT
personalize_promote_variant Pick the winning A/B subject. Subsequent stages render the winner's subject for all recipients. Sequence must be active|paused|completed. JWT
personalize_extend_pilot Extend an in-flight A/B pilot's decision deadline by additional_hours. Idempotent (additive). Used to buy more data before the 72h escalation ladder fires the relaxed-rule fallback or escalates to manual. JWT
personalize_get_perspective_review Read a perspective-review record (AF4). Triggered on operator's first launch above 10 recipients. V2 observe-only (status='skipped'); V3 will dispatch multipov review with 3 personas. JWT
personalize_create_engagement_webhook Register an engagement webhook on a sequence (CRM/Asana V1). Admin-only. Returns signing_secret + key_id once. Domain allowlist enforced. Justification required + audited. JWT + admin
personalize_list_engagement_webhooks List engagement webhooks on a sequence. Admin-only. No secrets in response. JWT + admin
personalize_disable_engagement_webhook Soft-disable an engagement webhook. Admin-only. JWT + admin
personalize_rotate_engagement_webhook_secret Rotate signing_secret + bump key_id. Admin-only. Returns new secret once. Sender dual-signs (current + previous) for a 7-day grace window so receivers update on their own schedule. JWT + admin
personalize_register_recipient_phone Capture phone consent for iMessage outbound on a recipient (Josh-only v1). Stores phone + consent_method + verbatim consent_disclosure_text + consent_at; audit-logs hashed phone. JWT (Josh-only)
personalize_revoke_recipient_phone Revoke iMessage phone consent (operator-side STOP). Flips phone_consent_for_imessage=false, inserts an imessage suppression row, audit-logs the revoke. Josh-only. JWT (Josh-only)
personalize_get_recipient_phone Read a recipient's phone-consent state + iMessage send history (last_imessage_sent_at, total_imessage_sent). Josh-only. JWT (Josh-only)
personalize_list_imessage_outbound List iMessage outbound rows for a sequence (queued/dispatching/sent/delivered/read/failed/superseded). Phone numbers in the response are SHA-256-hashed per AGENTS.md §7. Josh-only. JWT (Josh-only)
personalize_list_address_proposals List address-change proposals scoped to the calling operator (AUR5). Default status=pending. Each row is the platform's suggestion to swap a recipient's email after a bounce / auto-reply / FBL named a new address. JWT
personalize_approve_address_proposal Approve a pending address-change proposal — atomically swaps recipients.email, inserts a recipient_address_history row, audit-logs. Optional new_email override (required when the proposal has no extracted address, e.g., AUR4 blind-bounce). JWT
personalize_reject_address_proposal Reject a pending address-change proposal — leaves recipients.email untouched, audit-logs with the reason. Reason 5-500 chars; feeds AUR8 detection-quality scoring. JWT
personalize_admin_list_operators List tenant operator roster (Phase 8 admin parity for /admin/operators). Admin-only. Optional `search` substring filter on email. JWT + admin
personalize_admin_queue_snapshot Tenant-wide send-queue health (Phase 8 admin parity for /admin/queue-health). Returns queue depth, per-operator breaker state, cron freshness, tenant cap headroom. Admin-only. JWT + admin
personalize_admin_audit_search Admin-flavored convenience wrap over /api/audit (Phase 8 admin parity for /admin/audit). Filters: actor, action, since, before-cursor, limit (default 100, max 500). Payloads may contain hashed PII per §7. JWT + admin
personalize_health Public health probe (returns ok + iso timestamp). none