Skip to main content
Glama
manganate006

mailu-mcp

README.md
<div align="center">

# mailu-mcp

**MCP server to administer a [Mailu](https://mailu.io) mail server from Claude — domains, mailboxes, aliases and forwards, without leaving the conversation.**

[![CI](https://github.com/manganate006/mailu-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/manganate006/mailu-mcp/actions/workflows/ci.yml)
[![npm](https://img.shields.io/npm/v/@manganate06/mailu-mcp)](https://www.npmjs.com/package/@manganate06/mailu-mcp)
[![License: MIT](https://img.shields.io/github/license/manganate006/mailu-mcp)](LICENSE)

**[Installation](#installation) · [Tools](#tools) · [Examples](#examples) · [Limitations](#limitations) · [🇫🇷 Français](README.fr.md)**

</div>

## Overview

This [MCP](https://modelcontextprotocol.io) server exposes Mailu's admin REST API as tools Claude can call. Ask in natural language, Claude executes:

> **You:** List the domains managed by Mailu, then the aliases of `example.com`.
>
> **Claude:** *(calls `mailu_list_domains` then `mailu_list_aliases_by_domain`)*
> 3 domains: `example.com`, `example.org`, `example.net`.
> Aliases of `example.com`: `contact@` → `team@gmail.com`, `info@` → `team@gmail.com`.

## Requirements

Enable the REST API on the Mailu server (`mailu.env`, Mailu ≥ 1.9, tested on 2.0):

```ini
API=true
WEB_API=/api
API_TOKEN=<generate with: openssl rand -hex 32>
```

Then recreate the containers: `cd /mailu && docker compose up -d`.
Verify: `curl -H "Authorization: <API_TOKEN>" https://mail.example.com/api/v1/domain`.

> Auth: the token goes **raw** in the `Authorization` header (apiKey scheme, **no** `Bearer` prefix).

## Installation

### Claude Code

```bash
claude mcp add mailu \
  --env MAILU_API_URL=https://mail.example.com/api/v1 \
  --env MAILU_API_TOKEN=your_token \
  -- npx -y @manganate06/mailu-mcp
```

### Claude Desktop / Cursor

Add to `claude_desktop_config.json` (or Cursor's MCP config):

```json
{
  "mcpServers": {
    "mailu": {
      "command": "npx",
      "args": ["-y", "@manganate06/mailu-mcp"],
      "env": {
        "MAILU_API_URL": "https://mail.example.com/api/v1",
        "MAILU_API_TOKEN": "your_token"
      }
    }
  }
}
```

Tested with Claude Code and Claude Desktop.

## Configuration

| Variable | Purpose | Required | Where to get it |
|---|---|---|---|
| `MAILU_API_URL` | API base URL (with `/api/v1`) | ✅ | your Mailu instance |
| `MAILU_API_TOKEN` | API token | ✅ | `API_TOKEN` in `mailu.env` |
| `MAILU_MCP_DEBUG` | Debug logs on stderr | ❌ | `true` / `false` |

## Tools

32 tools, `mailu_` prefix (omitted in the table). Parameter details: [`src/index.ts`](src/index.ts).

| Area | Tools |
|---|---|
| **Domains** | `list_domains`, `get_domain`, `create_domain`, `update_domain`, `delete_domain`, `generate_domain_dkim`, `list_domain_users`, `list_domain_managers`, `create_domain_manager`, `get_domain_manager`, `delete_domain_manager` |
| **Mailboxes** | `list_users`, `get_user`, `create_user`, `update_user`, `delete_user` |
| **Aliases** | `list_aliases`, `get_alias`, `list_aliases_by_domain`, `create_alias`, `update_alias`, `delete_alias` |
| **Alternatives** | `list_alternatives`, `get_alternative`, `create_alternative`, `delete_alternative` |
| **Relays** | `list_relays`, `get_relay`, `create_relay`, `update_relay`, `delete_relay` |
| **Generic** | `mailu_request` (`method`, `path`, `body`) — escape hatch for any endpoint |

## Examples

- "List the Mailu domains"
- "Show the aliases of `example.com`"
- "Create the mailbox `contact@example.com` with a 2 GB quota"
- "Add an alias `info@example.com` forwarding to `jean@gmail.com`"
- "Regenerate the DKIM keys for `example.com`"

## Limitations

- Mirrors the Mailu admin REST API — anything the API doesn't expose (fetched accounts, webmail/antispam settings…) isn't available; reach any un-wrapped endpoint via `mailu_request`.
- No bulk helpers — one object per call (the assistant can loop over a list).
- `MAILU_API_TOKEN` is a **full-admin** credential — scope it and restrict network access to the API.

## Transport

`stdio` — works with Claude Code, Claude Desktop, Cursor and any MCP client.

## Development

```bash
git clone https://github.com/manganate006/mailu-mcp
cd mailu-mcp && npm install
npm run build && npm run bundle    # dist/bundle.js (single file, e.g. for NFS)
npm test                           # unit tests (mocked HTTP, no live server)
npm run test:integration           # end-to-end CRUD self-test (needs live MAILU_API_URL/TOKEN)
npx @modelcontextprotocol/inspector node dist/bundle.js
```

## License

[MIT](LICENSE)

TDQS

A3.5/5.0

Scored across 32 tools

Disambiguation5/5

Each tool targets a distinct resource-action pair (e.g., domain, user, alias, alternative, relay), with clear descriptions and no overlapping functionality. Even similar tools like list_users and list_domain_users are differentiated by scope.

Naming Consistency5/5

All tools follow a consistent 'mailu_{verb}_{noun}' pattern (e.g., mailu_list_domains, mailu_create_user). Verbs are action-oriented (list, get, create, update, delete, generate) and nouns correspond to resources, with no mixing of styles.

Tool Count4/5

32 tools is on the high side but justified by the comprehensive coverage of multiple resource types (domains, users, aliases, alternatives, relays) including managers, DKIM generation, and a generic API fallback. Could be slightly trimmed but remains well-scoped.

Completeness5/5

The set covers the full lifecycle for all major resources: CRUD for domains, users, aliases, alternatives, and relays, plus domain managers, DKIM generation, and a generic API call for edge cases. No obvious gaps for standard mail server management.

Maintenance

ActivitySlowing
ResponsivenessNo issues