Pylos
Lee, busca y redacta correos electrónicos en cualquier buzón IMAP, con cada mensaje delimitado como entrada no confiable y el envío restringido a una lista de permitidos.
Documentación
pylos-mcp
Servidor MCP de correo electrónico enfocado en lectura y endurecido contra inyección de prompts, para cualquier proveedor IMAP.
Cualquier persona en el mundo puede poner texto en tu bandeja de entrada, y en el momento en que un asistente de IA lee esa bandeja, cualquier persona en el mundo puede poner texto frente a tu asistente. pylos-mcp es un servidor MCP de correo construido alrededor de ese hecho. Permite que Claude, o cualquier cliente MCP, busque, lea y redacte tu correo mientras trata cada mensaje como lo que realmente es: entrada de un desconocido. El contenido del buzón se delimita como datos antes de que el modelo lo vea, y no existe un campo bcc para que un correo inyectado copie silenciosamente a alguien.
Se ejecuta en tu máquina y habla IMAP simple, por lo que funciona con Gmail, iCloud, Yahoo, GMX, Fastmail, mailbox.org, Posteo, Proton vía Bridge, o cualquier cosa autoalojada, y tus credenciales nunca salen de casa. De serie puede leer y redactar. Cualquier cosa más arriesgada—mover, enviar, eliminar—es un interruptor separado que permanece apagado hasta que lo actives.
Lo que esto nunca puede hacer
El correo es texto controlado por atacantes, por lo que los límites duros residen en la arquitectura, no en un prompt. Ningún mensaje puede convencer al servidor de violar ninguno de estos límites.
- Ningún HTML crudo llega jamás al modelo. Los cuerpos provienen de la parte de texto plano cuando existe, o se convierten a texto en caso contrario. Los caracteres invisibles que ocultan instrucciones a un lector humano mientras permanecen legibles para un modelo se eliminan.
- El contenido no confiable está delimitado. Todo lo del buzón—cuerpos, asuntos, nombres de remitentes, listados de carpetas, texto de scripts Sieve—se envuelve en un delimitador etiquetado antes de que el modelo lo vea, y el delimitador se neutraliza dentro del contenido, de modo que un mensaje no pueda falsificar su salida de la cerca. Las pocas líneas fuera de ella son escritas por el servidor y nunca llevan contenido de mensajes.
- No existe ningún campo
bccen ninguna parte, ni en borradores ni en correo enviado. Un destinatario en copia oculta recibe una copia completa de un mensaje sin aparecer en él, exactamente la invisibilidad que un correo inyectado desea. El campo está ausente en lugar de protegido, así que no hay nada que pueda convencer al modelo. - Eliminar un mensaje lo mueve a la Papelera. No hay expurgo ni opción de borrado permanente, y el resultado de la herramienta nunca afirma una permanencia que este servidor no ofrece.
- El acceso a Sieve es de solo lectura, permanentemente. Las reglas de filtrado del lado del servidor pueden reenviar, responder automáticamente y notificar, cada una un canal de exfiltración que sobrevive a la revocación de la contraseña de aplicación o a la desinstalación de este servidor. El acceso de escritura se omite por completo, no se defiende.
El envío es la otra puerta arriesgada, así que comienza cerrada incluso con la capacidad send activada. Hasta que SEND_ALLOWLIST diga quién puede ser destinatario, cada envío se rechaza, y el rechazo nombra las dos formas de abrir la puerta. SEND_ALLOWLIST=* permite a cualquiera, visiblemente y a propósito.
La delimitación reduce el riesgo de inyección de prompts; nada lo elimina. El modelo aún lee texto escrito por desconocidos, así que trata cada respuesta que incluya contenido de mensajes como entrada no confiable, no como verdad absoluta. Las notas de diseño más detalladas están en SECURITY.md.
Inicio rápido
Añade el servidor a la configuración de tu cliente MCP. Para Claude Desktop, ese archivo es claude_desktop_config.json.
{
"mcpServers": {
"pylos-mcp": {
"command": "npx",
"args": ["-y", "pylos-mcp"],
"env": {
"PROVIDER": "mailbox.org",
"EMAIL_USER": "you@example.com",
"EMAIL_PASSWORD": "your-app-password"
}
}
}
}
Usa una contraseña de aplicación, no la contraseña normal de tu cuenta. La siguiente sección dice qué proveedores insisten en una. Reinicia el cliente y aparecerán las herramientas de lectura y redacción. Los cambios posteriores de configuración necesitan el mismo tratamiento: una capacidad recién habilitada solo registra sus herramientas tras un reinicio completo del cliente, y en Claude Desktop alternar el servidor de apagado a encendido no siempre es suficiente.
Configuración del proveedor
Establece PROVIDER a uno de gmail, icloud, yahoo, gmx, fastmail, mailbox.org o posteo y los hosts y puertos IMAP, SMTP y Sieve correspondientes se completan solos.
Gmail, iCloud, Yahoo y Fastmail rechazan contraseñas de cuenta normales a través de IMAP, así que una contraseña de aplicación es la única vía. Google solo ofrece una una vez que la Verificación en dos pasos está activada, e iCloud quiere autenticación de dos factores en el Apple ID primero. mailbox.org, GMX y Posteo aceptan la contraseña de cuenta, aunque una contraseña de aplicación sigue siendo la opción más prudente.
Proton Mail pasa por Bridge. Deja PROVIDER sin establecer y configura IMAP_HOST y IMAP_PORT con lo que muestre Bridge. El nombre de usuario es la dirección que Bridge te dice usar, y la contraseña es la de los detalles del buzón de Bridge, sección IMAP, no la contraseña de tu cuenta Proton. Bridge usa STARTTLS por defecto mientras este servidor solo habla TLS implícito, así que cambia Bridge a SSL en sus Ajustes avanzados. El certificado de Bridge es autofirmado, así que expórtalo y apunta TLS_CA_FILE a él.
Los servidores autoalojados también dejan PROVIDER sin establecer. Configura IMAP_HOST, más SMTP_HOST o SIEVE_HOST cuando esos niveles opcionales estén habilitados, y autentícate como requiera tu servidor. Para una CA privada, apunta TLS_CA_FILE al certificado de la CA. La verificación en sí siempre permanece activada; esto solo añade un ancla de confianza.
Capacidades
Las capacidades son interruptores independientes, no una escalera. La lectura siempre está activada, la redacción comienza activada, todo lo demás permanece apagado hasta que lo listes en CAPABILITIES. Un nivel apagado tiene sus herramientas excluidas por completo de la lista de herramientas, no solo rechazadas, de modo que un modelo nunca aprende que existe una herramienta deshabilitada.
| Nivel | Predeterminado | Herramientas |
|---|---|---|
read | siempre activado | search_emails, get_email, get_attachment, list_folders |
drafts | activado | create_draft |
manage | apagado | move_email, set_flags |
send | apagado | send_email |
delete | apagado | delete_email |
sieve-read | apagado | list_sieve_scripts, get_sieve_script |
Habilita más con una lista separada por comas, por ejemplo CAPABILITIES=drafts,manage,delete.
Mover un mensaje a la Papelera es un borrado por otra vía, así que move_email rechaza la Papelera a menos que delete también esté activado.
Advertencias de sospecha
El servidor también te dice qué es sospechoso de un mensaje. Cinco detectores anotan los resultados de get_email con una línea sobre el contenido, escrita enteramente con las palabras del servidor y nunca citando el contenido que las disparó.
Warnings: hidden_text (412 hidden characters via display:none), encoded_blob (base64 run of 600 characters)
- Texto oculto. Texto oculto con los trucos CSS comunes,
display:none, fuentes invisibles o de un píxel, colores de texto y fondo coincidentes, posicionamiento fuera de pantalla,aria-hidden. Cubre estilos y atributos en línea, un cable trampa, no un motor de renderizado. Los boletines ocultan legítimamente texto breve de vista previa, así que la advertencia solo se dispara más allá de un umbral, a menos que el texto oculto contenga una frase similar a una instrucción o una secuencia codificada, lo que advierte a cualquier longitud. El texto permanece en el cuerpo por defecto.STRIP_HIDDEN_TEXT=truelo elimina en su lugar, con una nota de cuánto se eliminó. - Patrones de instrucción. Un conjunto deliberadamente pequeño de frases que se dirigen a una IA como objetivo de instrucción, como "ignora las instrucciones anteriores". Pequeño para que una bandeja de entrada que simplemente hable de IA permanezca en silencio. Extiéndelo con
FLAG_EXTRA_PATTERNS, frases separadas por barras verticales que se comparan como literales sin distinción de mayúsculas. Los asuntos, líneas de remitente y nombres de archivos adjuntos se verifican además del cuerpo, y los espacios extra o saltos de línea dentro de una frase no la ocultan. - Blobs codificados. Secuencias largas y continuas de base64 o hexadecimal en el cuerpo, reportadas con su longitud y nunca decodificadas.
- Discrepancia de remitente. Una dirección Reply-To en un dominio diferente al de la dirección From, o un nombre visible From que lleva una dirección en un dominio que el remitente real no usa. Los subdominios cuentan como el mismo dominio, así que un proveedor que responde desde uno propio permanece en silencio. La dirección Reply-To en sí se muestra dentro del contenido delimitado, para que el modelo pueda ver a dónde iría realmente una respuesta.
- Scripts mixtos. Palabras que mezclan letras latinas con letras cirílicas o griegas dibujadas para parecer latinas, como un "paypal" escrito con una а cirílica. Solo cuentan las letras que se parecen, así que unidades como
μmy texto ruso o griego ordinario permanecen en silencio.
Las advertencias anotan, nunca retienen. El mensaje siempre regresa, y cada detector tiene su propio interruptor en la referencia a continuación.
Referencia de configuración
Toda la configuración son variables de entorno, validadas al inicio. Una configuración inválida falla inmediatamente con un mensaje accionable, nunca a mitad de una conversación. Un valor vacío cuenta como no establecido, ya que los gestores de paquetes llenan los campos opcionales que los usuarios dejan en blanco con cadenas vacías.
| Variable | Valor por defecto | Notas |
|---|---|---|
PROVIDER | ninguno | Uno de gmail, icloud, yahoo, gmx, fastmail, mailbox.org, posteo. Completa los hosts y puertos de IMAP, SMTP y Sieve. |
EMAIL_USER | requerido | Inicio de sesión de la cuenta. |
EMAIL_PASSWORD | ninguno | Contraseña de aplicación. Se requiere esta o EMAIL_PASSWORD_CMD. |
EMAIL_PASSWORD_CMD | ninguno | Comando cuya salida estándar es la contraseña, como una búsqueda en el llavero o pass, para que el secreto nunca esté en el archivo de configuración del cliente. Tiene 60 segundos para terminar. |
IMAP_HOST / IMAP_PORT | preestablecido / 993 | Valores explícitos para servidores autohospedados. Establece cualquiera para anular el preestablecido. |
SMTP_HOST / SMTP_PORT | preestablecido / 465 | Requerido solo cuando send está habilitado. |
SIEVE_HOST / SIEVE_PORT | IMAP_HOST / 4190 | Se usa solo cuando sieve-read está habilitado. |
CAPABILITIES | drafts | Lista separada por comas de niveles más allá de read, que siempre está incluido. |
MAX_BODY_KB | 64 | Límite de truncamiento del cuerpo del mensaje. |
MAX_ATTACHMENT_MB | 25 | Tope de tamaño de adjuntos, verificado contra el tamaño que el servidor declara antes de descargar cualquier byte. |
DOWNLOAD_DIR | ~/Downloads | Dónde escribe archivos get_attachment. |
SEND_SESSION_CAP | 5 | Llamadas exitosas a send_email permitidas por vida útil del proceso del servidor. |
SEND_SAVE_COPY | true | Agrega una copia de cada mensaje enviado a la carpeta de Enviados, marcado como leído. Desactívalo para proveedores que ya archivan el correo enviado en el servidor (Gmail lo hace), que de otro modo mostrarían duplicados. |
SEND_ALLOWLIST | ninguno (envío cerrado) | Direcciones separadas por comas o patrones de *@domain, o solo * para permitir a cualquiera. Con send habilitado y sin valor establecido, cada envío se rechaza y el rechazo explica esta variable. Un valor explícitamente vacío tampoco permite a nadie. Una entrada que nunca podría coincidir, como un dominio simple, falla al inicio. |
DRAFTS_NO_RECIPIENTS | false | Cuando true, create_draft rechaza to y cc por completo. Los borradores no llevan direccionamiento y se les agrega más tarde en tu cliente de correo. |
FLAG_HIDDEN_TEXT | true | Advertir cuando el HTML del mensaje oculta texto con estilos en línea o aria-hidden. |
FLAG_INSTRUCTION_PATTERNS | true | Advertir cuando el cuerpo, el asunto, la línea del remitente o los nombres de adjuntos contienen frases que tratan a una IA como objetivo de instrucciones. |
FLAG_ENCODED_BLOBS | true | Advertir sobre secuencias largas contiguas de base64 o hex en el cuerpo. |
FLAG_SENDER_MISMATCH | true | Advertir cuando una dirección Reply-To está en un dominio diferente al de la dirección From, o el nombre visible de From lleva una dirección en otro dominio. |
FLAG_MIXED_SCRIPT | true | Advertir cuando una palabra mezcla letras latinas con caracteres similares cirílicos o griegos. |
STRIP_HIDDEN_TEXT | false | Eliminar el texto oculto detectado del cuerpo en lugar de solo advertir, con una nota de cuánto se eliminó. Requiere que FLAG_HIDDEN_TEXT permanezca activado; la combinación con el detector desactivado se rechaza al inicio. |
FLAG_EXTRA_PATTERNS | ninguno | Frases separadas por barras verticales agregadas al conjunto de patrones de instrucciones, coincidentes como subcadenas literales sin distinción de mayúsculas. |
TLS_CA_FILE | ninguno | Ruta a un certificado CA PEM agregado como ancla de confianza adicional, para servidores autohospedados con una CA privada. La verificación de certificados no se puede desactivar; esto solo extiende lo que se confía. Configurarlo confía en el almacén raíz incluido de Node más este archivo, lo que significa que las anclas agregadas a través de NODE_EXTRA_CA_CERTS no están en ese conjunto. Si dependes de esas, apunta TLS_CA_FILE al mismo certificado. |
Expectativas de mantenimiento
pylos-mcp está construido para el uso diario del autor y se mantiene sobre esa base. Las issues y pull requests son bienvenidas, y CONTRIBUTING.md lleva una lista de deseos de direcciones que realmente ayudarían. El alcance se mantiene deliberadamente estrecho, así que si necesitas algo más amplio de lo que permite la postura de seguridad, haz un fork. El código base es deliberadamente lo suficientemente pequeño para que eso sea agradable.
Desarrollo
npm install
npm test # unit and MCP-layer tests, entirely offline
npm run test:integration # starts a disposable local Dovecot container, tests against it, tears it down
npm run build
Ninguna prueba en este proyecto se conecta a un buzón real, ni en desarrollo ni en CI. npm test ejecuta simulacros en proceso, y npm run test:integration levanta su propio contenedor local de Dovecot mediante Docker, sembrado con mensajes de prueba sintéticos, y lo elimina cuando la ejecución termina.