Resend Blade MCP
Security-first MCP server for Resend transactional email — send, manage contacts, broadcasts, templates, domains, and webhooks with programmatic safety controls.
Built on FastMCP 2.0 and httpx. Designed for agentic workflows where LLMs operate autonomously.
Why not the official Resend MCP?
The official resend-mcp covers the full API but was designed for human-supervised chat, not autonomous agents. In agentic contexts, its security model breaks down:
| Capability | resend-blade-mcp | Official resend-mcp | Generic vendor MCPs |
|---|---|---|---|
| Write gating | Programmatic env var gate | Prompt engineering only | Usually none |
| Filesystem access | None — base64/URL only | filePath reads any file |
Varies |
| API key management | Excluded entirely | Full CRUD exposed to agent | Often exposed |
| Credential scrubbing | All error paths scrubbed | Not implemented | Rarely |
| Tool count | 28 focused | 60+ (context window bloat) | Varies |
| Output format | Pipe-delimited, null omission | Raw JSON responses | Raw JSON |
| HTTP transport auth | Built-in bearer middleware | Per-session key only | Rarely |
| Idempotency | Native Idempotency-Key header |
Not exposed as parameter | Rarely |
| Rate limit handling | Typed RateLimitError with retry-after |
Raw error passthrough | Varies |
The filesystem problem
The official MCP accepts filePath in attachments, calling fs.readFile() with no path validation. An autonomous agent could read /etc/passwd, ~/.ssh/id_rsa, or any file on the host and attach it to an email sent to any address. resend-blade-mcp rejects all filesystem paths — only base64 content and HTTPS URLs are permitted.
The API key problem
The official MCP exposes create-api-key and remove-api-key tools. An agent could create a full-access API key and exfiltrate it, or delete existing keys to disrupt services. resend-blade-mcp excludes API key management entirely — these are privileged operations that belong out-of-band.
Features
- 28 tools across 8 categories: sending, contacts, segments, broadcasts, templates, domains, webhooks, logs
- Write-gate — all mutating operations disabled by default (
RESEND_WRITE_ENABLED=trueto enable) - No filesystem access — attachments via base64 content or HTTPS URL only
- No API key CRUD — excluded by design, not just gated
- Credential scrubbing —
re_*API keys stripped from all error output - Token-efficient — pipe-delimited output, null-field omission, capped lists
- Idempotent sends — native
Idempotency-Keysupport prevents duplicate emails on retry - Webhook management — create, list, delete webhook endpoints for event-driven architectures
- Sidereal Marketplace — native plugin manifest for one-click install
Requirements
- macOS (tested) or Linux
- Python 3.12+
- uv
- Resend account with API key (get one here)
Quick Start
# Clone and install
git clone https://github.com/Groupthink-dev/resend-blade-mcp.git
cd resend-blade-mcp
uv sync
# Set your API key
export RESEND_API_KEY=re_xxxxxxxx
# Run (stdio transport)
uv run resend-blade-mcp
Claude Code
claude mcp add resend-blade -- uv run --directory ~/src/resend-blade-mcp resend-blade-mcp
Claude Desktop (claude_desktop_config.json)
{
"mcpServers": {
"resend-blade": {
"command": "uv",
"args": ["run", "--directory", "/path/to/resend-blade-mcp", "resend-blade-mcp"],
"env": {
"RESEND_API_KEY": "re_xxxxxxxx",
"RESEND_WRITE_ENABLED": "false"
}
}
}
}
Tools (28)
Sending (5)
| Tool | Gate | Description |
|---|---|---|
resend_send |
write | Send email (HTML/text, attachments, scheduled, idempotent) |
resend_send_batch |
write | Batch send up to 100 emails |
resend_get_email |
read | Retrieve sent email by ID |
resend_list_emails |
read | List sent emails with status |
resend_cancel_scheduled |
write | Cancel a scheduled email |
Contacts (4)
| Tool | Gate | Description |
|---|---|---|
resend_create_contact |
write | Create a contact with properties |
resend_list_contacts |
read | List contacts |
resend_update_contact |
write | Update contact properties |
resend_delete_contact |
write | Delete a contact |
Segments (3)
| Tool | Gate | Description |
|---|---|---|
resend_create_segment |
write | Create a segment |
resend_list_segments |
read | List segments |
resend_delete_segment |
write | Delete a segment |
Broadcasts (4)
| Tool | Gate | Description |
|---|---|---|
resend_create_broadcast |
write | Create a broadcast (draft) |
resend_send_broadcast |
write | Send or schedule a draft broadcast |
resend_list_broadcasts |
read | List broadcasts with status |
resend_delete_broadcast |
write | Delete a draft/scheduled broadcast |
Templates (4)
| Tool | Gate | Description |
|---|---|---|
resend_create_template |
write | Create template with variables |
resend_list_templates |
read | List templates |
resend_get_template |
read | Get template with HTML content |
resend_publish_template |
write | Publish template for use in sends |
Domains (4)
| Tool | Gate | Description |
|---|---|---|
resend_add_domain |
write | Register a sending domain (returns DNS records) |
resend_list_domains |
read | List domains with verification status |
resend_get_domain |
read | Get domain with DNS record details |
resend_verify_domain |
write | Trigger DNS verification |
Webhooks (3)
| Tool | Gate | Description |
|---|---|---|
resend_create_webhook |
write | Create webhook endpoint (returns signing secret) |
resend_list_webhooks |
read | List webhook endpoints |
resend_delete_webhook |
write | Delete a webhook |
Logs (1)
| Tool | Gate | Description |
|---|---|---|
resend_list_logs |
read | List recent API request logs |
Security
| Layer | Control |
|---|---|
| API key | RESEND_API_KEY from env (never logged, scrubbed from errors) |
| Transport | stdio default (no network exposure) |
| Write gate | RESEND_WRITE_ENABLED default false — blocks all 17 write tools |
| Attachments | Base64 content or HTTPS URL only — filesystem paths rejected |
| API key CRUD | Excluded — no tool can create, list, or delete API keys |
| Batch limits | resend_send_batch capped at 100 (Resend API maximum) |
| Credential scrubbing | re_* patterns removed from all error output |
| HTTP auth | Optional bearer token middleware (RESEND_MCP_API_TOKEN) |
| Rate limits | 429 responses surface as typed RateLimitError with retry-after |
HTTP Transport
export RESEND_MCP_TRANSPORT=http
export RESEND_MCP_HOST=127.0.0.1
export RESEND_MCP_PORT=8770
export RESEND_MCP_API_TOKEN=your-secret-token
uv run resend-blade-mcp
Environment Variables
| Variable | Default | Description |
|---|---|---|
RESEND_API_KEY |
(required) | Resend API key |
RESEND_WRITE_ENABLED |
false |
Enable write operations |
RESEND_MCP_TRANSPORT |
stdio |
Transport: stdio or http |
RESEND_MCP_HOST |
127.0.0.1 |
HTTP bind host |
RESEND_MCP_PORT |
8770 |
HTTP bind port |
RESEND_MCP_API_TOKEN |
(none) | Bearer token for HTTP auth |
Development
make install-dev # Install with dev dependencies
make test # Run unit tests (mocked, no Resend needed)
make test-e2e # Run E2E tests (requires live API key)
make check # Lint + format + type-check
make run # Start the server
License
MIT
Metadata
Release files for resend-blade-mcp 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| resend_blade_mcp-0.2.0.tar.gz | 105.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| resend_blade_mcp-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 125.3 kB
Release files / resend_blade_mcp-0.2.0.tar.gz
| Download URL | resend_blade_mcp-0.2.0.tar.gz |
|---|---|
| Size | 105.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ef891f0a9567e14e9d56271d64729a5bb5e376d119e46d86efe70c52ec7a66a5
|
|
BLAKE2b-256 checksum How to use checksums |
9b4ae671e21fe2ad4dc1c86afe47e84bf92e77c50439d4c5b748a6343fd5086b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 28, 2026.
Transparency logRelease files / resend_blade_mcp-0.2.0-py3-none-any.whl
| Download URL | resend_blade_mcp-0.2.0-py3-none-any.whl |
|---|---|
| Size | 19.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
66b4c2c9502702eea49575d3fa4ccd69cba6c60f39d3b22099fd863b30230c1e
|
|
BLAKE2b-256 checksum How to use checksums |
015732fe665758b7322397fb1d841d6cee7a557b65eabb0719a3b6c1b07f603a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Apr 28, 2026.
Transparency log