@postilon/mcp
Official# @postilon/mcp
[Model Context Protocol](https://modelcontextprotocol.io) server for the [Postilon](https://postilon.com) transactional email API. It lets AI assistants such as Claude Desktop, Claude Code and Cursor send email, follow its delivery, read inbound email and manage templates and domains in your Postilon workspace.
Full documentation: [postilon.com/docs/mcp](https://postilon.com/docs/mcp). Needs Node.js 18 or later.
## Get an API key
In the Postilon dashboard, open **API Keys** and create a key.
- Start with a `ps_test_…` key: emails are accepted and reported like real ones, but nothing is delivered and no credits are used.
- A `ps_live_…` key sends real mail from a [verified domain](https://postilon.com/docs/domains). Your assistant can then send email to anyone, so review what it sends.
- A key with **sending access** can only use the email tools; the domain, inbound and template tools need **full access**.
## Configuration
| Environment variable | Description |
| --- | --- |
| `POSTILON_API_KEY` | Your API key (required). |
| `POSTILON_FROM` | Sender used when the assistant gives none, such as `Acme <hello@acme.com>`. |
| `POSTILON_REPLY_TO` | Reply-to address used when the assistant gives none. |
| `POSTILON_BASE_URL` | API base URL; defaults to `https://api.postilon.com`. |
### Claude Desktop
Open **Settings → Developer → Edit Config** and add:
```json
{
"mcpServers": {
"postilon": {
"command": "npx",
"args": ["-y", "@postilon/mcp"],
"env": {
"POSTILON_API_KEY": "ps_test_…",
"POSTILON_FROM": "Acme <hello@acme.com>"
}
}
}
}
```
Restart Claude Desktop to load it.
### Cursor
Add the same entry to `~/.cursor/mcp.json` (every project) or `.cursor/mcp.json` (one project):
```json
{
"mcpServers": {
"postilon": {
"command": "npx",
"args": ["-y", "@postilon/mcp"],
"env": {
"POSTILON_API_KEY": "ps_test_…",
"POSTILON_FROM": "Acme <hello@acme.com>"
}
}
}
}
```
### Claude Code
```bash
claude mcp add postilon -e POSTILON_API_KEY=ps_test_… -e POSTILON_FROM="Acme <hello@acme.com>" -- npx -y @postilon/mcp
```
## Tools
| Tool | Description |
| --- | --- |
| `send_email` | Send one email: HTML and/or text, or a template with variables; cc, bcc, reply-to, scheduling and an idempotency key. |
| `send_batch` | Send up to 100 emails in one request, each with its own recipient and variables. |
| `get_email` | Get an email with its status and events. |
| `list_emails` | List emails, filtered by status, search text, source or age. |
| `cancel_email` | Cancel a queued or scheduled email. |
| `list_domains` | List sending domains and their verification status. |
| `get_domain` | Get a domain with its DNS records. |
| `add_domain` | Add a sending domain. |
| `verify_domain` | Check a domain's DNS records now. |
| `list_inbound` | List received email. |
| `get_inbound` | Get a received email with its headers and authentication results. |
| `list_templates` | List templates. |
| `get_template` | Get a template. |
| `create_template` | Create a template with `{{ variable }}` placeholders. |
| `update_template` | Change a template. |
| `delete_template` | Delete a template. |
Lists return 20 items unless the assistant asks for more. Every tool answers with the API's JSON response, or with the API's error (`403 domain_not_verified: …`) so the assistant can explain or fix it.
## Example prompts
> Send jane@example.com a short note saying the invoice is attached to her account, and tell me when it's delivered.
> Did any email bounce in the last 7 days? Show me who and why.
> Create a welcome template with a first_name variable, then send it to these three addresses.
> Add the domain mail.acme.com and tell me which DNS records to create.
## Use it in your own server
The package also exports `createServer`, which builds the MCP server around a client of [`@postilon/node`](https://www.npmjs.com/package/@postilon/node):
```ts
import { createServer } from "@postilon/mcp";
import { Postilon } from "@postilon/node";
const server = createServer(new Postilon(process.env.POSTILON_API_KEY!), { defaultFrom: "hello@acme.com" });
// await server.connect(transport);
```
## License
MIT
TDQS
Scored across 16 tools
Each tool targets a distinct resource+action pair, and the resource is explicit in the name (email, inbound, template, domain). Overlaps like send_email vs send_batch or get_email vs get_inbound are disambiguated by the descriptions (single vs up to 100 recipients, sent vs received). No two tools appear to do the same thing.
All 16 tools follow a strict snake_case verb_noun pattern (list_/get_/create_/update_/delete_/send_/cancel_/verify_ + resource). The only slight oddity is send_batch naming the shape rather than the object, but it still reads naturally alongside send_email.
16 tools sits at the upper end of comfortable but is justified by four distinct sub-domains (templates, sending, sent-mail inspection, domains, inbound). Each tool maps to a real workflow step, with no filler. Just slightly heavier than ideal.
Templates have full CRUD, emails cover send/get/list/cancel, and domains cover add/list/get/verify. The notable gap is domain lifecycle teardown (no delete_domain or update_domain), and inbound/email data is read-only, but core transactional workflows have no dead ends.