MCP Server

Mailsoftly MCP Server
for Email Marketing & Automation

Connect Claude, ChatGPT, Cursor, or any MCP-compatible client to your Mailsoftly account and work with contacts, lists and campaigns in plain language.

https://app.mailsoftly.com/mcp

What is MCP?

Model Context Protocol (MCP) is an open standard that lets AI assistants connect to external tools and data sources. With Mailsoftly's MCP server, an assistant can read your contacts and lists, prepare campaign drafts, and (only if you allow it) send them.

Two ways to connect

Pick one. Most people want the hosted server; the local server exists for developers who prefer to run the process themselves.

Hosted server (recommended)

Paste one URL into your AI client and sign in with your Mailsoftly account. No install, no API key to copy, no key sitting in a config file. Works with Claude and ChatGPT.

Local server (stdio)

Run the open source Node.js server on your own machine and point Claude Desktop, Cursor or VS Code at it. Authenticates with a Mailsoftly API key.

 Hosted serverLocal server (stdio)
SetupPaste a URL, approve the permissionsClone, build, edit a JSON config
Sign-inOAuth, no key to copyMailsoftly API key
Runs onMailsoftly serversYour machine
Tools139 curated toolsOne tool per live API endpoint
Turn it offSettings > Connected appsDelete the key or the config entry

A. Hosted server

Recommended

The hosted server lives at https://app.mailsoftly.com/mcp. It speaks Streamable HTTP and is authorized with OAuth, so the only thing you ever give your AI client is that URL. Your client registers itself, sends you to Mailsoftly to sign in, and receives a token scoped to exactly the permissions you approved.

Connect from Claude

1

Open Settings > Connectors

In Claude, go to Settings, then Connectors, then Add custom connector.

2

Paste the server URL

Give it the name Mailsoftly and the URL https://app.mailsoftly.com/mcp, then confirm.

3

Sign in and approve

Claude opens Mailsoftly in your browser. Sign in, read the list of permissions the app is asking for, and approve. You land back in Claude with the connector ready.

Connect from ChatGPT

1

Open the connector settings

In ChatGPT, open the settings area where connectors and apps are managed and choose to add one by URL.

2

Paste the same server URL

https://app.mailsoftly.com/mcp. ChatGPT walks the same sign-in and consent flow as Claude.

Any other MCP client that supports remote servers with OAuth works the same way: give it the server URL and let it discover the rest.

A Mailsoftly admin has to approve the connection

Connecting a third-party app is an admin action. If you are not an admin on your company, the consent screen tells you so and asks you to have an admin connect the app instead.

How the connection is set up

You do not have to do any of this by hand, but here is what happens behind the URL:

Permissions

An app has to ask for what it needs, and you see the request in plain language before anything is granted. Nothing is granted by default.

PermissionWhat the app can do with it
contacts:readRead your contacts, lists and tags
contacts:writeCreate and update contacts, lists and tags
campaigns:readRead your campaigns and their status
campaigns:draftCreate and edit campaign drafts. Drafts are never delivered on their own
campaigns:sendSend or schedule campaigns to your contacts. Separate opt-in, see below
suppressions:writeAdd addresses to your suppression list so they stop receiving mail
account:readRead your account and company profile
account:writeInvite teammates and change their roles

Sending is a separate opt-in

Sending mail cannot be undone, so approving an app never grants it on its own. When an app asks for campaigns:send, the consent screen shows a separate checkbox that starts unchecked. Leave it off and everything else still works: the app can research, draft and prepare, and you press send yourself.

What the hosted server can do

The hosted server publishes 139 curated tools rather than every API operation, so the assistant picks the right one instead of guessing between near-identical endpoints. Reading tools cover contacts and their activity, lists, tags, segments, suppressions, imports, forms, templates, automations, campaigns with their reports (links, recipients, audience), files, images, content blocks, the brand kit, domain health and the team; writing tools add, import and update contacts, build lists, draft and edit campaigns, upload assets, invite teammates, and, only with the send permission, deliver mail or send a test.

