MCP server
Connect any MCP client (Claude Code, Claude Desktop, Cursor) to Zexr and use your data and workflows as tools. Sign in with OAuth, or scope a static API key.
Zexr speaks the Model Context Protocol. Point any MCP client at Zexr's server and it can search contacts, check campaigns, read your inbox, draft replies, and create draft campaigns and automations, all scoped to what you grant it.
- URL:
https://api.zexr.app/v1/mcp - Transport: streamable HTTP
- Auth: an OAuth 2.1 access token (browser sign-in) or a static API key (bearer header).
There are two ways to connect. OAuth is the one-command path: you run a single add command, approve access in the browser, and the client holds a short-lived token it can refresh. An API key is the static path: you mint a key and paste it into the client config. Both reach the exact same tools, gated the exact same way.
Connect with OAuth
This is the recommended path. You do not paste a key anywhere: the client discovers Zexr's authorization server, opens a browser for you to sign in and approve the scopes, and stores the resulting token itself.
Claude Code
claude mcp add --transport http zexr https://api.zexr.app/v1/mcpThen run /mcp inside Claude Code and pick Authenticate. A browser opens, you sign in to Zexr, approve the requested scopes, and you are connected. No header, no key.
Claude Desktop and Cursor
Add the server with just its URL, and the client runs the OAuth flow on first use:
{
"mcpServers": {
"zexr": { "type": "http", "url": "https://api.zexr.app/v1/mcp" }
}
}What you are approving
The consent screen marks a self-registered client as Not affiliated with Zexr, names where approving sends access, and shows exactly which scopes the client will get: the ones it asks for that your role in the workspace covers, so a connected client never does more than you could yourself. Sending real mail is never one of them: SEND_CAMPAIGNS and API-key management are excluded from OAuth-connected MCP clients by design, and the assistant only ever drafts. You can revoke a connected client at any time from your dashboard under connected apps.
Connect with an API key
Prefer a static, long-lived credential (CI, a shared script, a client that does not implement OAuth)? Mint an API key and send it as a bearer token:
Authorization: Bearer zexr_...Scope your key
Create a dedicated API key for each MCP client and grant it only the scopes it needs (see Permissions). Grant the read/write scopes for the data you want the client to reach, and AI_AGENT if it should search the web or read your playbooks.
Claude Code
claude mcp add --transport http zexr https://api.zexr.app/v1/mcp \
--header "Authorization: Bearer zexr_..."Claude Desktop
Add to your claude_desktop_config.json:
{
"mcpServers": {
"zexr": {
"type": "http",
"url": "https://api.zexr.app/v1/mcp",
"headers": { "Authorization": "Bearer zexr_..." }
}
}
}Cursor
Add to .cursor/mcp.json:
{
"mcpServers": {
"zexr": {
"url": "https://api.zexr.app/v1/mcp",
"headers": { "Authorization": "Bearer zexr_..." }
}
}
}What is exposed
The server exposes exactly the tools your credential is allowed to use, whether that credential is an OAuth token or an API key. Each tool checks its own scope, and an OAuth token or API key also needs its member to hold the matching organization permission today. A credential with only read scopes sees only the read tools; one with write scopes sees those too, so an MCP client acts with precisely the permissions you granted, and nothing more.
This is a subset of what the in-product assistant can do. Two categories are dashboard-only and never reachable by an API key or OAuth token: sending email (send_reply, compose_email), and workspace governance (team, workspace settings, and billing). Those routes are session-only and have no API scope to grant, so they never appear over MCP.
Every tool is gated by its API permission. tools/list returns only the tools your mask allows. Sending-class tools (anything that transmits a message to a recipient) are never exposed over MCP regardless of scope; over MCP the assistant only produces drafts (draft_reply).
| Tool | Does | Required scope |
|---|---|---|
search_contacts | Find contacts by text | READ_CONTACTS |
get_contact | Read one contact | READ_CONTACTS |
update_contact_fields | Update contact fields | WRITE_CONTACTS |
add_tag / remove_tag | Add or remove a label on a contact | WRITE_CONTACTS |
list_campaigns | List campaigns | READ_CAMPAIGNS |
get_campaign_stats | Campaign stats, all time or for the emails sent from from to to | READ_ANALYTICS |
list_campaign_leads | A campaign's leads with derived status + totals | READ_CONTACTS |
create_campaign_draft | Create a draft campaign | WRITE_CAMPAIGNS |
set_campaign_status | Start or stop a campaign | SEND_CAMPAIGNS |
set_lead_hold | Hold or resume one contact's flow in one campaign, without unsubscribing them | WRITE_CAMPAIGNS |
get_dashboard_analytics | Sending stats for a period, org-wide or for chosen campaigns and campaign folders | READ_ANALYTICS |
list_mailboxes | Sender mailboxes with health + warmup state | READ_ANALYTICS |
list_placement_tests / get_placement_test | Inbox placement tests and where each copy landed | READ_ANALYTICS |
run_placement_test | Send a step or template to the seed inboxes from one mailbox | SEND_CAMPAIGNS |
list_placement_batches / get_placement_batch | Placement batches, their progress, and placement by sending domain, sending provider and recipient provider | READ_ANALYTICS |
run_placement_batch | Run the same placement test from a campaign's senders or the whole workspace, optionally sampled. Signed-in members only: an API key starts a batch with POST /placement/batches, which applies the key's mailbox limits | SEND_CAMPAIGNS |
add_contact / delete_contact | Create or delete a contact | WRITE_CONTACTS |
bulk_edit_contacts | Label or subscribe many contacts at once | BULK_CONTACTS |
get_contact_timeline / get_contact_sent_emails | Read a contact's activity and sent mail | READ_CONTACTS |
list_segments / get_segment / list_segment_fields | Read saved audiences, and the fields a condition can name | READ_CONTACTS |
preview_segment | Count what a set of conditions would match, saving nothing | READ_CONTACTS |
create_segment / update_segment / delete_segment | Manage saved audiences | WRITE_CONTACTS |
set_segment_members | Pin contacts into or out of a segment | WRITE_CONTACTS |
list_campaign_segments | Read the segments feeding a campaign | READ_CAMPAIGNS |
set_campaign_segments / add_segment_to_campaign | Link an audience to a campaign, or enrol its members once | WRITE_CAMPAIGNS |
list_forms / get_form / list_form_submissions / get_form_stats | Read hosted forms, their submissions, and their funnel | READ_CONTACTS |
create_form / update_form / delete_form | Manage hosted forms | WRITE_CONTACTS |
mint_form_link | Get one contact's personalized form URL | WRITE_CONTACTS |
get_campaign_forms | How a campaign's forms performed for its recipients | READ_CAMPAIGNS |
list_suppressions | Read the do-not-contact list, and why each entry is on it | READ_CONTACTS |
add_suppressions / remove_suppression | Suppress an address or domain, or lift one | WRITE_CONTACTS |
list_pipelines / list_deals / get_deal / list_deals_by_contact | Read CRM pipelines and deals | READ_CRM |
create_task / create_deal | Create CRM records | WRITE_CRM |
update_deal / move_deal_stage / delete_deal | Edit, move, or delete a deal | WRITE_CRM |
list_tasks / list_task_types | Read CRM tasks and task types | READ_CRM |
update_task / complete_task / delete_task | Edit, complete, or delete a task | WRITE_CRM |
add_contact_note / list_contact_notes | Add or read contact notes | WRITE_CRM / READ_CRM |
update_contact_note / delete_contact_note | Edit or delete a note | WRITE_CRM |
create_pipeline / update_pipeline / delete_pipeline | Manage CRM pipelines | WRITE_CRM |
create_pipeline_stage / update_pipeline_stage / delete_pipeline_stage | Manage pipeline stages | WRITE_CRM |
get_campaign / list_campaign_senders / get_campaign_logs | Read a campaign's config, senders, and logs | READ_CAMPAIGNS |
update_campaign / delete_campaign | Edit or delete a campaign | WRITE_CAMPAIGNS |
set_campaign_senders / verify_campaign_tracking_domain | Set senders, verify tracking domain | WRITE_CAMPAIGNS |
list_campaign_steps | Read a campaign's sequence steps | READ_CAMPAIGNS |
add_campaign_step / update_campaign_step / delete_campaign_step | Edit a campaign's sequence steps | WRITE_CAMPAIGNS |
list_threads / get_thread | Read the unified inbox | READ_UNIBOX |
draft_reply | Draft a reply (never sends) | READ_UNIBOX |
list_scheduled_sends | List queued outbound messages | READ_UNIBOX |
mark_thread_seen / set_thread_labels | Mark seen, set thread labels | WRITE_UNIBOX |
snooze_thread / unsnooze_thread / cancel_scheduled_send | Snooze a thread, cancel a queued send | WRITE_UNIBOX |
get_mailbox / get_warmup_ban_status | Read a mailbox's config and warmup standing | READ_EMAILS |
update_mailbox / set_mailbox_warmup / set_mailbox_send_hold / set_mailbox_tracking_domain | Edit mailbox settings, warmup, the campaign hold, tracking domain | WRITE_EMAILS |
submit_warmup_appeal / disconnect_mailbox | Appeal a warmup ban, disconnect a mailbox | WRITE_EMAILS |
create_automation_draft / list_automations / get_automation | Read automations, create a disabled draft | INTEGRATIONS |
update_automation / set_automation_enabled / delete_automation | Edit, enable, or delete an automation | INTEGRATIONS |
list_api_keys / create_api_key / update_api_key / revoke_api_key | Manage API keys | API_KEYS |
list_webhooks / list_webhook_deliveries | Read webhook endpoints and deliveries | WEBHOOKS |
create_webhook / update_webhook / delete_webhook / rotate_webhook_secret / verify_webhook | Manage webhook endpoints | WEBHOOKS |
search_web / fetch_url | Search and read public pages | AI_AGENT |
load_skill | Read one of your playbooks | AI_AGENT |
Two form surfaces are deliberately absent: brand-asset uploads (logo, cover, background) are multipart images with dimension and MIME limits that a tool call cannot express, and the custom forms domain is workspace-wide branding behind a DNS check, so it lives in settings rather than in a tool.
Rate limits apply to MCP calls exactly as they do to the rest of the API (per-key for API keys, per-user for OAuth tokens). SEND_CAMPAIGNS appears in the table because set_campaign_status and the placement tools need it. A self-registered MCP client is never granted it, so only an API key or app that holds the scope can start or stop a campaign over MCP. Tools that send a message to a recipient (send_reply, compose_email) are never exposed over the MCP transport regardless of scope.
Tools that return a secret (create_webhook and rotate_webhook_secret) return it to the MCP client that called them, which is the caller asking for it. The in-product assistant never sees these values.
How OAuth discovery works
The one-command flow is standard MCP authorization, so any spec-compliant client works without Zexr-specific setup. On a request with no valid token, /v1/mcp returns 401 with a WWW-Authenticate header pointing at the protected-resource metadata. The client then walks:
GET /.well-known/oauth-protected-resource: the resource and its authorization server (RFC 9728).GET /.well-known/oauth-authorization-server: the authorize, token, and registration endpoints (RFC 8414).POST /v1/oauth/register: dynamic client registration, so the client mints a public (PKCE)client_idwith no manual app setup (RFC 7591).- Authorization code with PKCE (S256) in the browser, then
POST /v1/oauth/tokenfor a short-lived access token and a rotating refresh token.
The same discovery drives Zexr's OAuth server for any client. See the OAuth 2.1 page for the full authorization-server reference.
See also
- Agent tools (REST) for the same registry over plain HTTP, for Hermes and OpenAI-style function-calling agents that do not speak MCP.
- OAuth 2.1 for the authorization-server endpoints, scopes, and dynamic registration.
- Authentication for how API keys and OAuth tokens work.
- Permissions for the full scope list.
- To connect Zexr to external MCP servers instead (the other direction), see the Connect MCP tools guide.
Endpoint scope map
Every endpoint, which auth types it accepts, and which permission it requires.
Agent tools (REST)
Use Zexr's AI tool registry from any function-calling agent, no MCP client required. List the tools your credentials allow, export OpenAI and Hermes format manifests, and execute tools over plain HTTP.