Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 9 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ https://github.com/user-attachments/assets/8c05cbf0-1664-4b3b-afb1-663b46af3464
**Cursor**

1. First, you need to authorize Resend to send emails from your domain or email. Follow the steps [here](https://resend.com/docs/send-with-nodejs) to set that up and get a Resend API key.
2. Clone this project locally. Edit index.ts and replace [email protected] to your own email to send emails from
2. Clone this project locally.
3. Run `npm install`, `npm run build` under the project dir. You should now see a /build/index.js generated - this is the MCP server script!

Then go to Cursor Settings -> MCP -> Add new MCP server
Expand All @@ -44,16 +44,19 @@ Now you can test out sending emails by going to email.md, replace the to: email

Same set up as above, and then add the following MCP config

```
```json
{
"mcpServers": {
"resend": {
"command": "node",
"args": ["ABSOLUTE_PATH_TO_MCP_SERVER/build/index.js"],
"env": {
"RESEND_API_KEY": [YOUR_API_KEY],
"SENDER_EMAIL_ADDRESS": [OPTIONAL_SENDER_EMAIL_ADDRESS],
"REPLY_TO_EMAIL_ADDRESSES": [OPTIONAL_REPLY_TO_EMAIL_ADDRESSES_COMMA_DELIMITED]
"RESEND_API_KEY": "<YOUR_API_KEY>",
"SENDER_EMAIL_ADDRESS": "<OPTIONAL_SENDER_EMAIL_ADDRESS>",
"SENDER_NAME": "<OPTIONAL_SENDER_NAME>",
"REPLY_TO_EMAIL_ADDRESSES": "<OPTIONAL_REPLY_TO_EMAIL_ADDRESSES_COMMA_DELIMITED>",
"CC_EMAIL_ADDRESSES": "<OPTIONAL_CC_EMAIL_ADDRESSES_COMMA_DELIMITED>",
"BCC_EMAIL_ADDRESSES": "<OPTIONAL_BCC_EMAIL_ADDRESSES_COMMA_DELIMITED>"
}
}
}
Expand All @@ -63,4 +66,5 @@ Same set up as above, and then add the following MCP config
**Develop**

`npm install`

`npm run build`
90 changes: 69 additions & 21 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,45 @@ const apiKey = argv.key || process.env.RESEND_API_KEY;
// Optional.
const senderEmailAddress = argv.sender || process.env.SENDER_EMAIL_ADDRESS;

// Get reply to email addresses from command line argument or fall back to environment variable
let replierEmailAddresses: string[] = [];
// Get sender name from command line argument or fall back to environment variable
// Optional.
const senderName = argv.sendername || process.env.SENDER_NAME;

if (Array.isArray(argv["reply-to"])) {
replierEmailAddresses = argv["reply-to"];
} else if (typeof argv["reply-to"] === "string") {
replierEmailAddresses = [argv["reply-to"]];
} else if (process.env.REPLY_TO_EMAIL_ADDRESSES) {
replierEmailAddresses = process.env.REPLY_TO_EMAIL_ADDRESSES.split(",");
// Get reply to email addresses, BCC email addresses, and CC email addresses from command line argument or fall back to environment variable
let replierEmailAddresses: string[] = [];
let bccEmailAddresses: string[] = [];
let ccEmailAddresses: string[] = [];

function parseArrayOrStringParam(
cliParam: string | string[] | undefined,
envParam: string | undefined,
delimiter: string = ","
): string[] {
if (Array.isArray(cliParam)) {
return cliParam;
} else if (typeof cliParam === "string") {
return [cliParam];
} else if (envParam) {
return envParam.split(delimiter);
}
return [];
}

replierEmailAddresses = parseArrayOrStringParam(
argv["reply-to"],
process.env.REPLY_TO_EMAIL_ADDRESSES
);

bccEmailAddresses = parseArrayOrStringParam(
argv["bcc"],
process.env.BCC_EMAIL_ADDRESSES
);

ccEmailAddresses = parseArrayOrStringParam(
argv["cc"],
process.env.CC_EMAIL_ADDRESSES
);

if (!apiKey) {
console.error(
"No API key provided. Please set RESEND_API_KEY environment variable or use --key argument"
Expand Down Expand Up @@ -58,13 +86,17 @@ server.tool(
.email()
.array()
.optional()
.describe("Optional array of CC email addresses. You MUST ask the user for this parameter. Under no circumstance provide it yourself"),
.describe(
"Optional array of CC email addresses. You MUST ask the user for this parameter. Under no circumstance provide it yourself"
),
bcc: z
.string()
.email()
.array()
.optional()
.describe("Optional array of BCC email addresses. You MUST ask the user for this parameter. Under no circumstance provide it yourself"),
.describe(
"Optional array of BCC email addresses. You MUST ask the user for this parameter. Under no circumstance provide it yourself"
),
scheduledAt: z
.string()
.optional()
Expand Down Expand Up @@ -97,9 +129,25 @@ server.tool(
: {}),
},
async ({ from, to, subject, text, html, replyTo, scheduledAt, cc, bcc }) => {
const fromEmailAddress = from ?? senderEmailAddress;
// If sender name is provided, use it to format the from email address
// e.g. "John Doe <[email protected]>"
const fromEmailAddress =
from ??
(senderName
? `${senderName} <${senderEmailAddress}>`
: senderEmailAddress);
const replyToEmailAddresses = replyTo ?? replierEmailAddresses;

// Combine provided BCC addresses with any default BCC addresses
const combinedBccAddresses = bcc
? [...bcc, ...bccEmailAddresses]
: bccEmailAddresses;

// Combine provided CC addresses with any default CC addresses
const combinedCcAddresses = cc
? [...cc, ...ccEmailAddresses]
: ccEmailAddresses;

// Type check on from, since "from" is optionally included in the arguments schema
// This should never happen.
if (typeof fromEmailAddress !== "string") {
Expand All @@ -115,7 +163,7 @@ server.tool(
}

console.error(`Debug - Sending email with from: ${fromEmailAddress}`);

// Explicitly structure the request with all parameters to ensure they're passed correctly
const emailRequest: {
to: string;
Expand All @@ -134,24 +182,24 @@ server.tool(
from: fromEmailAddress,
replyTo: replyToEmailAddresses,
};

// Add optional parameters conditionally
if (html) {
emailRequest.html = html;
}

if (scheduledAt) {
emailRequest.scheduledAt = scheduledAt;
}
if (cc) {
emailRequest.cc = cc;

if (combinedCcAddresses.length > 0) {
emailRequest.cc = combinedCcAddresses;
}
if (bcc) {
emailRequest.bcc = bcc;

if (combinedBccAddresses.length > 0) {
emailRequest.bcc = combinedBccAddresses;
}

console.error(`Email request: ${JSON.stringify(emailRequest)}`);

const response = await resend.emails.send(emailRequest);
Expand Down