ToolWhat it doesPermission
list_contactsList contactscontacts:read
get_contactGet a single contactcontacts:read
create_contactCreate a new contactcontacts:write
update_contactUpdate an existing contactcontacts:write
create_or_update_contactCreate or update a contactcontacts:write
search_contactsSearch contactscontacts:read
list_contact_listsList all contact listscontacts:read
list_contacts_in_listList contacts in a contact listcontacts:read
create_contact_listCreate a new contact listcontacts:write
add_contact_to_contact_listAdd a single contact to a listcontacts:write
add_contacts_to_contact_listAdd several contacts to a listcontacts:write
list_tagsList all tagscontacts:read
assign_tags_to_contactAssign tags to a contactcontacts:write
get_custom_fieldsList all custom fieldscontacts:read
draft_campaignCreate email draftscampaigns:draft
get_campaign_statusCheck email draft statuscampaigns:read
send_campaignSend an email draft (cannot be undone)campaigns:send
unsubscribe_contactGlobally unsubscribe an email (cannot be undone)suppressions:write
reinstate_contactRemove an address from the suppression list (cannot be undone)suppressions:write
unsubscribe_smsOpt a phone number out of SMS (cannot be undone)suppressions:write
reinstate_smsRemove a phone number from the SMS opt-out list (cannot be undone)suppressions:write
list_email_templatesList email templatescampaigns:read
get_email_templateGet an email templatecampaigns:read
list_sendersList sendersaccount:read
list_email_sender_addressesList sender addressesaccount:read
list_automationsList automationscampaigns:read
get_automationGet an automationcampaigns:read
enroll_contact_in_automationEnrol a contact in an automation (cannot be undone)campaigns:send
list_formsList formscontacts:read
get_formGet a formcontacts:read
get_form_responsesGet form submissionscontacts:read
list_landing_pagesList landing pagescampaigns:read
get_landing_pageGet a landing pagecampaigns:read
list_sms_campaignsList SMS campaignscampaigns:read
get_sms_campaignGet an SMS campaigncampaigns:read
list_segmentsList segmentscontacts:read
list_integrationsList connected integrationsaccount:read
list_webhook_endpointsList webhook endpointsaccount:read
list_signaturesList email signaturesaccount:read
list_suppressionsList suppressed addressescontacts:read
get_accountGet account and sending stateaccount:read
list_team_membersList team membersaccount:read
update_campaignUpdate a campaign draft (cannot be undone)campaigns:draft
list_campaignsList campaignscampaigns:read
get_campaign_statsGet campaign performancecampaigns:read
create_automationCreate an automationcampaigns:draft
update_automation_statusActivate or deactivate an automation (cannot be undone)campaigns:send
schedule_campaignSchedule a campaign (cannot be undone)campaigns:send
delete_contactDelete a contact (cannot be undone)contacts:write
remove_tags_from_contactRemove tags from a contact (cannot be undone)contacts:write
remove_contact_from_listRemove a contact from a list (cannot be undone)contacts:write
rename_contact_listRename a contact listcontacts:write
delete_contact_listDelete a contact list (cannot be undone)contacts:write
create_tagCreate a tagcontacts:write
update_tagRename or recolor a tagcontacts:write
delete_tagDelete a tag (cannot be undone)contacts:write
create_email_templateCreate an email templatecampaigns:draft
update_email_templateUpdate an email template (cannot be undone)campaigns:draft
delete_email_templateDelete an email template (cannot be undone)campaigns:draft
trash_campaignMove a campaign to the trashcampaigns:draft
delete_campaignDelete an unsent campaign permanently (cannot be undone)campaigns:draft
restore_campaignRestore a campaign from the trashcampaigns:draft
delete_automationDelete an automation (cannot be undone)campaigns:draft
create_formCreate a formcontacts:write
update_formUpdate a form (cannot be undone)contacts:write
delete_formDelete a form (cannot be undone)contacts:write
create_landing_pageCreate a landing pagecampaigns:draft
update_landing_pageUpdate a landing page (cannot be undone)campaigns:draft
publish_landing_pagePublish or unpublish a landing page (cannot be undone)campaigns:draft
trash_landing_pageMove a landing page to the trashcampaigns:draft
create_webhook_endpointCreate a webhook endpointcontacts:write
delete_webhook_endpointDelete a webhook endpoint (cannot be undone)contacts:write
update_automationUpdate an automation (cannot be undone)campaigns:draft
start_ab_testStart an A/B subject test (cannot be undone)campaigns:send
list_domainsList sending domainsaccount:read
add_domainAdd a sending domaincampaigns:draft
verify_domainVerify a sending domaincampaigns:draft
remove_domainArchive a sending domain (cannot be undone)campaigns:draft
create_senderCreate a sender addresscampaigns:draft
delete_senderRemove a sender address (cannot be undone)campaigns:draft
list_reply_to_addressesList reply-to addressesaccount:read
create_reply_to_addressAdd a reply-to addresscampaigns:draft
create_segmentCreate a segmentcontacts:write
update_segmentUpdate a segmentcontacts:write
delete_segmentDelete a segment (cannot be undone)contacts:write
refresh_segmentRecalculate a segmentcontacts:write
create_custom_fieldDefine a custom contact fieldcontacts:write
list_email_typesList email typescontacts:read
create_email_typeCreate an email typecontacts:write
create_signatureCreate an email signaturecampaigns:draft
update_signatureUpdate an email signature (cannot be undone)campaigns:draft
delete_signatureDelete an email signature (cannot be undone)campaigns:draft
unschedule_campaignCancel a scheduled sendcampaigns:draft
create_sms_campaignCreate an SMS campaigncampaigns:draft
update_sms_campaignUpdate an SMS campaign (cannot be undone)campaigns:draft
send_sms_campaignSubmit an SMS campaign for sending (cannot be undone)campaigns:send
get_campaign_reportGet a full campaign reportcampaigns:read
get_campaign_linksGet per link clicks for a campaigncampaigns:read
get_campaign_recipientsList the recipients of a campaigncampaigns:read
get_contact_activityGet one contact's activity timelinecontacts:read
add_contact_noteWrite a note on a contactcontacts:write
preview_campaign_audiencePreview who a campaign would go tocampaigns:read
import_contactsImport contacts from a CSVcontacts:write
get_importGet import progresscontacts:read
list_importsList contact importscontacts:read
get_contact_subscriptionsGet a contact's subscriptionscontacts:read
update_contact_subscriptionsChange a contact's subscriptions (cannot be undone)suppressions:write
get_compliance_summaryGet the compliance summary for a regioncontacts:read
get_consent_evidenceList consent evidencecontacts:read
get_opt_outsList opt-out recordscontacts:read
record_consentRecord a consentcontacts:write
get_iys_summaryGet the registry filing statuscontacts:read
get_campaignGet one campaign in fullcampaigns:read
send_test_emailSend a test copy of a campaign (cannot be undone)campaigns:send
duplicate_campaignCopy a campaign into a new draftcampaigns:draft
update_campaign_sharingChange how a campaign is shared on the web (cannot be undone)campaigns:draft
add_campaign_attachmentAttach a file to a draft campaigncampaigns:draft
remove_campaign_attachmentRemove a file from a draft campaign (cannot be undone)campaigns:draft
list_filesList hosted filescampaigns:read
upload_fileUpload a file to the gallerycampaigns:draft
delete_fileRemove a file from the gallery (cannot be undone)campaigns:draft
list_imagesList the image librarycampaigns:read
upload_imageUpload an imagecampaigns:draft
list_custom_blocksList saved content blockscampaigns:read
get_custom_blockGet one content blockcampaigns:read
create_custom_blockSave a content blockcampaigns:draft
update_custom_blockUpdate a content block (cannot be undone)campaigns:draft
delete_custom_blockDelete a content block (cannot be undone)campaigns:draft
get_brand_kitGet the brand kitaccount:read
update_brand_kitUpdate the brand kit (cannot be undone)campaigns:draft
invite_team_memberInvite a teammate (cannot be undone)account:write
list_pending_invitationsList pending invitationsaccount:read
revoke_invitationRevoke a pending invitation (cannot be undone)account:write
update_team_member_roleChange a teammate's roleaccount:write
list_api_keysList the account's API keysaccount:read
list_connected_appsList connected appsaccount:read
list_audit_eventsList the account's audit trailaccount:read
list_domain_health_checksList saved domain health checksaccount:read
run_domain_health_checkRun a domain health checkcampaigns:draft

