ZapSMTP MCP server
OfficialClick on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@ZapSMTP MCP serversend a test email to a simulator address and check delivery status"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ZapSMTP MCP server
The official Model Context Protocol server for ZapSMTP: let Claude, Cursor, VS Code, Codex and any other MCP client send, receive and track email, and manage templates, domains, webhooks and everything else the API does.
The whole API: one tool per API operation (112), generated from the API reference, so a new endpoint becomes a tool with the next release. Clear descriptions and JSON Schemas with every parameter, required field and allowed value.
Safe to hand to an agent: tool annotations (read-only, destructive, idempotent, open-world) for clients that ask before acting,
--read-only, toolsets, a recipient domain allowlist, and sends that never repeat when retried. The API key never reaches the model.Made for agents:
send_test_emailtries any delivery outcome on simulator addresses that never leave ZapSMTP;verify_webhook_signaturechecks webhook requests; lists come back one page at a time with a cursor for the next; errors carry the API's code, message and request id.stdio or Streamable HTTP: run it next to your editor, or serve a team over HTTP where every client brings its own API key.
The docs as resources:
llms.txtand every guide, bundled in the package (nothing is fetched at runtime).
Node.js 18.3 or newer. Built on the official Node.js SDK.
Quick start
Create an API key in the dashboard (a zap_test_… key runs everything without
delivering anything), then add the server to your client.
Claude Code
claude mcp add zapsmtp -e ZAP_API_KEY=zap_... -- npx -y zapsmtp-mcpWith a default sender and only the tools you need:
claude mcp add zapsmtp -e ZAP_API_KEY=zap_... -e ZAP_SENDER="Acme <hello@acme.com>" \
-- npx -y zapsmtp-mcp --toolsets emails,templates,simulatorClaude Desktop
Settings → Developer → Edit Config (claude_desktop_config.json):
{
"mcpServers": {
"zapsmtp": {
"command": "npx",
"args": ["-y", "zapsmtp-mcp"],
"env": { "ZAP_API_KEY": "zap_..." }
}
}
}Cursor
~/.cursor/mcp.json (every project) or .cursor/mcp.json (one project):
{
"mcpServers": {
"zapsmtp": {
"command": "npx",
"args": ["-y", "zapsmtp-mcp"],
"env": { "ZAP_API_KEY": "zap_..." }
}
}
}VS Code (GitHub Copilot agent mode)
.vscode/mcp.json; VS Code asks for the key once and stores it securely:
{
"inputs": [
{ "type": "promptString", "id": "zapsmtp-key", "description": "ZapSMTP API key", "password": true }
],
"servers": {
"zapsmtp": {
"type": "stdio",
"command": "npx",
"args": ["-y", "zapsmtp-mcp"],
"env": { "ZAP_API_KEY": "${input:zapsmtp-key}" }
}
}
}OpenAI Codex
codex mcp add zapsmtp --env ZAP_API_KEY=zap_... -- npx -y zapsmtp-mcpor in ~/.codex/config.toml:
[mcp_servers.zapsmtp]
command = "npx"
args = ["-y", "zapsmtp-mcp"]
env = { ZAP_API_KEY = "zap_..." }Windsurf
~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"zapsmtp": {
"command": "npx",
"args": ["-y", "zapsmtp-mcp"],
"env": { "ZAP_API_KEY": "zap_..." }
}
}
}Zed
settings.json:
{
"context_servers": {
"zapsmtp": {
"source": "custom",
"command": "npx",
"args": ["-y", "zapsmtp-mcp"],
"env": { "ZAP_API_KEY": "zap_..." }
}
}
}Gemini CLI
~/.gemini/settings.json (Gemini CLI expands $ZAP_API_KEY from your environment):
{
"mcpServers": {
"zapsmtp": {
"command": "npx",
"args": ["-y", "zapsmtp-mcp"],
"env": { "ZAP_API_KEY": "$ZAP_API_KEY" }
}
}
}Any other client
Run npx -y zapsmtp-mcp over stdio with ZAP_API_KEY in its environment, or connect to the HTTP
server below.
Related MCP server: packet-pigeon
Streamable HTTP
npx -y zapsmtp-mcp --http # http://127.0.0.1:3000/mcp
npx -y zapsmtp-mcp --http --port 8080 --host 0.0.0.0The HTTP server holds no API key. Every client sends its own as Authorization: Bearer <key>, and each
request gets its own SDK client and MCP server (the server is stateless), so one client's key is never
used for another's calls. A request without a key gets 401.
claude mcp add --transport http zapsmtp http://127.0.0.1:3000/mcp --header "Authorization: Bearer zap_..."{
"mcpServers": {
"zapsmtp": { "url": "http://127.0.0.1:3000/mcp", "headers": { "Authorization": "Bearer zap_..." } }
}
}It listens on
127.0.0.1unless--hostsays otherwise, and while on loopback it refuses requests whoseHostorOriginis not local (DNS rebinding).Beyond your machine, put it behind HTTPS (a reverse proxy): the key travels in a header.
GET /healthanswers{"status": "ok"}for load balancers. Request bodies are limited to 64 MiB.
Options
Flag | Environment | Default | |
|
| API key (stdio). Not used with | |
| off | Serve Streamable HTTP at | |
|
|
| HTTP port |
|
|
| HTTP address |
|
| the defaults below | Toolsets to expose, or |
|
| off | Only tools that change nothing |
|
| From for sends that omit it; without one, sends require | |
|
| Reply-To for sends that omit it | |
|
| Refuse sends to any other domain | |
|
|
| API base URL |
| Print the tools these options expose, and exit | ||
|
Flags win over the environment.
Toolsets
The default toolsets give 76 tools; --read-only leaves 41 of them. Clients that slow down with many
tools do best with just the toolsets they need: --toolsets emails,simulator is 14 tools.
Toolset | Default | Tools | |
| yes | 12 |
|
| yes | 8 |
|
| yes | 3 |
|
| yes | 12 |
|
| yes | 3 |
|
| yes | 11 |
|
| yes | 12 |
|
| yes | 6 |
|
| yes | 2 |
|
| yes | 4 |
|
| yes | 1 |
|
| yes | 2 |
|
| 16 | inbound domains, routes and forward destinations | |
| 5 | click actions | |
| 5 | reusable template modules | |
| 3 | images hosted for templates | |
| 1 | countdown timer images | |
| 4 | create, update and revoke API keys | |
| 3 | SMTP relay credentials | |
| 1 | dedicated sending IPs |
zapsmtp-mcp --list-tools --toolsets all prints every tool. Tool names follow the
Node.js SDK: zap.templates.versions.get is
templates_versions_get.
What the tools do
Arguments are the API's parameters by their API names (
reply_to,scheduled_at), path parameters included (templates_versions_gettakesidandvid). Unknown or missing arguments are refused before anything is sent.Results are the API's JSON. A list returns one page:
{data, has_more, next_cursor}; passnext_cursorback ascursorfor the next page with the same filters. An operation without a body returns{"ok": true}.Errors are tool errors (
isError) with{"error": {status, code, type, message, request_id}}, so the model can correct itself; quote therequest_idto support.Sends (
emails_send,emails_send_batch,emails_receiving_reply) take anidempotency_key; the server makes one when it is omitted, so the SDK's automatic retries never send twice.send_test_emailsends to the simulator address of a scenario (delivered,bounced,full,blocked,delayed,complained,suppressed, or any SMTP reply asbounce+<code>…) and returns the email id with the event to expect.verify_webhook_signaturechecks a webhook request'sZap-Signatureagainst its raw body and the endpoint's secret, locally, and returns its events (several for a batch webhook).
Annotations: tools for GET requests, renders and spam checks are readOnlyHint. Deletes, cancelling a
scheduled email, rotating a webhook secret, removing suppressions and restoring a template version are
destructiveHint. Sends, test webhooks and replays are openWorldHint. Updates, deletes and
verifications are idempotentHint.
Resources
When the package was built with the docs site, resources/list offers
https://zapsmtp.com/llms.txt (an index of the docs) and every guide as Markdown, for example
https://zapsmtp.com/docs/sending.md. They are read from the package; nothing is fetched.
Safety
The key stays out of the conversation. It is read from the environment or a flag and sent only to the API. Tool results and errors are scrubbed of it, and the server writes nothing about it to its logs. Prefer the environment (or VS Code's
promptStringinput) over--key, which shows in process lists.Scope the key. Give the agent a
zap_test_…key while you try things, and a key restricted to sending, one domain or one stream (api_keys_create) for production use.Limit what the agent can do:
--read-only,--toolsets, and--allowed-recipient-domains acme.com,example.org, which refuses sends to any other domain (and its subdomains) before any request is made. Under the allowlist,emails_receiving_replymust name its recipients intoand cannot usereply_all, since the original sender's domain is unknown until the API answers.send_test_emailalways sends to the simulator.Review before approving: destructive tools are annotated, so clients that ask before running a tool (Claude Code, Claude Desktop, VS Code, Cursor) show which calls change or delete things.
HTTP: loopback by default with
Host/Originchecks; use HTTPS beyond your machine.
Embedding
import { API, buildTools, createServer, makeClient } from 'zapsmtp-mcp';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
const tools = buildTools(API, { toolsets: ['emails', 'simulator'], sender: 'hello@acme.com' });
const server = createServer({ client: makeClient({ apiKey: process.env.ZAP_API_KEY! }), tools });
await server.connect(new StdioServerTransport());Development
cd sdks/node && npm ci && npm run build # the SDK this package uses
cd ../mcp && npm ci
npm run generate # src/generated/ by sdks/codegen (emit/mcp.mjs); the build fails when it is stale
npm test # every tool against the conformance server, HTTP auth, safety options
npm run coverage # 100% of the hand-written code
npm run build # the codegen check, dist/, and docs/ from landing/zapsmtp-site/dist when it is built
../live/run.sh mcp # against the dev APIsrc/generated/ is generated by sdks/codegen (emit/mcp.mjs; the code calling the SDK comes from
codegen/templates/tools-model.ts, shared with the CLI); src/catalog.ts holds the hand-written choices (toolsets,
annotations, descriptions).
This server cannot be deployed
Maintenance
Related MCP Connectors
Email infrastructure for AI agents — send, receive, search, and reply to email over MCP.
- EusendOAuthdev.eusend
Send transactional email and manage domains, audiences, and broadcasts from any MCP client.
Hosted email for AI agents: create inboxes, send, receive, and reply over MCP with scoped API keys
Email inboxes for AI agents: send, receive, reply, search, and manage threaded email over MCP.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI models to send emails, manage contacts, and interact with SendGrid's email platform via MCP.1MIT
- AlicenseNot gradedqualityBmaintenanceEmail capabilities for AI agents to receive, read, reply, and send through MCP.1 npmISC
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to read, search, send, manage, schedule, and analyze email across multiple IMAP/SMTP accounts through MCP, including drafts and templates, provider-aware labels, bulk operations, real-time IMAP IDLE watching with AI triage, verification-code capture, calendar extraction, and analytics.21 npmISC
- AlicenseNot gradedqualityAmaintenanceEnables AI assistants to search, read, send, reply to, forward, organize, and bulk-delete email across multiple IMAP/SMTP mailboxes, with AES-256-encrypted credential storage, connection pooling, and folder management. Supports 15+ pre-configured providers and simultaneous multi-account access from any MCP client.929 npmMIT