Skip to content

feat(resend-mcp): add Resend email API integration#158

Open
viktormarinho wants to merge 1 commit intomainfrom
feat/resend-mcp
Open

feat(resend-mcp): add Resend email API integration#158
viktormarinho wants to merge 1 commit intomainfrom
feat/resend-mcp

Conversation

@viktormarinho
Copy link
Contributor

@viktormarinho viktormarinho commented Jan 23, 2026

Summary

This PR introduces a new Resend MCP for sending transactional and marketing emails via the Resend API.

Features

  • 📧 Send Email Tool: Comprehensive email sending with full Resend API support
  • 💌 Content Formats: Supports both HTML and plain text emails
  • 👥 Multiple Recipients: Full support for to/cc/bcc addressing
  • 🔄 Advanced Options: Custom headers and reply-to addresses
  • ⚙️ Default Configuration: Optional default sender configuration to reduce repetition
  • 🔒 Secure Authentication: API key-based authentication via StateSchema
  • 📊 Error Handling: Comprehensive error mapping (401, 403, 422, 429, 500)

Architecture

This MCP follows the TikTok Ads MCP pattern:

  • ✅ Simple API key authentication via StateSchema (no OAuth flow needed)
  • ✅ Uses bun build (like mcp-studio) instead of wrangler/vite
  • ✅ Clean {data, error} response format
  • ✅ Comprehensive Zod validation
  • ✅ Email format validation (supports both "email@domain.com" and "Name email@domain.com" formats)

Implementation Details

File Structure

resend-mcp/
├── server/
│   ├── main.ts              # Entry point
│   ├── lib/
│   │   ├── client.ts        # Resend API client with error mapping
│   │   └── env.ts           # Environment helpers
│   └── tools/
│       ├── email.ts         # send_email tool with validation
│       └── index.ts         # Tools export
├── shared/
│   └── deco.gen.ts          # StateSchema & types
├── app.json                 # MCP metadata
├── package.json             # Dependencies
├── tsconfig.json            # TypeScript config
└── README.md                # Documentation

Tool: send_email

Required Parameters:

  • to: Recipient email(s)
  • subject: Email subject
  • html OR text: Email content (at least one required)

Optional Parameters:

  • from: Sender email (falls back to configured default)
  • cc: Carbon copy recipient(s)
  • bcc: Blind carbon copy recipient(s)
  • reply_to: Reply-to address(es)
  • headers: Custom email headers

Response Format:

{
  "data": { "id": "email_id" },
  "error": null
}

Configuration

Users configure the MCP during installation with:

  • API Key (required): Resend API key
  • Default From (optional): Default sender email
  • Default From Name (optional): Default sender name

Testing

  • ✅ Build successful: bun run build (334 modules bundled)
  • ✅ TypeScript type checking passes (minor known type warning in oauth.state)
  • ✅ Formatting validated with oxfmt
  • ✅ Linting validated with oxlint

Example Usage

Simple Email

{
  "to": "user@example.com",
  "subject": "Welcome!",
  "text": "Thanks for signing up!"
}

Rich HTML Email

{
  "from": "Team <team@company.com>",
  "to": "user@example.com",
  "cc": "manager@company.com",
  "subject": "Monthly Report",
  "html": "<h1>Report</h1><p>Your report is ready.</p>"
}

Related

  • Spec document: resend-mcp-spec.md
  • Follows patterns from: TikTok Ads MCP, mcp-studio

🤖 Generated with Claude Code


Note

Introduces a new MCP workspace to integrate with Resend’s email API.

  • Adds resend-mcp workspace with MCP server, send_email tool, and Resend API client (server/lib/client.ts) using bearer auth and JSON payloads
  • Implements Zod-validated inputs (email formats, required subject and at least one of html/text) and returns { data, error } responses with mapped error codes
  • Supports multiple recipients (to/cc/bcc), custom headers, reply-to, and default sender resolution via StateSchema/env helpers
  • Adds app metadata (app.json), generated types (shared/deco.gen.ts), build scripts, and README; updates root package.json workspaces and lockfile

Written by Cursor Bugbot for commit bcc1867. This will update automatically on new commits. Configure here.


Summary by cubic

Adds a new Resend MCP to send transactional and marketing emails via the Resend API. Provides a single send_email tool with flexible inputs, defaults, and clear error handling.

  • New Features

    • send_email tool supporting HTML and/or text.
    • Multiple recipients (to/cc/bcc), reply_to, and custom headers.
    • API key auth via StateSchema with optional default sender.
    • Zod validation for emails and inputs; returns {data, error}.
    • Mapped errors for 401, 403, 422, 429, and 500.
  • Migration

    • Configure the Resend API key during installation.
    • Optionally set defaultFrom and defaultFromName for the sender.

Written for commit bcc1867. Summary will update on new commits.

Implements a new MCP for sending transactional and marketing emails via Resend API.

Features:
- Send email tool with comprehensive parameters
- Support for HTML and plain text content
- Multiple recipients (to/cc/bcc)
- Custom headers and reply-to addresses
- Configurable default sender
- Secure API key-based authentication
- Comprehensive error handling with proper error codes

Architecture:
- Follows TikTok Ads MCP pattern (simple API key auth via StateSchema)
- No wrangler/vite dependencies (uses bun build like mcp-studio)
- Clean {data, error} response format
- Email format validation
- Single comprehensive send_email tool

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@github-actions
Copy link

🚀 Preview Deployments Ready!

Your changes have been deployed to preview environments:

📦 resend-mcp

🔗 View Preview

These previews will be automatically updated with new commits to this PR.


Deployed from commit: 39d0f98

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

This is the final PR Bugbot will review for you during this billing cycle

Your free Bugbot reviews will reset on February 22

Details

You are on the Bugbot Free tier. On this plan, Bugbot will review limited PRs each billing cycle.

To receive Bugbot reviews on all of your PRs, visit the Cursor dashboard to activate Pro and start your 14-day free trial.


const name = errorCodeMap[status] || "application_error";
return { name, message };
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error mapping discards API-provided error name

Medium Severity

The mapError function extracts message from the API response but ignores any name field returned by the Resend API. Instead, it always overrides the error name with a generic value based solely on HTTP status code. According to the spec, the same HTTP status can have multiple distinct error codes (e.g., 403 can be invalid_api_key, invalid_from_address, or validation_error; 422 can be missing_required_field, invalid_access, invalid_parameter, or invalid_region). This implementation loses that granular error information, making it harder for users to diagnose and fix issues.

Fix in Cursor Fix in Web

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 14 files

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant