MCP tool reference

Arguments and behaviour of every tool on Pairly's CRM MCP server.

Generated from the server's own tools/list response; the stamp under each tool names the api commit it was taken from. Connection requirements are on the MCP server page.

Contacts

upsert_person · Create or update a CRM contact

Create a contact, or fill in gaps on an existing one matched by email. Never overwrites a field a human already set. Args: email (str): The contact's email address. Required. first_name (Optional[str]): First name. last_name (Optional[str]): Last name. phone (Optional[str]): Phone number, any format. company_domain (Optional[str]): Links to an existing company by domain if one is already known; never creates a new company (use upsert_company for that). tags (Optional[list[str]]): Tags to merge onto the contact. Existing tags are kept; nothing is ever removed by omitting a tag here. email_marketing_consent (Optional[EmailMarketingConsent]): Explicit email marketing consent your app captured: {"granted": bool, "granted_at": ISO datetime, "method": str (max 100), "source_url": URL}; only "granted" is required. true records it with this call as evidence, false revokes it; omit it to leave consent unchanged. Returns: dict: {"status": "ok", "person_id": str}

idempotent
ArgumentTypeRequiredDefault
emailstringyes
company_domainstringno
email_marketing_consentEmailMarketingConsentno
first_namestringno
last_namestringno
phonestringno
tagsstring[]no

From tools/list at api 3ab3ffb0, 2026-09-29.

delete_person · Archive a CRM contact

Archive the contact matching this email. Idempotent -- calling this again for an already-archived (or never-existing) address still returns ok. Args: email (str): The contact's email address. Required. Returns: dict: {"status": "ok"}

destructiveidempotent
ArgumentTypeRequiredDefault
emailstringyes

From tools/list at api 3ab3ffb0, 2026-09-29.

Companies

upsert_company · Create or update a CRM company

Create a company, or match an existing one by domain. Args: name (str): The company's name. Required. domain (Optional[str]): The company's domain, used to match an existing company and avoid creating a duplicate. Returns: dict: {"status": "ok", "company_id": str}

idempotent
ArgumentTypeRequiredDefault
namestringyes
domainstringno

From tools/list at api 3ab3ffb0, 2026-09-29.

Account events

record_user_created · Record that a user account was created

Like upsert_person, plus a timestamped lifecycle note ("Account created") visible in Pairly's activity view. Call this instead of upsert_person the moment an account is created in your app. Args: email (str): The new user's email address. Required. first_name (Optional[str]): First name. last_name (Optional[str]): Last name. phone (Optional[str]): Phone number, any format. company_domain (Optional[str]): Links to an existing company by domain. tags (Optional[list[str]]): Tags to merge onto the contact. email_marketing_consent (Optional[EmailMarketingConsent]): Explicit email marketing consent your app captured: {"granted": bool, "granted_at": ISO datetime, "method": str (max 100), "source_url": URL}; only "granted" is required. true records it with this call as evidence, false revokes it; omit it to leave consent unchanged. Returns: dict: {"status": "ok", "person_id": str}

ArgumentTypeRequiredDefault
emailstringyes
company_domainstringno
email_marketing_consentEmailMarketingConsentno
first_namestringno
last_namestringno
phonestringno
tagsstring[]no

From tools/list at api 3ab3ffb0, 2026-09-29.

record_email_confirmed · Record that a user confirmed their email

Mark a user's email as confirmed. If Pairly has never heard of this email, the contact is created on the spot -- there is no need to call record_user_created first. Args: email (str): The confirmed email address. Required. tags (Optional[list[str]]): Tags to merge onto the contact -- typically something like ["email_confirmed"] so the business can build a campaign audience from it. email_marketing_consent (Optional[EmailMarketingConsent]): Explicit email marketing consent your app captured: {"granted": bool, "granted_at": ISO datetime, "method": str (max 100), "source_url": URL}; only "granted" is required. true records it with this call as evidence, false revokes it; omit it to leave consent unchanged. Returns: dict: {"status": "ok", "person_id": str}

ArgumentTypeRequiredDefault
emailstringyes
email_marketing_consentEmailMarketingConsentno
tagsstring[]no

From tools/list at api 3ab3ffb0, 2026-09-29.

record_event · Record a custom lifecycle event

Record any named moment worth logging -- an upgrade, a completed onboarding step, a churn signal -- with your own structured data attached. Pairly stores properties verbatim and does not interpret event_name against a fixed list. Args: email (str): The contact's email address. Required. event_name (str): A short name for the event, e.g. "completed_onboarding". Required. properties (Optional[dict]): Arbitrary structured data about the event. tags (Optional[list[str]]): Tags to merge onto the contact. Returns: dict: {"status": "ok", "person_id": str}

ArgumentTypeRequiredDefault
emailstringyes
event_namestringyes
propertiesobjectno
tagsstring[]no

From tools/list at api 3ab3ffb0, 2026-09-29.

Email

send_transactional_email · Send a transactional email as the business

Send one transactional email (a receipt, a password reset) from the business's verified domain, or from Pairly's address with a "Powered by PairlyHQ" footer when it has none. Transactional only: no marketing. Sent exactly once per idempotency_key -- retry with the same key and the same content. Args: to (str): The recipient's email address. Required. subject (str): 1-300 characters. Required. idempotency_key (str): 1-200 characters, unique per message. Required. html (Optional[str]): HTML body, up to 512,000 characters. One of html/text is required. text (Optional[str]): Plain-text body, up to 512,000 characters. reply_to (Optional[str]): Where replies go. Returns: dict: {"send_id": str, "status": "sent" | "queued" | "suppressed" | "failed", "error"?: "no_verified_sender" | "provider_rejected" | "provider_unavailable" | "outcome_unknown" | "expired" | "send_failed"}

idempotentreaches outside Pairly
ArgumentTypeRequiredDefault
idempotency_keystringyes
subjectstringyes
tostringyes
htmlstringno
reply_tostringno
textstringno

From tools/list at api 3ab3ffb0, 2026-09-29.