Bring your own HTML, or use ours

A draft's body comes in two formats. body_format: "content" (the default) takes an HTML fragment and places it inside Mailsoftly's responsive layout, so it renders well on phones without any email-CSS work. body_format: "html" takes a complete HTML email you built yourself and stores and sends it exactly as written. Passing template_id instead starts the draft from a saved template, so an assistant can reuse a design your team already approved. update_campaign edits the draft in place afterwards.

Automations from a sentence

An assistant can build an automation the user describes, as a draft: a trigger (a contact is created or updated, a tag is added, a contact joins a list, a form is submitted, a contact unsubscribes) and ordered steps (send an email from a saved template, add or remove tags, add to or remove from lists, wait, post a webhook, stop). Activating it is a separate call that needs the send permission and a verified account, and a contact can be enrolled in an active automation on request. Plan caps apply exactly as in the builder: a free, unverified account may keep a small number of automations, forms and pages, and the response says so with an upgrade or verify path instead of a bare error.

When a send is held, the answer says why

Sending is gated on purpose: a new account needs a sending channel of its own, and every account's first campaigns pass a short content review. Instead of a bare error, send_campaign, get_account, list_senders and get_campaign_status return a gate object that names the level (account or campaign), the reason, a message the assistant can relay verbatim, and unlock_paths with links into your settings. Account-level gates unlock by connecting a Google Workspace or Microsoft 365 account (verified organizations are trusted automatically), connecting a personal Gmail or Outlook mailbox, or authenticating your own sending domain. Campaign-level gates, such as the content review, have no unlock path: the campaign goes out when it is approved, and no account change speeds that up.

