Gmail Manager
Servidor MCP de Gmail (33 herramientas) con lista de destinatarios permitidos opcional y registro de auditoría local
Documentación
mcp-gmail-manager
Un servidor integral de Gmail Model Context Protocol: 35 herramientas que cubren enviar/vista previa/confirmar, responder, reenviar, borradores, búsqueda, lectura, adjuntos, papelera, etiquetas, filtros, firma y respuesta automática de vacaciones.
Características de defensa en profundidad que lo distinguen de otros MCP de Gmail:
- Registro de auditoría a prueba de manipulación (activado por defecto): cada operación de escritura/envío/modificación/descarga añade una línea JSON a
audit.jsonl, encadenada por SHA-256 para que la manipulación parcial sea detectable. Incluye rotación de registros, verificación de cadena al inicio, auditoría de lectura opcional y una CLI demcp-gmail-manager-verify-log. - Lista de permitidos de destinatarios (desactivada por defecto): cuando está habilitada, cada operación saliente (
send_email,create_draft,reply_to_message,forward_message,create_filtercon una acciónforward, además de direcciones incrustadas en la firma y el cuerpo de vacaciones) verifica los destinatarios contra dominios configurados y direcciones explícitas. - Lista de permitidos + lista de denegados de rutas de adjuntos (lista de denegados activada por defecto): el MCP se niega a adjuntar o sobrescribir archivos de credenciales obvios (
~/.ssh/,~/.aws/,id_rsa,.env,token.json, etc.), cerrando el ataque de "LLM exfiltra clave SSH como adjunto". Consulte Notas de seguridad para el conjunto completo de denegaciones por defecto. - Marcadores de contenido contaminado por inyección de prompts: las herramientas de lectura (
get_message,get_thread,search_threads,list_drafts) envuelven los cuerpos y fragmentos de mensajes en etiquetas<untrusted-email-content>...</untrusted-email-content>. Las descripciones de herramientas instruyen al LLM a tratar el contenido envuelto como datos, no como instrucciones. - Escaneo de contenido saliente (desactivado por defecto): detección basada en regex de secretos en el asunto/cuerpo/firma/contenido de vacaciones (claves de acceso de AWS, tokens de Stripe/OpenAI/Anthropic/GitHub/GitLab/Google/Twilio, claves privadas PEM, JWTs, credenciales incrustadas en URLs). Bloquea el envío antes de que llegue a Gmail si un patrón coincide.
- Flujo de vista previa + confirmación de envío (desactivado por defecto):
preview_send_emailejecuta todas las salvaguardas y almacena la carga útil;confirm_send_email(preview_id)la entrega. Cuandosend_confirmation.required=true, elsend_emaildirecto está deshabilitado para que un LLM comprometido no pueda "vista previa X, luego enviar Y". - Limitación de velocidad (desactivada por defecto): limita los envíos salientes por hora para evitar que los bucles de agentes descontrolados agoten la cuota de Gmail.
- Ámbitos OAuth de privilegio mínimo: solicita solo
gmail.modify+gmail.settings.basic. NO solicitamail.google.com, por lo que la eliminación permanente no está disponible intencionalmente.
Consulte examples/config.with-allowlist.json para una configuración de modo institucional.
Herramientas (33)
| Grupo | Herramientas |
|---|---|
| Enviar / responder / reenviar | send_email, preview_send_email, confirm_send_email, reply_to_message, forward_message |
| Borradores | create_draft, list_drafts, send_draft, update_draft, delete_draft |
| Leer / perfil | get_profile, get_message, search_threads, get_thread |
| Adjuntos | get_message_attachments, download_attachment |
| Papelera | trash_message, untrash_message, trash_thread, untrash_thread |
| Etiquetas | list_labels, create_label, update_label, delete_label, label_message, unlabel_message, label_thread, unlabel_thread |
| Filtros | list_filters, create_filter, delete_filter |
| Firma | get_signature, update_signature |
| Respuesta de vacaciones | get_vacation_responder, set_vacation_responder |
Ámbitos OAuth solicitados: gmail.modify + gmail.settings.basic. NO solicita el ámbito de superusuario https://mail.google.com/: la eliminación permanente no es compatible intencionalmente.
Requisitos
- Python ≥ 3.10
- Un proyecto de Google Cloud con la API de Gmail habilitada y un cliente OAuth 2.0 (tipo Desktop)
- Una forma de reenviar
localhost:8765a su host de autenticación (normalmentessh -L 8765:localhost:8765 user@host)
Instalación
📖 ¿Prefiere un tutorial paso a paso con capturas de pantalla para cada etapa de la configuración de Google Cloud? Consulte la Guía de instalación. La sección siguiente cubre solo la instalación del paquete; la guía completa explica GCP, credenciales, OAuth, configuración de VM y registro en Claude Code.
Compatible con Linux, macOS y Windows. La ruta recomendada es pipx, que instala la CLI en un venv aislado y expone los puntos de entrada en $PATH.
Linux (Debian / Ubuntu / Mint / Fedora / Arch)
sudo apt install pipx # Debian / Ubuntu / Mint
sudo dnf install pipx # Fedora
sudo pacman -S python-pipx # Arch
pipx ensurepath # adds ~/.local/bin to PATH
# reopen shell or: source ~/.bashrc
pipx install mcp-gmail-manager
macOS
brew install pipx # or: python3 -m pip install --user pipx
pipx ensurepath # adds ~/.local/bin to PATH
# reopen shell or: source ~/.zshrc
pipx install mcp-gmail-manager
Windows (PowerShell)
# If you don't have Python yet: winget install --id Python.Python.3.12
python -m pip install --user pipx
python -m pipx ensurepath
# close and reopen PowerShell
pipx install mcp-gmail-manager
Advertencias de Windows: todo funciona, con tres notas:
- Permisos del archivo de token. En Linux/macOS el MCP escribe
token.jsonconchmod 0o600. En Windows no hay chmod POSIX, por lo que el archivo hereda su ACL de%USERPROFILE%: protegido contra otras cuentas de usuario, pero cualquier proceso que se ejecute como su usuario puede leerlo. Misma postura efectiva que la mayoría de las herramientas CLI de Windows que almacenan tokens OAuth. - La lista de denegados de rutas de adjuntos funciona. A partir de v0.3.2, la coincidencia de listas de denegados/permitidos normaliza las rutas a formato de barra diagonal mediante
Path.as_posix(), por lo que una ruta de Windows comoC:\Users\me\.ssh\id_rsase detecta correctamente con el patrón de denegación~/.ssh/por defecto. Confirmado por la suite de humo en ambas plataformas. - El puerto 8765 puede estar reservado por Windows. Hyper-V, WSL2 y Docker Desktop reservan rangos de puertos dinámicos que a veces incluyen 8765, lo que da
bind [127.0.0.1]:8765: Permission denieden el extremo local de un reenvío SSH-L. Verifique connetsh interface ipv4 show excludedportrange protocol=tcp. Si 8765 está reservado, establezcaGMAIL_MCP_AUTH_PORTa un puerto libre en ambos extremos (v0.3.3+):set GMAIL_MCP_AUTH_PORT=18765en el servidor antes de ejecutarmcp-gmail-manager-auth, y reenvíe ese mismo puerto:ssh -L 18765:localhost:18765 user@server.
Alternativa en cualquier sistema operativo: venv manual
python3 -m venv ~/.venv-mcp-gmail
~/.venv-mcp-gmail/bin/pip install mcp-gmail-manager
# Windows: python -m venv %USERPROFILE%\.venv-mcp-gmail
# Use the absolute path when registering with Claude Code (see below)
¿Por qué no un pip install simple a nivel de sistema? En distribuciones modernas basadas en Debian y Homebrew Python falla con error: externally-managed-environment (PEP 668): el sistema operativo protege su Python. Los métodos pipx y venv anteriores son las soluciones canónicas.
Desde el código fuente:
git clone https://github.com/arthjhon/mcp-gmail-manager.git
cd mcp-gmail-manager
pipx install .
Configuración de Google Cloud (una sola vez, ~10 minutos)
- Vaya a Google Cloud Console y cree un nuevo proyecto (o elija uno existente).
- Habilite la API de Gmail (no "Gmail MCP API": esa es el MCP remoto propio de Google; no es lo que queremos).
- Configure la pantalla de consentimiento OAuth:
- Tipo de usuario: Interno si su cuenta es parte de Google Workspace (sin expiración de token); de lo contrario Externo en modo Prueba (hasta 100 usuarios, los tokens de actualización expiran cada 7 días: consulte Expiración de token más abajo).
- Ámbitos: agregue
https://www.googleapis.com/auth/gmail.modifyyhttps://www.googleapis.com/auth/gmail.settings.basic. No agregue nada más. - Usuarios de prueba (solo Externo): agregue la dirección de Gmail con la que se autenticará.
- Cree un ID de cliente OAuth:
- Tipo de aplicación: Aplicación de escritorio
- Descargue el JSON. Guárdelo como
credentials.json.
Autenticación inicial
Mueva sus credenciales al directorio de configuración (por defecto ~/.config/mcp-gmail-manager/):
mkdir -p ~/.config/mcp-gmail-manager
mv ~/Downloads/client_secret_*.json ~/.config/mcp-gmail-manager/credentials.json
chmod 600 ~/.config/mcp-gmail-manager/credentials.json
Ejecute el flujo de autenticación:
mcp-gmail-manager-auth
Esto se vincula a localhost:8765 e imprime una URL de autorización de Google. Ábrala en un navegador en una máquina que pueda alcanzar localhost:8765 en el host de autenticación:
- Escritorio local: la URL impresa funciona directamente.
- Servidor remoto / sin cabeza: reenvíe el puerto desde su portátil primero:
Luego ejecutessh -L 8765:localhost:8765 user@your-servermcp-gmail-manager-authdentro de esa sesión SSH.
Autorice con la cuenta de Google que será propietaria del correo saliente. Al tener éxito, el script escribe token.json y sale.
Expiración de token
La vida útil del token de actualización depende de cómo esté configurada la pantalla de consentimiento OAuth:
| Configuración | Vida útil del token de actualización | ¿Requiere reautenticación? |
|---|---|---|
| Interno (Google Workspace) | Sin expiración | Nunca (hasta que el usuario revoque) |
| Externo + Prueba | 7 días (política de Google para aplicaciones no verificadas) | Sí: semanalmente |
| Externo + Producción verificada | Sin expiración | Nunca, pero la verificación requiere una evaluación de seguridad de Google de pago |
Cuando el token de actualización expire en modo Prueba, verá errores de invalid_grant o Token has been expired or revoked. Para recuperarse:
rm ~/.config/mcp-gmail-manager/token.json
mcp-gmail-manager-auth
Tarda ~30 segundos. Su credentials.json no se ve afectado: solo el token del usuario.
Cómo evitar la rotación semanal
- Usuarios de Workspace: configure la pantalla de consentimiento como Interno en lugar de Externo. El token nunca expira.
- Usuarios personales de Gmail: la reautenticación semanal es la única opción práctica hoy. La verificación de producción para
gmail.modifyrequiere una evaluación de seguridad de Google (de pago, semanas de proceso): no es factible para la mayoría de los proyectos personales. - Establezca un recordatorio de calendario o un trabajo cron para avisarle semanalmente. Una versión futura puede agregar advertencias proactivas en la herramienta antes de la expiración.
Registro con Claude Code
Si se instaló mediante pipx:
claude mcp add gmail-manager -- mcp-gmail-manager
Si se instaló en un venv manual que no está en $PATH:
claude mcp add gmail-manager -- ~/.venv-mcp-gmail/bin/mcp-gmail-manager
Reinicie su sesión de Claude Code para que se carguen los nuevos esquemas de herramientas.
Múltiples cuentas de Gmail
Cada instancia del MCP maneja una cuenta de Gmail. Para usar varias cuentas desde la misma sesión de Claude Code (por ejemplo, personal + trabajo), registre el MCP una vez por cuenta con un GMAIL_MCP_CONFIG_DIR distinto. Cada instancia obtiene sus propias credenciales, token, registro de auditoría y configuración: totalmente aisladas.
Configuración por cuenta
# 1. Dedicated config directory
mkdir -p ~/.config/mcp-gmail-<name> && chmod 700 ~/.config/mcp-gmail-<name>
# 2. Reuse the same OAuth client (one credentials.json works for any user in the same GCP project)
cp ~/.config/mcp-gmail-<other>/credentials.json ~/.config/mcp-gmail-<name>/
chmod 600 ~/.config/mcp-gmail-<name>/credentials.json
# 3. Authenticate with the target Gmail account
GMAIL_MCP_CONFIG_DIR=$HOME/.config/mcp-gmail-<name> mcp-gmail-manager-auth
# 4. Register with the env override
claude mcp add gmail-<name> -s user \
-e GMAIL_MCP_CONFIG_DIR=$HOME/.config/mcp-gmail-<name> \
-- mcp-gmail-manager
Reinicie Claude Code. Las herramientas aparecen bajo espacios de nombres separados:
mcp__gmail-personal__send_email→ envía desde la cuenta personalmcp__gmail-work__send_email→ envía desde la cuenta de trabajo
Puede indicar a Claude "enviar vía gmail-work" y elige el espacio de nombres correcto.
Configuración por cuenta
Cada <config_dir>/config.json es independiente. Patrones útiles:
// ~/.config/mcp-gmail-work/config.json — strict allowlist
{
"allowlist": {
"enabled": true,
"domains": ["yourcompany.com"]
}
}
// ~/.config/mcp-gmail-personal/config.json — silence the audit log
{
"audit_log": { "enabled": false }
}
El compromiso del token de una cuenta no filtra el de la otra: cada uno vive en un directorio separado con chmod 600.
Configuración
~/.config/mcp-gmail-manager/config.json es opcional: si no existe, se aplican valores predeterminados sensatos (sin lista de permitidos, registro de auditoría habilitado). Se proporcionan dos ejemplos listos para copiar:
examples/config.example.json: valores predeterminados endurecidos (punto de partida recomendado). Todas las salvaguardas activadas; lista de permitidos habilitada pero vacía, por lo que la advertencia de inicio le indicará qué configurar primero.examples/config.with-allowlist.json: ejemplo institucional completamente poblado con dominios de marcador de posición.examples/config.permissive.json: exclusión explícita para usuarios que no quieren salvaguardas (lista de permitidos desactivada, escaneo de contenido desactivado, límite de velocidad desactivado, sin confirmación de envío). Considere esto solo si comprende el radio de explosión.
Referencia de esquema:
{
"allowlist": {
"enabled": false,
"domains": [],
"emails": []
},
"audit_log": {
"enabled": true,
"include_reads": false,
"path": null
},
"attachments": {
"max_total_bytes": 20971520,
"allowed_paths": [],
"deny_patterns": [],
"use_default_deny_patterns": true
}
}
| Campo | Predeterminado | Significado |
|---|---|---|
allowlist.enabled | false | Cuando false, se acepta cualquier destinatario. Habilítalo explícitamente para uso institucional. |
allowlist.domains | [] | Sufijos de dominio en minúsculas aceptados como destinatarios. |
allowlist.emails | [] | Direcciones de correo explícitas en minúsculas aceptadas independientemente del dominio. |
audit_log.enabled | true | Añade cada escritura/envío/modificación a JSONL. |
audit_log.include_reads | false | También registra operaciones de lectura (get_message, search_threads, get_thread, list_drafts, get_message_attachments). Útil para detectar reconocimiento silencioso. |
audit_log.path | null | null → <config_dir>/audit.jsonl. Anula para centralizar registros. |
audit_log.max_size_bytes | 10485760 (10 MB) | Rota a audit.jsonl.1..N cuando el archivo actual supera este tamaño. La cadena se reinicia entre rotaciones; verifica cada archivo por separado con la CLI. |
audit_log.max_backups | 5 | Número de copias de seguridad rotadas a conservar. Las más antiguas se sobrescriben. |
audit_log.verify_on_startup | false | Recorre la cadena al iniciar el servidor y emite una advertencia en stderr si está rota. Económico para registros de hasta unos pocos MB. |
attachments.max_total_bytes | 20971520 (20 MB) | Límite de tamaño combinado por envío. El límite estricto de Gmail es de 25 MB en bruto. |
attachments.allowed_paths | [] | Cuando se completa, los orígenes y destinos de adjuntos/descargas DEBEN estar bajo una de estas bases. Vacío = solo se aplican patrones de denegación. |
attachments.deny_patterns | [] | Patrones regex adicionales para rechazar (coinciden con la ruta absoluta). Se añaden además de los predeterminados. |
attachments.use_default_deny_patterns | true | Incluye el conjunto de denegación integrado (~/.ssh/, ~/.aws/, id_rsa, .env, token.json, archivos de credenciales, almacenes de navegador). |
rate_limit.enabled | false | Cuando true, limita los envíos salientes por hora por instancia en ejecución. Ventana deslizante en memoria: se reinicia al reiniciar el servidor. |
rate_limit.sends_per_hour | 60 | Se aplica a send_email, reply_to_message, forward_message y send_draft combinados. |
content_scan.enabled | false | Cuando true, escanea asuntos, cuerpos, firmas y contenido de vacaciones salientes en busca de patrones secretos. Las coincidencias bloquean la operación antes de que llegue a Gmail. |
content_scan.use_default_patterns | true | Incluye las expresiones regulares secretas integradas (claves de acceso de AWS, tokens de Stripe/OpenAI/Anthropic/GitHub/GitLab/Google/Twilio, claves privadas PEM, JWT, credenciales incrustadas en URL). |
content_scan.patterns | [] | Patrones adicionales definidos por el usuario. Cada entrada: {"name": "...", "regex": "..."}. Los nombres aparecen en mensajes de error para depuración. |
content_scan.scan_subject / scan_body / scan_signature / scan_vacation | true | Alternancias por ámbito. Útil para deshabilitar una ubicación mientras se mantienen otras activas. |
send_confirmation.required | false | Cuando true, el send_email directo está deshabilitado: debe pasar por preview_send_email → confirm_send_email(preview_id). |
send_confirmation.preview_ttl_seconds | 300 | Cuánto tiempo sigue siendo válida una vista previa antes de que deba reemitirse. |
signature.auto_append | false | Cuando true, obtiene la firma configurada en la Configuración de Gmail y la añade a cada cuerpo saliente (enviar/responder/reenviar/crear_borrador/actualizar_borrador/vista_previa). La interfaz web de Gmail aplica firmas automáticamente; la API de Gmail NO: habilítalo para que coincida. |
signature.cache_ttl_seconds | 3600 | Cuánto tiempo almacenar en caché la firma obtenida en memoria antes de volver a obtenerla. |
signature.strip_html | true | Gmail almacena firmas como HTML. Cuando true, el MCP reduce a texto plano (preservando saltos de línea) y envía un mensaje solo de texto/plano. Cuando false (v0.3.5+), el MCP envía multipart/alternative: una parte de texto plano con la firma reducida, más una parte de texto/html con la firma HTML original preservando imágenes de logotipos, colores y diseño. Establécelo en false si tu firma de Gmail tiene un logotipo o formato enriquecido que quieras conservar. |
body.format | "plain" | Cómo se interpreta el campo body de las herramientas de enviar/responder/reenviar/borrador. "plain" (predeterminado): el cuerpo es texto plano, enviado como texto/plano (compatible con v0.3.5). "markdown" (v0.3.6+): el cuerpo es Markdown; la parte de texto plano conserva el Markdown en bruto, la parte HTML se renderiza: **bold**, *italic*, # H1, - lists, [links](url), `code` all render properly in email clients. "html": body is raw HTML; HTML part is passthrough, plain part is a stripped-to-text fallback. Enable markdown si quieres que el Markdown natural de Claude se renderice como formato enriquecido. |
signature.send_as_email | null | Qué identidad de sendAs usar para la firma. null = el correo principal. |
Verificación del registro de auditoría
Ejecuta mcp-gmail-manager-verify-log para recorrer la cadena de hash y confirmar que ninguna entrada ha sido editada o eliminada:
mcp-gmail-manager-verify-log # verify the active log
mcp-gmail-manager-verify-log ~/.config/.../audit.jsonl.1 # verify a rotated backup
Códigos de salida: 0 OK, 1 registro no encontrado, 2 JSON malformado, 3 cadena rota.
Anulaciones de variables de entorno
| Variable | Predeterminado |
|---|---|
GMAIL_MCP_CONFIG_DIR | $XDG_CONFIG_HOME/mcp-gmail-manager o ~/.config/mcp-gmail-manager |
GMAIL_MCP_CREDENTIALS | <config_dir>/credentials.json |
GMAIL_MCP_TOKEN | <config_dir>/token.json |
Notas de seguridad
- Modelo de amenaza: este MCP está principalmente endurecido contra un LLM con mal comportamiento: inyección de prompts, destinatarios alucinados, escenarios de exfiltración engañosa. NO es un sustituto de la seguridad del host; un atacante con acceso local puede leer
token.jsony llamar a Gmail directamente, omitiendo todas las salvaguardas aquí. - Almacenamiento de tokens:
token.jsonse escribechmod 600. Trátalo como una contraseña. - Sin atestación remota: este servidor se ejecuta completamente en tu máquina. Sin telemetría, sin llamadas de terceros más allá de
googleapis.com. - El alcance de OAuth es deliberadamente algo estrecho:
gmail.modifycubre enviar/leer/etiquetar/papelera/borradores. NO solicitamail.google.com, por lo que la eliminación permanente no está disponible: las eliminaciones van a la Papelera y se pueden deshacer conuntrash_*. Si solo necesitas enviar, haz un fork y reemplaza el alcance congmail.send. - Las salvaguardas de destinatarios cubren el reenvío en filtros:
create_filtercon unaction.forwarddirigido a una dirección no permitida se rechaza. Los filtros eran una omisión común de las listas de permitidos solo de envío. - Las herramientas de lectura marcan el contenido como no confiable: los cuerpos y fragmentos están envueltos en
<untrusted-email-content>...</untrusted-email-content>. Las descripciones de herramientas instruyen a los LLM posteriores a tratar el contenido envuelto como datos. Cualquier aparición de la etiqueta de cierre dentro del cuerpo de un mensaje se escapa para evitar la fuga. - Conjunto de denegación de adjuntos predeterminado (origen y destino) cubre rutas comunes de credenciales/secretos:
~/.ssh/,~/.aws/,~/.gnupg/,~/.docker/config.json,~/.kube/,.env,.env.*,credentials.json,token.json,id_rsa/id_ed25519/id_ecdsa/id_dsa,.git-credentials,.netrc,wallet.dat,.bash_history,.zsh_history,~/.mozilla/*/logins.json,authorized_keys,known_hosts. Extiéndelo medianteattachments.deny_patternso redúcelo más medianteattachments.allowed_paths. - El registro de auditoría es a prueba de manipulaciones, no a prueba de manipulaciones: cada entrada incluye
prev_hash = sha256(previous line). La modificación parcial rompe la cadena y es detectable. Una reescritura completa del registro por un atacante con escritura de archivos NO se previene: combínalo con envío de registros fuera del host (hoja de ruta) para garantías más sólidas. - Lo que NO se mitiga: limitación de velocidad (un agente comprometido puede agotar la cuota de Gmail rápidamente), escaneo de patrones de contenido saliente (sin regex de secretos en cuerpos), phishing de firmas/vacaciones (la lista de permitidos no cubre su contenido), reescritura completa del registro por un atacante local. Consulta SECURITY.md para el modelo de amenaza actual y la hoja de ruta.
Limitaciones
- La verificación "Producción" de OAuth para
gmail.modifyrequiere una evaluación de seguridad paga de Google. Mantente en "Interno" (Workspace, sin expiración) o "Pruebas" (≤ 100 usuarios, rotación de token de actualización de 7 días — consulta Expiración de token) para evitar esto. - La composición del cuerpo de correo HTML no se expone como un campo de primera clase. Envía mediante
create_draft+ edición manual de HTML en la interfaz de Gmail, o extiende_build_mimeen un fork. - Las notificaciones push (Pub/Sub
watch/stop) no están implementadas: fuera de alcance.
Contribuciones
Se aceptan issues y PRs. Mantén los cambios enfocados, documenta cualquier nueva herramienta con un ejemplo de esquema y añade una entrada de registro de auditoría para cualquier cosa que mute el estado.
Licencia
MIT — consulta LICENSE.