your-mail-mcp
Acceso MCP de solo lectura y autoalojado al correo IMAP, reflejado en un maildir local e indexado por notmuch.
Documentación
your-mail-mcp
Tu correo ya contiene las respuestas: referencias de reservas, códigos de puerta, facturas, períodos de garantía, promesas que la gente hizo por escrito. Este servidor permite que tu asistente de IA las encuentre, y solo puede leer.
Pregúntale cosas como:
- "Encuentra la referencia de reserva para el ferry de junio."
- "¿Cuál era la contraseña del wifi que el hotel envió el verano pasado?"
- "¿Qué respondió el contador sobre el IVA, y cuándo?"
- "Reúne todo entre yo y el constructor sobre el techo, en orden, y resume quién prometió qué."
- "¿Qué llegó esta mañana, en todas mis cuentas, que realmente necesita mi atención?"
Úsalo para:
- Búsqueda que entiende preguntas. Búsqueda de texto completo en todo tu historial, cada cuenta en un solo índice, formulada como piensas.
- Triaje desde tu teléfono. Un resumen matutino de lo que llegó durante la noche, con el spam ya filtrado, desde donde estés.
- Correo como contexto para otro trabajo. Extrae los requisitos del cliente del hilo y llévalos a tu sesión de codificación o escritura.
- Agentes que puedes dejar ejecutándose. El proceso no tiene ninguna ruta que envíe, elimine o mueva un mensaje. Un correo malicioso que llegue a tu asistente se lee, y eso es todo lo que puede sucederle. Los resúmenes programados y los agentes siempre activos son algo tranquilo de ejecutar.
La configuración son dos archivos y docker compose up -d. Consulta Inicio rápido.
Cómo funciona
Un servidor MCP autoalojado. Duplica una o más cuentas IMAP en un maildir local con mbsync, las indexa con notmuch y responde llamadas de herramientas desde ese índice. Las aplicaciones Claude y ChatGPT se conectan por HTTPS con OAuth; Claude Code, Codex, Cursor y Claude Desktop se conectan por stdio en la misma máquina. Cualquier cliente MCP funciona, así que si quieres privacidad total puedes conectar uno respaldado por un LLM local y tu correo nunca sale de tu máquina.

