TypeScript

The @mcpmailer/sdk client: install, send, read the inbox, and open the vault.

The TypeScript SDK is a thin, fully typed wrapper over the v1 API with no runtime dependencies. It uses the global fetch, so it runs unchanged on Node 18 and up, Bun, Deno, and Cloudflare Workers.

Shell
npm install @mcpmailer/sdk

The client

One class, one method per call, no local state. Pass your own fetch if you need to route requests through a proxy or a test double.

TypeScript
import { Mcpmailer } from '@mcpmailer/sdk';

// Reads MCPMAILER_API_KEY when you pass nothing.
const mm = new Mcpmailer();

// Or be explicit, and point at another deployment if you need to.
const staging = new Mcpmailer({
  apiKey: process.env.STAGING_KEY,
  baseUrl: 'https://staging.mcpmailer.com'
});

Sending

Attachments take raw bytes or a base64 string; the SDK encodes them for you. Set style to plain, flat, or card to override how the message looks, or leave it out and let the mailbox decide.

TypeScript
const result = await mm.send({
  to: ['jane@acme.com'],
  subject: 'Your quote',
  body: 'Attached, as promised.',
  attachments: [
    { filename: 'quote.pdf', content: await Bun.file('quote.pdf').bytes() }
  ],
  trackOpens: true
});

if (result.status === 'rejected') {
  // A refused send is a result, not a throw: reason is something to act on.
  console.log(result.reason); // daily_send_quota_exhausted, recipient_suppressed, ...
}

Reading and answering

The methods below cover the loop most agents actually run: read what came in, find out who wrote, answer, record what you learned, and get it out of the inbox.

TypeScript
const inbox = await mm.listMessages({ unreadOnly: true, limit: 20 });

for (const message of inbox) {
  const [who] = await mm.lookupContact(message.from);

  await mm.replyAll(message.id, 'Thanks, looking into it now.');

  if (who) {
    await mm.rememberAboutContact(who.id, 'Asked about SSO pricing', message.id);
  }
  await mm.archiveMessage(message.id);
}

Also on the client: getMessage, getThread, search, getAttachment, markUnread, forward, listNotes and createNote, listContacts and createContact, listMailboxes and createMailbox, listDomains, listWebhooks, createWebhook and updateWebhook.

The vault

Secrets this agent has been granted, read with the same key as everything else. Values are encrypted at rest and opened server-side for the agents that were granted them, so a credential can be used without ever passing through a prompt.

TypeScript
const secrets = await mm.listSecrets();
const stripe = await mm.getSecret(secrets[0].id);
// The value arrives ready to use, without ever passing through a prompt.

const { code, expiresInSeconds } = await mm.getTotpCode(secrets[0].id);

Errors

McpmailerError carries the HTTP status, a stable code, and a hint meant to be read. A rejected send does not throw: check result.status instead.

TypeScript
import { McpmailerError } from '@mcpmailer/sdk';

try {
  await mm.send({ to: ['jane@acme.com'], subject: 'Hi', body: 'Hello' });
} catch (error) {
  if (error instanceof McpmailerError) {
    console.log(error.status, error.code, error.hint);
  }
}