Stalwart MCP
Servidor MCP para Stalwart mail server via JMAP — buzones, búsqueda, envío y administración
Documentación
mcp-server-stalwart
Servidor MCP para Stalwart Mail Server. Proporciona operaciones de correo electrónico (búsqueda, lectura, envío, eliminación) vía JMAP y acceso opcional a la API de administración para la gestión del servidor.
Requisitos
- Rust (edición 2024)
- Un servidor de correo Stalwart con JMAP habilitado
Compilación
cargo build --release
El binario se genera en target/release/mcp-server-stalwart.
Configuración
El servidor se conecta mediante stdio y se configura a través de variables de entorno.
Obligatorias
| Variable | Descripción |
|---|---|
JMAP_SESSION_URL | Endpoint de sesión JMAP (p. ej. https://mail.example.com/jmap/session) |
JMAP_USERNAME | Dirección de correo de la cuenta JMAP |
JMAP_PASSWORD | Contraseña de la cuenta JMAP |
Opcionales (otros buzones)
Cambia las herramientas a otro buzón con account (p. ej. hello@codechap.com) sin necesidad de la API de administración.
| Variable | Descripción |
|---|---|
JMAP_SECRETS_FILE | Ruta a un secrets.toml de mailman4 (tabla [passwords] de "email" = "password") |
JMAP_ACCOUNTS | Lista email=password;other@host=password en línea (anula el archivo en caso de conflicto) |
Opcionales (API de administración)
| Variable | Descripción |
|---|---|
STALWART_ADMIN_URL | URL base de la API de administración — https://mail.example.com o https://mail.example.com/api (ambas aceptadas; /api se normaliza) |
STALWART_ADMIN_USER | Nombre de usuario de administración (predeterminado: admin) |
STALWART_ADMIN_PASSWORD | Contraseña de administración (principal distinto de las contraseñas de buzón) |
Advertencia sobre contraseñas (aprendida por las malas)
| Secreto | Se usa para | NO se usa para |
|---|---|---|
JMAP_PASSWORD / contraseña de buzón | Envío SMTP (smtp://user:pass@host:587), JMAP, IMAP para esa cuenta | API de administración |
STALWART_ADMIN_PASSWORD | API de administración (/api/principal, /api/logs, …) | DSN de aplicaciones de correo |
Si una aplicación (mailer de facturas, WordPress, etc.) está configurada con la contraseña de administración como secreto SMTP, Stalwart devuelve 535 Authentication credentials invalid y no se pone nada en cola. check_sent mostrará correctamente cero envíos. Usa verify_account_auth para probar las credenciales antes de perseguir problemas de entrega.
Configuración de MCP en Claude Code
{
"mcpServers": {
"stalwart": {
"command": "/path/to/mcp-server-stalwart",
"env": {
"JMAP_SESSION_URL": "https://mail.example.com/jmap/session",
"JMAP_USERNAME": "you@example.com",
"JMAP_PASSWORD": "your-password",
"JMAP_SECRETS_FILE": "/home/you/.local/share/mailman4/secrets.toml",
"STALWART_ADMIN_URL": "https://mail.example.com",
"STALWART_ADMIN_PASSWORD": "admin-password"
}
}
}
}
Herramientas
get_mailboxes
Lista todos los buzones/carpetas con recuentos de mensajes.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
account | string | no | Buzón a listar (p. ej. hello@codechap.com) |
create_mailbox
Crea un nuevo buzón/carpeta.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name | string | sí | Nombre del buzón |
parent_id | string | no | ID del buzón padre para anidamiento (nivel superior si se omite) |
role | string | no | Rol estándar: archive, drafts, inbox, junk, sent, trash |
search_emails
Busca correos con filtros. Devuelve IDs de correo — usa get_emails para leer el contenido completo.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
query | string | no | Texto para buscar en asunto, cuerpo, remitente, destinatario |
from | string | no | Filtrar por dirección del remitente |
to | string | no | Filtrar por dirección del destinatario |
subject | string | no | Filtrar por texto del asunto |
mailbox_id | string | no | Restringir a un buzón específico |
position | number | no | Desplazamiento de paginación (predeterminado 0) |
limit | number | no | Máximo de resultados (predeterminado 10, máximo 50) |
account | string | no | Buzón a buscar (p. ej. hello@codechap.com) |
get_emails
Obtiene el contenido completo de los correos por IDs. Devuelve asunto, remitente, destinatario, fecha, cuerpo de texto y metadatos.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
ids | string[] | sí | Lista de IDs de correo a recuperar |
account | string | no | Buzón propietario de estos correos |
delete_emails
Elimina permanentemente correos por ID. No se puede deshacer.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
ids | string[] | sí | Lista de IDs de correo a eliminar |
account | string | no | Buzón del que eliminar |
send_email
Envía un correo con cuerpo HTML opcional y archivos adjuntos. Cuando se proporciona html_body, el correo se envía como multipart con partes de texto plano y HTML — el cliente de correo del destinatario elegirá cuál mostrar.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
to | string[] | sí | Direcciones de correo de los destinatarios |
subject | string | sí | Asunto del correo |
body | string | sí | Cuerpo en texto plano |
html_body | string | no | Cuerpo HTML. Cuando se proporciona, el correo se envía como multipart (text/plain + text/html) |
cc | string[] | no | Destinatarios en copia (CC) |
bcc | string[] | no | Destinatarios en copia oculta (BCC) |
attachments | object[] | no | Archivos adjuntos (ver más abajo) |
account | string | no | Enviar como este buzón (p. ej. hello@codechap.com) en lugar del usuario JMAP predeterminado |
Objeto de adjunto:
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
path | string | sí | Ruta absoluta al archivo en disco |
filename | string | sí | Nombre de archivo para el adjunto |
content_type | string | no | Tipo MIME (se detecta automáticamente desde la extensión si se omite) |
download_attachments
Descarga todos los adjuntos de un correo a un directorio local.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
email_id | string | sí | ID del correo del que descargar adjuntos |
download_dir | string | sí | Ruta del directorio donde guardar los adjuntos |
create_account (admin)
Crea una nueva cuenta de correo en el servidor. Requiere configuración de la API de administración.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
email | string | sí | Dirección de correo principal |
password | string | sí | Contraseña de la cuenta |
description | string | no | Nombre para mostrar |
quota | number | no | Cuota de disco en bytes (0 para ilimitada) |
permissions | string[] | no | Permisos a otorgar en la creación (p. ej. email-send, authenticate, imap-authenticate). Sin permisos, la cuenta no puede autenticarse ni enviar correo — proporciónalos aquí o llama a update_account_permissions después. |
list_accounts (admin)
Lista todas las cuentas, u obtiene detalles de una. Requiere configuración de la API de administración.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
name | string | no | Nombre de la cuenta para detalles. Si se omite, lista todas las cuentas. |
manage_aliases (admin)
Añade o elimina un alias de correo en una cuenta. Requiere configuración de la API de administración.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
account | string | sí | Nombre de la cuenta |
action | string | sí | add o remove |
alias | string | sí | Alias de correo a añadir/eliminar |
update_account_permissions (admin)
Actualiza los enabledPermissions de una cuenta. Los principales recién creados comienzan sin permisos y no pueden autenticarse, enviar ni recibir correo hasta que se les concedan permisos. Requiere configuración de la API de administración.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
account | string | sí | Nombre de la cuenta objetivo |
action | string | no | set (reemplazar lista, predeterminado), add (conceder) o remove (revocar) |
permissions | string[] | sí | Nombres de permisos (p. ej. email-send, authenticate, imap-authenticate, imap-append) |
reset_password (admin)
Restablece la contraseña de una cuenta. Si se omite password, se genera una contraseña aleatoria segura de 24 caracteres. La nueva contraseña se devuelve en texto plano en la respuesta para que pueda entregarse al usuario. Requiere configuración de la API de administración.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
account | string | sí | Nombre de la cuenta objetivo |
password | string | no | Nueva contraseña. Se genera automáticamente si se omite. |
get_dsn_accounts (admin)
Lista las direcciones de correo que tienen habilitados los informes de entrega DSN (Delivery Status Notification). Requiere configuración de la API de administración.
set_dsn_accounts (admin)
Establece qué direcciones de correo reciben informes de entrega DSN (SUCCESS + FAILURE). Reemplaza la lista completa. Requiere configuración de la API de administración.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
accounts | string[] | sí | Direcciones de correo para las que habilitar informes de entrega |
check_sent (admin)
La primera herramienta a la que acudir al verificar cualquier correo saliente — formularios de contacto, wp_mail() de WordPress, mailers de facturas/estados de cuenta, restablecimientos de contraseña, correo transaccional — cualquier cosa que necesite saber "¿salió esto del servidor?".
Lee el /api/logs de Stalwart (autoritativo) y agrupa por queueId: envío → intento de entrega → estado final (delivery.delivered / delivery.dsn-success / delivery.failed) más code/hostname del MX ascendente.
NO busques primero en los buzones — los envíos SMTP no se guardan automáticamente en Enviados. Empieza aquí.
Cómo funciona la obtención del registro (lección de producción):
La consulta filter= del lado del servidor de Stalwart a menudo se cuelga con archivos de registro diarios de varios GB. Por defecto, esta herramienta obtiene las filas más recientes de scan_limit sin filtrar y aplica to/from/filter en el cliente (rápido: ~300 ms para 1000 filas). Pasa use_server_filter=true solo si sabes que lo necesitas (p. ej. un queueId único en un host poco cargado).
Casos de uso comunes:
- "¿Envió el mailer de facturas / formulario de contacto a
ap@client.com?" - "¿Se entregó un correo transaccional — qué devolvió Gmail?"
- "¿Por qué rebotó — código SMTP remoto?"
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
to | string | no | Correo o dominio del destinatario (subcadena en el cliente). Prefiere esto para comprobaciones de formularios de contacto. |
from | string | no | Correo o dominio del remitente (subcadena en el cliente). |
filter | string | no | Subcadena adicional en el cliente (p. ej. queueId). |
since | string | no | Límite inferior RFC3339 en las marcas de tiempo de los eventos. |
scan_limit | number | no | Filas de registro más recientes a obtener (predeterminado 500, máximo 5000). Auméntalo si el envío es más antiguo que la ventana. |
use_server_filter | bool | no | Predeterminado false. Si es true, pasa el filtro a Stalwart (puede agotar el tiempo de espera en hosts ocupados). |
Devuelve messages_found, delivered_count, failed_count, cronologías por mensaje (mx_code / mx_hostname), además de auth_events (éxito/fallo de autenticación de envío) y un log_window.
verify_account_auth
Comprueba si un nombre de usuario/contraseña es aceptado por Stalwart (mismo secreto que SMTP puerto 587). Úsalo cuando check_sent muestre sin envío — normalmente la aplicación tiene la contraseña incorrecta.
| Parámetro | Tipo | Obligatorio | Descripción |
|---|---|---|---|
username | string | sí | Correo de la cuenta (p. ej. hello@codechap.com) |
password | string | sí | Contraseña candidata (secreto de buzón, no de administración) |