A remote Model Context Protocol (MCP) server that exposes the Instantly.ai V2 API as tools, so you can create and manage cold email campaigns from an MCP client like Claude. It runs as a Next.js App Router route and deploys to Vercel.
The server holds your Instantly V2 API key on the server side and exposes a small, safe set of tools over the MCP Streamable HTTP transport. The endpoint is unauthenticated, so keep your Vercel URL private; anyone who knows it can act on your Instantly account. Each tool is a plain stateless request to Instantly, so there is no database or session store.
Campaigns and sequences
| Tool | What it does | Required inputs |
|---|---|---|
list_campaigns |
Lists your campaigns with id, name, and status label. | none (optional limit, search) |
get_campaign |
Returns one campaign's full config: name, status, schedule, and ordered steps with subjects and delays. | campaign_id |
create_campaign |
Creates a campaign with a sending schedule and email sequence steps. | consent_confirmed, name, sequence_steps |
add_sequence_step |
Appends one email step to an existing campaign's sequence. | campaign_id, subject, body |
activate_campaign |
Activates (starts) a campaign, after a consent and readiness check. | consent_confirmed, campaign_id |
pause_campaign |
Pauses an active campaign so it stops sending. | campaign_id |
Analytics
| Tool | What it does | Required inputs |
|---|---|---|
get_campaign_analytics |
Sent, opens, open rate, replies, reply rate, bounces, bounce rate, and opportunities. One campaign or all. | none (optional campaign_id, date range) |
get_campaign_analytics_daily |
Day-by-day sent/opens/replies/bounces for a campaign. | campaign_id |
get_campaign_step_analytics |
Per-step sent, opens, replies, and rates, with each step's subject. | campaign_id |
Leads and accounts
| Tool | What it does | Required inputs |
|---|---|---|
add_leads_to_campaign |
Adds one or more leads to a campaign. | consent_confirmed, campaign_id, leads |
update_lead_status |
Updates a lead's interest status (by email). | lead_email, interest_status |
list_campaign_leads |
Lists leads in a campaign with name, email, step, and interest status. | campaign_id |
list_accounts |
Lists connected sending mailboxes with status, warmup status/score, and daily limit. | none (optional limit) |
create_campaign, add_leads_to_campaign, and activate_campaign can cause real cold email to be sent. They require a consent_confirmed boolean that must be true. Setting it to true asserts that every lead has given consent and has been checked against your suppression and unsubscribe lists, in line with CASL and PIPEDA. If consent_confirmed is false, the tool refuses and returns a clear message before any API call is made. activate_campaign additionally refuses to start a campaign that has no sequence steps or no attached sending account.
| Variable | Purpose |
|---|---|
INSTANTLY_API_KEY |
Your Instantly V2 API key. Create one in Instantly under Settings, Integrations, API. It must be a V2 key (V1 keys do not work). |
Copy .env.example to .env.local and fill in real values. Never commit .env.local.
npm install
cp .env.example .env.local # then edit .env.local with real values
npm run build
npm run start # serves on http://localhost:3000Health check (no auth, reports only whether env vars are present):
curl http://localhost:3000/api/healthSmoke test the MCP endpoint (lists tools and calls list_campaigns):
node scripts/smoke-test.mjsYou can also point the official MCP Inspector at http://localhost:3000/api/mcp using Streamable HTTP. No auth header is required.
-
Push this repo to GitHub (account
Yeti567). -
In Vercel, click New Project and import the repo.
-
Under Settings, Functions, turn on Fluid compute (recommended for this workload).
-
Under Settings, Environment Variables, add the variable for Production (and Preview if you want):
INSTANTLY_API_KEY
-
Deploy. Your MCP endpoint will be:
https://PROJECT.vercel.app/api/mcpReplace
PROJECTwith your Vercel project name. Confirm the deploy withhttps://PROJECT.vercel.app/api/health.
Whenever you change the env vars, redeploy so the new values take effect.
-
In Claude, go to Settings, Connectors, then Add custom connector.
-
Name it (for example
Instantly). -
For the URL, enter your Streamable HTTP endpoint:
https://PROJECT.vercel.app/api/mcp -
For authentication, choose "No authentication" (the endpoint is open). Claude.ai custom connectors do not support static header tokens, only OAuth 2.1.
-
Save and connect. Claude will list the tools above. Ask it to, for example, "list my Instantly campaigns" to confirm it works.
- Base URL:
https://api.instantly.ai/api/v2. Auth header:Authorization: Bearer <INSTANTLY_API_KEY>. add_sequence_stepreads the campaign, appends a step, and saves it back withPATCH /campaigns/{id}, because the V2 API has no dedicated append-step endpoint.update_lead_statusmaps friendly names (Interested, Meeting Booked, Won, and so on) to the Instantlylt_interest_statusvalues.- Timezone is a curated enum, not the full IANA database.
create_campaign's scheduletimezonemust be one of a specific set Instantly accepts (for exampleAmerica/Chicago,America/Detroit,America/Boise,America/Dawson,America/Glace_Bay). Common names outside that set, including most Canadian zones (America/Edmonton,America/Toronto,America/Vancouver) and mostEtc/GMT±Noffsets, are rejected with a genericHTTP 400. The connector handles this for you: it auto-maps common zones to an accepted equivalent with the same offset and DST rules (America/Edmonton → America/Boise,America/Toronto → America/Detroit, and so on), defaults toAmerica/Boise(Mountain), and rejects an unmapped zone with a clear pre-flight error instead of a bare 400. The accepted set and mappings live inlib/instantly.ts(INSTANTLY_TIMEZONES,TIMEZONE_ALIASES); re-verify them if Instantly changes the enum. - Bodyless endpoints (
DELETE,activate,pause) must be sent with no body and noContent-Typeheader; the client (instantlyRequest) only setsContent-Type: application/jsonwhen a body is present.
- Live deployment:
https://instantly-api-two.vercel.app— MCP endpoint athttps://instantly-api-two.vercel.app/api/mcp. - Vercel project:
instantly-api(GitHubYeti567/instantly-api). - Version: server
1.0.0(seeserverInfoin the route). - Data residency: Instantly is US-hosted. Campaign, lead, and analytics data sent through this connector is processed and stored in the United States. Note this for client security questionnaires.
- Key rotation: rotate
INSTANTLY_API_KEYevery 90 days, and re-run the three test cases after any connector change. When Instantly ships a V2 API change, re-verify thecreate_campaignpayload shape and the timezone enum first, since those are the brittle points.
- The Instantly key lives only in the server environment. It is never logged, never returned in a response, and never sent to the client.
- The MCP endpoint is unauthenticated. Keep your Vercel URL private; anyone who knows it can act on your Instantly account through these tools.
- API errors (auth failure, rate limit, not found) are turned into short, actionable messages, never raw stack traces.