maillog-mcp
# @maillog/node-sdk
Node SDK and MCP server for the [Maillog](https://maillog.nl) email API.
Other languages: [Python](https://github.com/Jorisslagter/sdk-python) ·
[Go](https://github.com/Jorisslagter/sdk-go) ·
[Ruby](https://github.com/Jorisslagter/sdk-ruby) ·
[PHP](https://github.com/Jorisslagter/sdk-php) ·
[Rust](https://github.com/Jorisslagter/sdk-rust)
## Install
```sh
npm install @maillog/node-sdk
```
## Get a key without an account
```sh
curl -X POST https://api.maillog.nl/v1/keys/sandbox \
-H "Content-Type: application/json" \
-d '{"email":"you@example.com"}'
```
The key it returns may only send to that address and expires after 24 hours.
For your own domains, sign up at https://maillog.nl/signup.
## Send
```js
import { Maillog } from "@maillog/node-sdk";
const maillog = new Maillog(process.env.MAILLOG_API_KEY);
const { id } = await maillog.emails.send({
from: "Acme <noreply@acme.nl>",
to: ["you@example.com"],
subject: "hello",
html: "<p>it works</p>",
});
```
`emails.sendBatch(emails)` takes 1 to 100 at a time. `emails.list({ limit, offset, status })`
returns what was sent, with delivery status and open/click counts.
## Errors
Failures throw `MaillogError` with `.status` and `.body`, so a 422 from validation
and a 403 from an expired key can be handled apart.
```js
import { MaillogError } from "@maillog/node-sdk";
try {
await maillog.emails.send(params);
} catch (err) {
if (err instanceof MaillogError && err.status === 422) {
// body carries errors[] with the offending field
}
}
```
There is no retry logic, on purpose: a client that silently resends produces
duplicate mail, and only you know whether that is acceptable.
## MCP server
The package ships an MCP server so an assistant can send mail directly.
```sh
claude mcp add maillog --env MAILLOG_API_KEY=ma_xxx -- npx -y maillog-mcp
```
Tools: `send_email`, `list_emails`.
## Options
```js
new Maillog(apiKey, {
baseUrl: "http://localhost:3086", // default https://api.maillog.nl
timeoutMs: 30_000,
});
```
## Develop
```sh
npm run build # tsc to dist/
node --test src/*.test.ts
```
MIT.
TDQS
Scored across 2 tools
send_email and list_emails have clearly distinct purposes: one creates a new outgoing message, the other reads history of previously sent messages. There is no overlap or ambiguity between them.
Both tool names follow the same verb_noun pattern (send_email, list_emails), making the set predictable and easy to navigate. The consistency is perfect for a two-tool surface.
With only two tools, the server feels thin for a general email service, though the pair covers the two most essential actions. The count is borderline but not unreasonable for a narrowly scoped transactional email logging use case.
The core lifecycle of sending and verifying delivery is covered: create an email and list sent emails with status. A minor gap is the lack of a single-email detail endpoint or pagination control, but agents can likely work around that using list_emails.