Let Your AI Write the HTML — Then Just Send the Email
Your coding agent can generate the email body. Your app should still deliver it with one HTTP call — no MCP server required. Notify is the dumb, reliable pipe.
AI tools are great at writing HTML email. They are unnecessary as a transport.
If your agent can call fetch, it does not need an MCP server, a plugin marketplace, or a special “email agent runtime” to deliver a password reset. Put the API key in your app (or CI), generate the body however you like, and send.
That is Notify’s whole product stance: you (or your AI) write the HTML; we deliver it. Tongue-in-cheek version: /mcp.
The wrong architecture
Agent → MCP email tool → mystery wrapper → ESP
More moving parts, more auth surfaces, more “why did the agent send 400 emails?” stories.
The right architecture
Agent or app code → generate HTML string → POST /api/email/send → inbox
Your application remains the security boundary. The agent helps author content or suggest code; production sends go through your server with your rate limits.
Pattern A — AI helps you write the template once
- Ask Cursor (or any agent) to draft a receipt layout
- Commit the HTML/TS template to your repo
- Fill variables at runtime
- Send with Notify
const message = renderReceiptEmail({
amount: '29.00',
currency: 'USD',
invoiceUrl
});
await fetch('https://notify.cx/api/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.NOTIFY_API_KEY!
},
body: JSON.stringify({
from: 'billing@your-verified-domain.com',
to: customer.email,
subject: `Receipt — ${amount} ${currency}`,
message
})
});
Human review optional but wise for auth-critical copy.
Pattern B — Agent generates HTML at runtime (guarded)
Use only behind strict allowlists:
export async function sendAgentDraftedEmail(input: {
to: string; // must be the current user’s email
subject: string; // allowlisted prefixes only
html: string; // run through sanitizer
}) {
assertUserCanEmail(input.to);
assertSubjectAllowed(input.subject);
const message = sanitizeEmailHtml(input.html);
await fetch('https://notify.cx/api/email/send', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': process.env.NOTIFY_API_KEY!
},
body: JSON.stringify({
from: 'noreply@your-verified-domain.com',
to: input.to,
subject: input.subject,
message
})
});
}
Never give an agent a raw API key in the browser. Never let it choose arbitrary to addresses in production.
What you do not need
- An official MCP server to wrap one HTTP request
- A template studio inside the ESP
- A second “AI email product” for transactional mail
If a vendor’s main AI story is MCP install paths, ask whether fetch already solved the problem.
Security checklist
- [ ] API key only on server / secret store
- [ ] Recipients constrained to verified user emails
- [ ] HTML sanitized if model-generated at runtime
- [ ] Rate limits and audit logs on send endpoints
- [ ] Verified domain for
from
Bottom line
AI is a content accelerator. Transactional email is still a boring pipe. Notify keeps the pipe small on purpose: to, from, subject, message.
Quick start · Why email APIs should stay small · /mcp · Pricing