El correo solo se mueve de izquierda a derecha en esa imagen. La duplicación es solo de extracción
por configuración. La única conexión que el código Go hace hacia un proveedor es
un IMAP LIST por cuenta, para saber cómo llama ese servidor a sus carpetas de
spam y papelera; nunca selecciona un buzón y nunca obtiene un mensaje.
Seguridad tiene la lista completa de lo que el proceso no puede hacer. La fuente del
diagrama es
docs/diagrams/how-it-works.html.
Inicio rápido
En tu máquina, para tu máquina. Docker es el único requisito; la imagen
en ghcr.io/wildsurfer/your-mail-mcp está construida por CI para amd64 y arm64.
mkdir your-mail && cd your-mail
curl -fsSLO https://raw.githubusercontent.com/wildsurfer/your-mail-mcp/main/compose.yaml
curl -fsSL https://raw.githubusercontent.com/wildsurfer/your-mail-mcp/main/accounts.example.json -o accounts.json
Pon tus cuentas en accounts.json. ${WORK_PASS} se reemplaza desde el
entorno, por lo que el archivo en sí no contiene ninguna contraseña:
{
"accounts": [
{ "name": "work", "host": "imap.gmail.com", "user": "you@example.com", "password": "${WORK_PASS}" },
{ "name": "personal", "host": "imap.mail.me.com", "user": "you", "password": "${PERSONAL_PASS}" }
]
}
Pon las contraseñas en .env junto a compose.yaml:
# .env
WORK_PASS=your-gmail-app-password
PERSONAL_PASS=your-icloud-app-specific-password
compose.yaml pasa WORK_PASS y PERSONAL_PASS al contenedor. Una
cuenta con otro nombre de variable necesita que ese nombre se agregue bajo
environment: allí también.
Dos detalles del proveedor cuestan a la gente más tiempo. Gmail acepta solo una contraseña
de aplicación por IMAP, y las contraseñas de aplicación requieren que la verificación en dos pasos
esté activada primero. iCloud quiere el nombre corto antes de @icloud.com como user; la
dirección completa falla al iniciar sesión. Cada clave del archivo está en
la referencia.
Estos dos archivos contienen las contraseñas de tu correo. Mantén el directorio fuera del control de versiones y fuera de las copias de seguridad que salgan de la máquina.
docker compose up -d
docker compose logs -f # watch the first sync
El correo de la bandeja de entrada de hoy se puede buscar en minutos. El historial completo sigue
al ritmo que el proveedor permita, y la herramienta status informa hasta dónde ha
llegado. Una cuenta grande de Gmail tarda días, porque Google limita las descargas IMAP
a unos 2.5GB por día; establece SYNC_TIMEOUT=8h en .env para esa primera
duplicación. Notas del proveedor tiene los detalles.
Luego conecta un cliente. Claude Code:
claude mcp add your-mail -- docker exec -i your-mail-mcp your-mail-mcp stdio
Cursor y VS Code lo agregan con un clic, una vez que la pila está activa:
Claude Desktop, Cursor, Codex y otros clientes stdio
Cualquier cliente que inicie un servidor MCP como comando:
{ "command": "docker", "args": ["exec", "-i", "your-mail-mcp", "your-mail-mcp", "stdio"] }
Cada sesión es un puente hacia el contenedor en ejecución, por lo que cada cliente ve el mismo índice y la misma sincronización. Cierra el cliente y la sesión se va con él.
Claude Code también puede tomarlo como complemento, lo que agrega el servidor y una
habilidad email que conoce la sintaxis de consulta:
/plugin marketplace add wildsurfer/your-mail-mcp
/plugin install your-mail@your-mail-mcp
Sin una pila en ejecución,
docker run -i --rm --env-file .env -v index:/index -v mail:/mail -v ./accounts.json:/config/accounts.json:ro ghcr.io/wildsurfer/your-mail-mcp
inicia un demonio para la vida de una sesión. Está bien para echar un vistazo; usa compose para
cualquier cosa que quieras mantener actualizada.
Úsalo desde tu teléfono
Las aplicaciones de smartphone Claude y ChatGPT alcanzan un conector a través de los servidores del proveedor, por lo que el servidor necesita una dirección HTTPS pública. Un túnel le da una: el túnel llama hacia afuera, nada escucha en tu red doméstica y el correo permanece en tu máquina.
Con Tailscale instalado, un comando, igual en macOS y Linux:
tailscale funnel --bg 8080
Imprime un nombre de host como https://your-machine.your-tailnet.ts.net, y
--bg lo mantiene ejecutándose entre reinicios. Pon ese nombre de host en .env junto
con una frase de contraseña, luego reinicia:
# .env
PUBLIC_URL=https://your-machine.your-tailnet.ts.net
OAUTH_PASSPHRASE=pick-a-long-one-you-can-type-on-a-smartphone
docker compose up -d
OAUTH_PASSPHRASE es la única credencial entre internet y tu
correo. Una suposición incorrecta cuesta un segundo y las suposiciones se serializan, y ninguna
de esas cosas salva una frase de contraseña corta. Usa una larga que aún puedas escribir en un
teléfono.
Funnel necesita certificados HTTPS y el atributo de nodo Funnel habilitado para
tu tailnet; la CLI ofrece agregar la línea de política la primera vez.
tailscale funnel status muestra lo que está expuesto, y
tailscale funnel --https=443 off lo desactiva.
Ahora agrega el conector. Ni la aplicación de smartphone Claude ni la de ChatGPT pueden agregar uno, así que lo haces una vez en la web, y luego aparece en el teléfono.
- En claude.ai o en Claude Desktop, abre Configuración → Conectores y agrega un conector personalizado.
- Dale un nombre y la URL
<PUBLIC_URL>/mcp. Deja los campos avanzados de OAuth vacíos; el servidor registra clientes por sí mismo. - Claude abre la página de consentimiento. Ingresa tu
OAUTH_PASSPHRASE. - Abre la aplicación Claude en tu teléfono. El conector ya está allí; actívalo para una conversación desde el menú de herramientas en el compositor.
PUBLIC_URL tiene que coincidir exactamente con lo que escribes en el cliente. El servidor
publica PUBLIC_URL + /mcp como el resource en sus metadatos OAuth, y una
discrepancia allí es la razón más común por la que un conector se niega a agregarse.
Cloudflare Tunnel en lugar de Tailscale, en tu propio dominio
Usa esto para un nombre de host en un dominio que poseas. mail.example.com a continuación tiene que
ser tu dominio, ya agregado a tu cuenta de Cloudflare; Cloudflare no
entrega nombres de host para túneles con nombre.
cloudflared tunnel login
cloudflared tunnel create your-mail
create imprime el UUID del túnel y la ruta del archivo de credenciales que
escribió; cloudflared tunnel list imprime el UUID nuevamente si lo pierdes. Enruta
el nombre de host, luego escribe ~/.cloudflared/config.yml:
cloudflared tunnel route dns your-mail mail.example.com
tunnel: your-mail
credentials-file: /Users/you/.cloudflared/f9e2….json # the path create printed
url: http://localhost:8080
cloudflared tunnel run your-mail
Para mantenerlo ejecutándose: en Linux, sudo cloudflared service install. En macOS,
instálalo a través de Homebrew y usa brew services start cloudflared,
porque la ruta de instalación de sudo busca su certificado bajo el directorio
inicio del usuario root y no encontrará el que cloudflared tunnel login escribió en
el tuyo.
Luego establece PUBLIC_URL=https://mail.example.com en .env y
docker compose up -d.
ChatGPT, y Claude Code o Codex desde otra máquina
ChatGPT. Los conectores MCP personalizados están detrás del modo desarrollador, que necesita una cuenta Pro, Plus, Business, Enterprise o Education y solo está disponible en la web.
- En ChatGPT en la web, abre Configuración → Seguridad e inicio de sesión y activa Modo desarrollador. En espacios de trabajo Business y Enterprise, un administrador puede tener que permitirlo primero.
- Agrega un conector para un servidor MCP remoto con la URL
<PUBLIC_URL>/mcpy OAuth como autenticación. ChatGPT admite registro dinámico de clientes, por lo que no hay nada que pegar. - Aprueba la página de consentimiento con tu
OAUTH_PASSPHRASE. - Abre ChatGPT en tu teléfono y habilita el conector en un chat.
Estos menús se mueven. Si los nombres anteriores no coinciden con lo que ves, busca el modo desarrollador en la configuración, luego el lugar que agrega un conector por URL. ChatGPT desactiva algunas acciones de escritura MCP en móvil, lo que no cambia nada aquí porque este servidor no tiene ninguna.
Claude Code:
claude mcp add --transport http your-mail https://your-host/mcp
Codex:
codex mcp add your-mail --url https://your-host/mcp
codex mcp login your-mail
Ejecútalo en un servidor
Elige esto cuando la duplicación deba permanecer activa esté o no encendida tu máquina. Cuesta unos pocos dólares al mes y un verdadero intercambio: una copia completa en texto plano de tu correo se mueve a un disco alquilado, con las contraseñas de aplicación al lado. La instalación es el inicio rápido más un túnel, en la computadora de otra persona, y la máquina necesita endurecimiento antes de que contenga tu correo. Ambos están en docs/server.md.
Las herramientas
Once herramientas, todas de solo lectura:
| Herramienta | Qué hace |
|---|---|
search | Busca correo. Devuelve resúmenes de hilos como JSON. |
ids | Devuelve los ids de mensajes que coinciden con una consulta. |
files | Devuelve las rutas de archivo maildir que coinciden con una consulta. |
count | Cuenta los mensajes que coinciden con una consulta. |
show | Muestra un mensaje: encabezados y cuerpo decodificado, como JSON. |
thread | Muestra el hilo completo que contiene un mensaje. Excluye respuestas de spam/papelera por defecto; establece include_excluded para incluirlas. |
text | Devuelve el cuerpo de texto plano de un mensaje, convirtiendo HTML. |
folders | Lista cuentas, sus carpetas, etiquetas de índice, y la última sincronización y último error de cada cuenta. |
refresh | Sincroniza cada carpeta de una cuenta o todas las cuentas ahora, luego reindexa. Espera hasta 20 segundos; si el pase aún se está ejecutando, lo dice. |
status | Salud de sincronización por cuenta: finalización de la primera sincronización, última sincronización, mensajes indexados, errores y retroceso. |
attachment | Un adjunto o parte MIME de un mensaje, por número de parte de show. Imágenes en línea, texto (JSON y XML incluidos) como bloque marcado, otros binarios como enlace de descarga firmado. |
search, ids, files y count toman una consulta notmuch (from:, to:,
subject:, tag:, folder:, date:2026-01-01..2026-06-30, combinadas con
y/o/no), un account opcional para limitar a una cuenta, y pueden incluir
spam y papelera con include_excluded. El spam y la papelera se descubren por
cuenta a través de RFC 6154 SPECIAL-USE, por lo que la exclusión funciona sean cuales sean
los nombres de esas carpetas y en cualquier idioma. Mientras la duplicación de una cuenta
aún se está llenando, estas cuatro herramientas anteponen una nota que nombra la cuenta y cuántos
mensajes están indexados hasta ahora.
Los adjuntos se enumeran en show y thread y se sirven con la herramienta attachment
una parte a la vez: imágenes en línea hasta 5MB, partes textuales como texto
marcado, y otros binarios como un enlace firmado de corta duración a
GET /attachment/{id}/{part} (un token de portador también funciona allí). Sin un
listener HTTP, un binario sobredimensionado se guarda bajo /index/attachments/ y
la herramienta devuelve la ruta a docker cp. Ese directorio está limitado a 1GB;
los archivos más antiguos se eliminan primero.
Por qué no uno de los otros
Hay alrededor de cuarenta servidores MCP de correo en GitHub. Casi todos hablan
IMAP en vivo y incluyen una ruta de envío, que es lo opuesto a ambas elecciones en las que
se basa este servidor. Dos están lo suficientemente cerca como para mencionarlos.
igor47/notmuchproxy es lo más parecido
que ya existía, y una gran parte de la razón por la que este tiene la forma
que tiene. Lee un archivo de notmuch que mantienes actualizado tú mismo, no tiene
ruta de escritura, y acepta un token de portador o OIDC completo. Su validación de consultas,
que rechaza un prefijo desconocido con una explicación, se reimplementa aquí como
validateQuery. Dos cosas difieren: asume que ya ejecutas mbsync y
notmuch, mientras que este servidor genera la configuración de mbsync, sincroniza cada
cuenta en paralelo y descubre basura y papelera a través de IMAP; y no tiene
parámetro account. Si ya tienes una configuración de notmuch con la que estás contento,
notmuchproxy es lo más pequeño de implementar y deberías usarlo en lugar de
este.
hgn/mcp-server-notmuch es solo stdio,
así que un cliente en una máquina, y su manejo de contenido no confiable es
el mejor del estudio. El único punto de estrangulamiento render() aquí, que marca
cada byte de texto de correo en un solo lugar para que ninguna herramienta individual pueda olvidar
hacerlo, proviene de su render.py.
El estudio completo, incluyendo qué afirmaciones se leyeron en el código fuente y cuáles se
tomaron de un README, está en
docs/research/email-mcp-landscape.md.
Seguridad
Lee esto antes de apuntarlo a un buzón que te importa.
No puede escribir. La configuración de mbsync generada para cada cuenta
lleva Sync Pull, Create Near, Remove None y Expunge None (o,
para una cuenta con expunge_local configurado, Expunge Near, que elimina archivos locales
solo), y el programa escribe ese archivo él mismo, así que nada en él puede
ser editado para convertirse en un push.
La única operación IMAP en el código Go es LIST, emitida por cuenta al
inicio y cada hora para encontrar las carpetas de basura y papelera; una cuenta con
exclude_folders configurado a mano omite incluso eso. El proceso no tiene ninguna ruta que
envíe, elimine, mueva o etiquete un mensaje, y nada en él tiene acceso de
escritura a ninguna cuenta.
El correo eliminado permanece en el espejo. El correo que eliminas en el servidor se mantiene
en disco y se oculta de la búsqueda mediante la etiqueta deleted de notmuch. Configura
expunge_local: true en una cuenta para eliminar físicamente esas copias locales
en su lugar. La cuenta nunca se escribe, pero el espejo entonces deja
de ser una copia de seguridad: lo que desaparece remotamente desaparece localmente en la siguiente
pasada.
Qué tan probado está esto. Un autor, un operador, tres cuentas reales: una iCloud y dos Gmail. Sin revisión de seguridad de terceros, y nadie más lo ha implementado. notmuchproxy tiene cero estrellas y una historia de producción más convincente que esta.
Las contraseñas son texto plano dentro del contenedor. Las contraseñas de las cuentas
provienen del entorno y se escriben al inicio en una configuración de mbsync generada
con modo de archivo 0600. Ese archivo no está cifrado. Cualquier cosa que
pueda leer el entorno del contenedor, o ese archivo, puede leerlas. El cifrado
del disco, quién puede ejecutar comandos dentro del contenedor y el acceso al host son
responsabilidad del operador; el servidor no afirma cifrar credenciales
en reposo.
Una frase de contraseña, un consentimiento. OAUTH_PASSPHRASE se verifica en tiempo
constante y controla todo el servidor con un único secreto compartido. No es un
sistema de credenciales por usuario, y todos los que tengan la frase de contraseña ven
todo el buzón. No cifra nada en reposo. Trátala a ella y a las
contraseñas de correo con el mismo cuidado.
Un buzón es un almacén de secretos. Los restablecimientos de contraseña, los códigos de inicio de sesión y los enlaces mágicos llegan por correo, así que solo el acceso de lectura es suficiente para tomar el control de cuentas si cae en las manos equivocadas o en la sesión de IA equivocada. El diseño de solo lectura y los marcadores de contenido no confiable eliminan la ruta de escritura y el canal de instrucciones; no hacen que los contenidos del correo sean inofensivos. Conecta clientes en los que confíes. Los flujos de trabajo de agentes que necesitan sus propios buzones necesitan sus propias direcciones, lo cual es una herramienta diferente.
Una brecha conocida. Los resúmenes de hilos de search incluyen un nombre para mostrar para cada
mensaje en un hilo coincidente, que el remitente controla. Un mensaje en una
carpeta excluida por defecto (basura, papelera) aún puede poner su propio
nombre elegido por el atacante frente a ti de esta manera, aunque su cuerpo nunca
lo haga. thread y show no están sujetos a esto. No está corregido en esta
versión.
Para un servidor que enfrenta internet, docs/server.md enumera los pasos de endurecimiento en el orden de cuánto te aporta cada uno.
Referencia
- El archivo de cuentas: cada clave, con valores predeterminados.
- Variables de entorno: intervalo de
sincronización y tiempo de espera, dirección del listener,
INIT_MIRROR. - Notas del proveedor: iCloud, Gmail, Dovecot.
- Solución de problemas: los rechazos al inicio, y por qué la basura a veces no se excluye.
- Sin Docker: binarios de lanzamiento y a qué programas externos llaman.
- Ejecutándolo en un servidor: script de instalación, endurecimiento, tu propio dominio con Caddy.
- Actualizando desde 0.3.x.
- Especificación de diseño y el estudio de servidores MCP de correo.