cd /news/ai-agents/email-as-an-agent-tool-mcp-the-sdk-o… · home topics ai-agents article
[ARTICLE · art-48030] src=mailkite.dev ↗ pub= topic=ai-agents verified=true sentiment=· neutral

Email as an agent tool: MCP, the SDK, or your own webhook

MailKite offers three ways to integrate email into AI agents: MCP for model-decided tool calls, SDK for deterministic code-driven sending, and webhooks for receiving emails. Developers can choose based on whether the agent or the program should control email actions, with runnable code examples provided for all three approaches.

read6 min views1 publishedJul 4, 2026
Email as an agent tool: MCP, the SDK, or your own webhook
Image: Mailkite (auto-discovered)

There are three ways to give an agent email, and they answer different questions. Install the MCP server and the model sends and reads mail as tool calls it decides to make. Hand it the SDK and email is deterministic code your agent runs. Point a signed webhook at it and the agent receives mail the moment it arrives. This is when to use each — with runnable code for all three, and how to mix them. For developers wiring an agent to email with MailKite.

“Give the agent email” isn’t one decision — it’s two, receiving and sending, and for sending there’s a real choice between the model deciding to send (a tool call) and your code deciding (a function call). Pick wrong and you either hard-code something the agent should choose, or hand the model a capability that should have been deterministic. Here are the three wirings and what each one is for.

The fastest one to show is MCP, because it’s a single command and then email is just tools the model has:

claude mcp add --transport http mailkite https://mcp.mailkite.dev/mcp

After that the model can send, read messages, and manage domains as tool calls it decides to make — no glue code. The runnable versions of all three wirings, including a webhook receiver and a mixed receive-by-webhook-send-by-SDK loop, are in demo-email-agent-tool;

open it in StackBlitz. Here’s each wiring and exactly when it’s the right one.

1. MCP: email as tools the model calls #

Use MCP when the agent should decide whether and when to touch email. You install the server once and the model gets a set of tools — send a message, list or read inbound, manage domains and routes — and calls them as part of its reasoning, the same way it calls any other tool. There’s no code path in your app that says “send now”; the model chooses.

mcp.mailkite.dev

with OAuth, plus there's a Claude Code plugin.## 2. The SDK: email as deterministic code

Use the SDK when your program decides. If the rule is “when a run finishes, email the result,” that’s not a judgment call the model should make on the fly — it’s a line of code. The SDK gives you mk.send()

and the full receive-verify path, in the agent’s own language:

// deterministic: your code decides to send, not the model
import { MailKite } from "mailkite";
const mk = new MailKite(process.env.MAILKITE_API_KEY);

async function onRunComplete(run) {
  await mk.send({
    from: "agent@yourco.dev",
    to: run.requestedBy,
    subject: `Done: ${run.title}`,
    html: renderReport(run),          // your template, your data
  });
}

This is also the right choice when you want a send to be testable, logged, and rate-limited by your own code rather than left to the model’s discretion. mk.send()

returns { id, status }

so you can record the outbound message. (Can’t take a dependency? Raw HTTP against the REST API works too — prefer the SDK, drop to raw only if you must.)

3. Your own webhook: email the agent receives #

Receiving is always the webhook, whichever way you send. A signed JSON payload arrives the instant mail hits the agent’s address; you verify it in one call and hand the decoded body to the model:

import express from "express";
import { MailKite } from "mailkite";

const app = express();
const SECRET = process.env.MAILKITE_WEBHOOK_SECRET;
app.use("/hooks/agent", express.raw({ type: "application/json" }));

app.post("/hooks/agent", async (req, res) => {
  // HMAC signature, replay window, constant-time compare — one call
  if (!MailKite.verifyWebhook(req.headers["x-mailkite-signature"], req.body, SECRET)) {
    return res.sendStatus(401);
  }
  res.sendStatus(200);

  const event = JSON.parse(req.body);
  if (event.type !== "email.received") return;

  // decoded text/html + an auth verdict — hand it to the model as untrusted INPUT
  await runAgent({ task: event.text, from: event.from.address, auth: event.auth });
});

app.listen(3000);

No public URL to host at all? A route with action: 'agent'

runs the receive-think-reply loop on a managed queue instead — covered in why we built programmable email for agents. But when you host the agent yourself, this handler is the receive half of every wiring above.

Mixing them: the common shape #

Most real agents combine wirings. The typical one is receive by webhook, send by whichever fits the decision: inbound arrives at your handler, the model reasons over it, and it replies either through an MCP tool call (if the model is choosing to reply) or through mk.send()

(if your code always replies). Here’s the decision in one grid.

Where I won’t overclaim #

MCP is not automatically the right answer just because you’re building an agent. Handing the model a send tool means giving it discretion over who gets email and when, and for a lot of flows that discretion is a liability, not a feature — a deterministic mk.send()

your code controls is easier to test, log, rate-limit, and reason about. Reach for MCP when the agent genuinely owns the decision; reach for the SDK when you do. And if you can’t take a dependency at all, the raw REST API is there — the SDK just saves you the HMAC and the boilerplate. The point isn’t “use all three,” it’s “these are the three, and they answer different questions.”

FAQ #

Should an agent send email through MCP or the SDK? Through MCP when the model should decide whether and when to send — it’s one of the tools it reasons with. Through the SDK when your program decides at a known point (“email the result when the run finishes”). Model-chosen sends want discretion; deterministic sends want code you can test and rate-limit.

How do I install the MailKite MCP server? It’s hosted at mcp.mailkite.dev

with OAuth. In Claude Code: claude mcp add --transport http mailkite https://mcp.mailkite.dev/mcp

. Any MCP-speaking client can connect the same way, and there’s also a Claude Code plugin. After that, sending, reading messages, and managing domains are tool calls the agent can make.

How does the agent receive email — is that MCP too? Receiving is the webhook: a signed JSON payload arrives at your handler the moment mail hits the agent’s address, and you verify it with MailKite.verifyWebhook()

. The model can also read the inbox on demand through MCP tools, but push delivery of new mail is the webhook (or a managed action: 'agent'

route if you don’t want to host an endpoint).

Can I use the webhook and MCP together? Yes, and that’s the common shape: receive by webhook, then reply by an MCP tool call (model-chosen) or mk.send()

(deterministic). The wirings compose — receiving and sending are separate decisions.

Do I need a dependency for any of this? No. The SDK (mailkite

on npm/PyPI/RubyGems, plus Go, PHP, Java, and a CLI) saves you the HMAC verification and request boilerplate, but the REST API works over plain HTTPS if you’d rather not add one. Prefer the SDK; drop to raw HTTP only if you must.

Receiving is the webhook; sending is a tool the model calls or code your program runs — pick by who owns the decision. Clone demo-email-agent-tool (or

run it in your browser) for all three wirings and the mixed loop, then

point a domain at MailKiteand wire email to your agent.

Related: why we built programmable email for agents, the AgentMail alternative for AI agents, and agent inbox security by design.

── more in #ai-agents 4 stories · sorted by recency
── more on @mailkite 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/email-as-an-agent-to…] indexed:0 read:6min 2026-07-04 ·