Example prompts

"Which of my lists is the biggest, and how many people are on it?"
Uses list_contact_lists
"Add john@example.com to the Webinar list, and create the list if we do not have one"
Uses search_contacts, create_contact, list_contact_lists, create_contact_list, add_contact_to_contact_list
"Draft next week's newsletter for the Customers list and show it to me before anything goes out"
Uses draft_campaign, then get_campaign_status
"Take maria@example.com off all our mailings, she asked twice"
Uses unsubscribe_contact

Tokens, and turning access off

B. Local server (stdio)

For developers

The local server is a small open source Node.js process that runs on your machine and talks to the Mailsoftly API with your API key. It builds its tools from the published OpenAPI spec, so it exposes one tool per live endpoint rather than the curated 139. Use it when your client cannot connect to a remote MCP server, or when you want to run everything yourself.

Prerequisites

1

Build the MCP server

The server lives in the Mailsoftly repository under mcp-server/.

Terminal
# Navigate to the MCP server directory
cd mcp-server

# Install dependencies
npm install

# Build the server
npm run build
2

Configure your API key

Create a .env file in the mcp-server/ directory with your Mailsoftly API key.

.env
API_KEY_API_KEY=your-mailsoftly-api-key-here
API_BASE_URL=https://app.mailsoftly.com
3

Connect to Claude Desktop

Add the following to your Claude Desktop configuration file.

Claude Desktop - claude_desktop_config.json
{
  "mcpServers": {
    "mailsoftly": {
      "command": "node",
      "args": ["/path/to/mcp-server/build/index.js"],
      "env": {
        "API_KEY_API_KEY": "your-mailsoftly-api-key",
        "API_BASE_URL": "https://app.mailsoftly.com"
      }
    }
  }
}
4

Connect to Cursor / VS Code

Add the same configuration to your Cursor or VS Code MCP settings.

Cursor - .cursor/mcp.json
{
  "mcpServers": {
    "mailsoftly": {
      "command": "node",
      "args": ["/path/to/mcp-server/build/index.js"],
      "env": {
        "API_KEY_API_KEY": "your-mailsoftly-api-key",
        "API_BASE_URL": "https://app.mailsoftly.com"
      }
    }
  }
}
5

Start using it

Restart your AI tool and ask it to work with your account. Try "List my contact lists" or "Create a new contact".

About API keys

API keys are managed in Settings > API Keys. A new key expires one year after it is created, is stored as a hash so the key itself is visible only once at creation, and records when it was last used, which makes an unused key easy to spot and revoke. Keys created before this change keep working exactly as before, with no expiry.

Direct API access

Both servers sit on top of the same REST API: 151 live endpoints covering contacts, lists, tags, segments, custom fields, imports and activity, campaigns with their reports, templates, automations, forms, landing pages, files and images, sending identity, team and account. If you would rather call it directly, or wire it into a platform that speaks OpenAPI instead of MCP, everything is documented at API Documentation with a machine-readable spec at app.mailsoftly.com/developers/openapi.json.

Custom GPTs

Use the OpenAPI spec in a custom GPT's actions to work with campaigns and contacts. Spec: /developers/openapi.json

Google Gemini / Vertex AI

Import the OpenAPI spec as a Vertex AI Extension to manage contacts and campaigns from Gemini.

Function calling anywhere

The same spec drives tool use and function calling in any framework that reads OpenAPI.

For direct API calls the key goes in the Authorization header without a Bearer prefix. OAuth access tokens from the hosted server are sent as Authorization: Bearer <token>.

Security

Hosted server. No key is ever pasted into a client. Access is granted by OAuth after a Mailsoftly admin approves it on a consent screen that lists the permissions in plain language, sending is a separate opt-in, access tokens are short-lived, refresh tokens rotate, and every connection can be revoked from Settings > Connected apps. Each tool call is checked against the permissions that were actually granted, and the connected app is recorded on the contact activity it creates, so you can see later which app did what.

Local server. The process runs on your machine and never sends your key anywhere except app.mailsoftly.com. The key sits in your .env file or MCP config, is stored hashed on our side, and expires a year after you create it.

Either way you are talking only to Mailsoftly: there is no third-party relay in between, and the data an assistant can reach is the data of the one account you connected. See our privacy policy for how account data is handled.

Ready to connect your assistant to your email marketing?

Add https://app.mailsoftly.com/mcp in your AI client and approve the permissions. That is the whole setup.

Sign Up for Free View API Documentation Learn about MCP