Skip to main content
Glama
eubin-create

gmail-mcp

by eubin-create

Gmail para tu asistente de IA: varias cuentas a la vez, en un servidor que tú controlas.

MIT Cloudflare Workers MCP OAuth 2.1 27 tools tests

日本語版 · 简体中文

gmail-mcp conecta Gmail con Claude y cualquier otro cliente MCP. Puede buscar y leer correo, enviar y responder a todos con historial citado, reenviar, gestionar adjuntos e imágenes en línea, y administrar borradores, etiquetas e hilos — en varias cuentas de Google a la vez.

Se ejecuta como un servidor remoto en tu propio Cloudflare Worker, de modo que la misma conexión responde desde Claude Code en un portátil, claude.ai en un navegador y Claude en el móvil. Cada conexión inicia sesión en una cuenta de Google, y el token de refresco de Google permanece en tu cuenta de Cloudflare.

Dos cosas traen a la gente hasta aquí. Los conectores de Gmail integrados en Claude y Google leen el correo y escriben borradores, pero no pueden enviar, y mantienen una cuenta de Google por cuenta de asistente. Los servidores que sí pueden enviar suelen ser procesos locales — bien en un escritorio, invisibles desde el móvil.


Cómo se compara

gmail-mcp

Claude · Google integrado

taylorwilsdon/google_workspace_mcp

ArtyMcLabin/Gmail-MCP-Server

shinzo-labs/gmail-mcp

aaronsb/google-workspace-mcp

Dónde se ejecuta

Cloudflare Workers

alojado por el proveedor

tu servidor o local

local

local

local

Accesible desde el móvil

Varios buzones a la vez

✅ vinculado por conexión

✅ elegido por llamada

❌ solo alias

✅ elegido por llamada

Enviar correo

Adjuntos · imágenes cid: en línea

sin documentar

Responder a todos con historial citado

solo borradores

sin citar

Reenviar

Respeta el charset de cada parte

❌ asume UTF-8

❌ asume UTF-8

Rechaza la inyección de cabeceras CRLF

✅ framework

✅ los elimina

ninguna

Ajustes del buzón (filtros, vacaciones)

❌ fuera de alcance

filtros

filtros

Número de herramientas

24

11–16

14 (Gmail)

30

64

11

Quién guarda tu token de refresco

el proveedor

google_workspace_mcp es el proyecto más completo de todos. Cubre todo Workspace, no solo Gmail, y añade tu firma de Gmail y descarga los adjuntos directamente desde una URL, cosas que gmail-mcp no hace. shinzo-labs/gmail-mcp llega a los respondedores de vacaciones, delegados y S/MIME a través de sus 64 herramientas; esas viven bajo gmail.settings.*, un ámbito que gmail-mcp nunca solicita, así que quedan fuera de su alcance pase lo que pase con un permiso.

Dos diferencias de diseño deciden casi todo lo demás. Enrutar las cuentas mediante un argumento de llamada permite que un permiso toque todos los buzones conectados, mientras que vincular el buzón a la conexión hace que un argumento equivocado no llegue a nada. Y al leer, los servidores locales decodifican cada parte como UTF-8: el correo en ISO-2022-JP y Shift_JIS llega distorsionado, y los mensajes largos que Gmail guarda como blobs adjuntos vuelven con el cuerpo vacío.


Despliégalo

Unos diez minutos. Necesitas una cuenta de Cloudflare, bun y una cuenta de Google. Un dominio en la cuenta de Cloudflare es opcional: sin él, el Worker responde en workers.dev.

1 · Crea un cliente OAuth de Google

PROJECT="gmail-mcp-$(openssl rand -hex 3)"
gcloud auth login
gcloud projects create "$PROJECT" --name="gmail-mcp"
gcloud config set project "$PROJECT"
gcloud services enable gmail.googleapis.com

Google no expone ninguna API para los dos pasos siguientes, así que se hacen en la Cloud console:

  • Pantalla de consentimiento de OAuthExterna, y luego en Audiencia pulsa Publicar aplicación. Si se deja en Pruebas, Google caduca cada token de actualización después de 7 días y cada conexión muere con su token. Publicada, la aplicación muestra una advertencia de aplicación no verificada al iniciar sesión y sirve hasta 100 cuentas.

  • Credenciales → Crear credenciales → ID de cliente de OAuthAplicación web, con https://<your-host>/callback como URI de redirección autorizado. Guarda el ID de cliente y el secreto.

<your-host> es el dominio que apuntas al Worker, o el nombre de host workers.dev que obtiene de otro modo. Desplegar primero y volver para rellenar esto funciona: la guía que el Worker sirve en / muestra el valor exacto.

2 · Desplegar el Worker

Deploy to Cloudflare

El botón copia el repositorio en tu cuenta de GitHub, crea el espacio de nombres KV y el Durable Object, y pide los cuatro secretos. Despliega en workers.dev; un dominio personalizado se adjunta después en Configuración → Dominios y rutas.

Desde una terminal en su lugar:

git clone https://github.com/mkpoli/gmail-mcp && cd gmail-mcp
bun install
bun run setup

bun run setup pregunta en qué dominio responder, crea o reutiliza el espacio de nombres OAUTH_KV, toma el ID de cliente y el secreto, genera una clave de cookie y despliega. Esas dos primeras respuestas van a wrangler.local.jsonc, que git ignora — wrangler.jsonc no nombra el espacio de nombres de ninguna cuenta ni el dominio de nadie, así que un clon despliega en cualquier lugar. Volver a ejecutar setup para rotar un solo secreto es seguro.

3 · Conectar un cliente

Deja los campos de ID de cliente y secreto vacíos: los clientes MCP se registran ellos mismos.

claude mcp add --transport http gmail-personal https://<your-host>/mcp
claude mcp add --transport http gmail-work     https://<your-host>/mcp/work

Ejecuta /mcp en Claude Code para iniciar sesión en cada conexión con su cuenta de Google. En claude.ai es Configuración → Conectores → Añadir conector personalizado con la misma URL. Cualquier etiqueta de un solo segmento funciona después de /mcp/, que es como un despliegue sirve varias bandejas de entrada a clientes que rechazan dos servidores que comparten una URL.

Tu despliegue sirve esta guía en https://<your-host>/.


Lo que puede hacer

whoami search_messages get_message get_thread get_attachment

send_message reply_all forward_message create_draft update_draft send_draft delete_draft list_drafts stage_attachment_begin stage_attachment_append stage_attachment_finish

list_labels create_label update_label delete_label modify_labels modify_thread_labels batch_modify_messages trash_message · untrash_message trash_thread · untrash_thread

Los mensajes salen como los envía un cliente de correo: texto plano con una alternativa HTML, archivos adjuntos e imágenes en línea referenciadas por cid:, anidados como multipart/mixed › multipart/related › multipart/alternative. Los asuntos y nombres para mostrar usan RFC 2047, los nombres de archivo usan RFC 2231, por lo que el japonés, el chino y los emojis sobreviven al viaje.

reply_all lee el Reply-To, From, To y Cc del original, elimina tu propia dirección y cualquier dirección desde la que envíes correo, responde desde la que el remitente escribió, lleva la cadena References y cita el original en las partes que envíes. forward_message reproduce el sobre reenviado y puede volver a adjuntar los archivos del original.

create_draft con replyToMessageId escribe la respuesta como borrador para editar antes de enviar: se une al hilo del original, lleva In-Reply-To y References, deriva los destinatarios de responder a todos y el asunto Re:, y cita el original. update_draft cambia solo los campos que se le dan; los destinatarios, el texto, los archivos añadidos a mano en cualquier cliente y el hilo al que responde el borrador se leen y se conservan. Un archivo cuyo base64 no quepa en los argumentos de la herramienta se prepara en su lugar: stage_attachment_begin devuelve una URL de subida que acepta los bytes crudos en un curl -T, stage_attachment_append acepta base64 en fragmentos, y cada campo attachments acepta el stagingId resultante.

La lectura está limitada a propósito: los cuerpos de mensajes e hilos tienen presupuestos de caracteres, una respuesta completa tiene un límite de bytes, y un adjunto se devuelve en línea solo mientras sea lo suficientemente pequeño para leerlo. Un hilo largo de lista de correo, o un archivo grande, vuelve recortado con una nota que lo dice en lugar de llenar el contexto del asistente.


Cómo funciona

Dos flujos OAuth se encuentran en un solo Worker. El cliente MCP se autentica ante el Worker; el Worker se autentica ante Google en tu nombre. Ninguna de las partes tiene las credenciales de la otra.

sequenceDiagram
    autonumber
    participant C as MCP client<br/>(Claude Code · claude.ai)
    participant W as Worker<br/>(OAuthProvider + McpAgent)
    participant G as Google<br/>(OAuth + Gmail API)

    C->>W: POST /register (dynamic client registration)
    C->>W: GET /authorize (PKCE challenge)
    W->>C: approval dialog
    C->>G: consent screen — pick the account
    G->>W: GET /callback?code=…
    W->>W: allowlist check on the verified email
    W->>G: exchange code → access + refresh token
    W->>C: MCP access token (Google tokens sealed inside the grant)
    C->>W: POST /mcp — tools/call
    W->>G: Gmail REST (token refreshed as needed)
    G->>W: message / thread / label data
    W->>C: tool result

Capa

Archivo

Qué hace

🔐 OAuth del lado MCP

workers-oauth-provider

Registro dinámico de clientes, PKCE, concesiones en KV con los tokens de Google sellados dentro

🔗 OAuth del lado de Google

src/google-handler.ts

Código de autorización con acceso sin conexión, estado de un solo uso vinculado a la sesión del navegador, CSRF de doble envío, lista blanca en el correo verificado

🤖 Agente

src/index.ts

Un Durable Object por sesión MCP, vinculado a la cuenta que lo abrió; actualización de token de un solo vuelo, fan-out limitado

✉️ Correo

src/gmail.ts

Construcción RFC 822, recorrido del árbol MIME, decodificación de conjuntos de caracteres, composición de respuestas y reenvíos

Construido con

Gmail se llama mediante fetch simple contra la API REST. El SDK oficial googleapis asume Node y lleva mucho más de lo que un Worker debería incluir, así que la construcción de mensajes, el análisis MIME y la actualización de tokens viven en src/gmail.ts y src/utils.ts en su lugar.

Endpoints

Ruta

Propósito

/mcp

Endpoint MCP

/mcp/<label>

El mismo servidor bajo cualquier etiqueta de un solo segmento, para clientes que rechazan dos servidores que comparten una URL

/

Esta guía de configuración

/authorize · /token · /register · /callback

Mecanismo OAuth


Quién puede iniciar sesión

ALLOWED_EMAILS decide, comprobado contra la dirección que Google informa como verificada — después del consentimiento, antes de que exista cualquier concesión.

Valor

Quién entra

(vacío)

nadie

you@gmail.com, work@company.com

esas cuentas

*@company.com

cualquiera en ese dominio

*

cualquier cuenta de Google verificada

Cada concesión llega solo a la bandeja de entrada que la autenticó, por lo que ampliar esta lista nunca amplía el acceso a bandejas ya conectadas. Establecer * permite que extraños usen tu despliegue, y la cuota de tu cliente de Google, para su propio correo.


Límites

Dos techos evitan que un despliegue compartido se agote, ambos establecidos en wrangler.jsonc:

Ajuste

Dónde

Predeterminado

Qué limita

MAX_ACCOUNTS

vars

25

Aproximadamente cuántas cuentas de Google distintas pueden completar el inicio de sesión. Las cuentas ya conectadas siguen funcionando cuando se alcanza el límite; las nuevas son rechazadas. Los inicios de sesión que llegan juntos leen el recuento antes de que se registre cualquiera de ellos, por lo que el total puede asentarse un poco por encima de este número. Google limita las aplicaciones no verificadas a 100 usuarios, así que deja espacio por debajo de eso.

RATE_LIMITER.simple.limit

unsafe.bindings

120 por 60s

Llamadas a Gmail que una cuenta puede hacer en esa ventana, en todas sus sesiones. Cloudflare mantiene este recuento por ubicación, por lo que una cuenta que se conecta desde dos regiones obtiene aproximadamente esa cantidad en cada una. Una lectura amplia gasta varias: search_messages que devuelve 50 hace 51 llamadas.

REGISTER_LIMITER.simple.limit

unsafe.bindings

10 por 60s

Registros de cliente que una dirección puede hacer en esa ventana. Un cliente se registra una vez y conserva el id que se le da, por lo que el uso ordinario nunca se acerca a esto; el techo está ahí porque el registro no necesita credenciales y cada uno escribe en KV.

En el plan Free de Workers se aplica un tope adicional: 50 solicitudes salientes por invocación. Una lectura amplia consume una por mensaje, así que search_messages y list_drafts necesitan un maxResults de 45 o menos; por encima de eso, el excedente vuelve en forma de errores por mensaje en lugar de resultados. El plan de pago permite 1000.

Sube cualquiera de los dos y vuelve a desplegar. El limitador de velocidad de Cloudflare lee su tope desde el binding en tiempo de compilación, así que el simple.limit de cada uno es el único sitio que lo cambia. Un despliegue de un solo usuario puede dejar los dos como están: el uso normal de un asistente se queda muy por debajo de esos límites.


Seguridad

El autoalojamiento traslada la cuestión de la confianza en lugar de eliminarla, así que esto es todo lo que está en juego.

  • Tus tokens siguen siendo tuyos. Los tokens de actualización se cifran dentro de su concesión OAuth en tu espacio de nombres KV. El Durable Object OWN de una sesión guarda el token de acceso con validez de una hora, y el framework del agente MCP mantiene una copia de la concesión allí mientras el objeto siga vivo, token de actualización incluido. Ambos almacenes están en tu propia cuenta de Cloudflare y se cifran en reposo. El correo nunca se guarda: no hace más que pasar.

  • Una sesión, un buzón. La sesión MCP quede ligada a la cuenta que la abriО, de modo que una concesión para un buzón no puede actuar sobre otra con un identificador de sesión prestado.

  • Alcance mínimo de permisos. gmail.modify cubre lectura, envío, etiquetas y papelera. Excluye la eliminación definitiva y campo todos los gmail.settings.* — las reglas de reenvío automático y la exfiltración de filtros, las clásicas puertas traseras del buzón — quedan fuera de lo que cualquier concesión robada pueda hacer. Junto a él se solicitan dos ámbitos de solo lectura, userinfo.email y userinfo.profile: son lo que permite a la lista de permitidos y a la sesión saber qué cuenta se ha conectado, y no llega ningún correo.

  • No se pueden colar cabeceras adicionales. Todo el valor de cabecera saliente se rechaza si contiene CR, LF o NUL, de manera que ningún argumento puede salir de su propio campo para añadir una más — un Bcc dentro de una línea de asunto, por ejemplo. Los tipos de contenido se validan y el histórico citado se escapa con entidades HTML. Lo que no tiene datos, no es vigilar los argumentos en sí: bcc es un parámetro real, así que un modelo remitido en una instrucción oculta en el cuerpo del mensaje podría rellenarlo, y el aviso de aprobación de tu cliente sigue siendo la comprobación para eso.

  • El acceso se puede revocar. Restringir ALLOWED_EMAILS impide nuevos inicios de sesión. El acceso de una sola cuenta se revoca en myaccount.google.com/connections. Si rotas el secreto de cliente de Google, se invalid toda las concesiones a la vez.

El Worker descifra el correo en memoria mientras sirve una solicitud, como tiene que hacer cualquier relay centralizado. Si eso es demasiado para algún buzón, ejecuta un servidor MCP local para este.


Cómo se probó

253 pruebas unitarias constructuración de mensajes (MIME anidado, plegado RFC 2047, nombres de archivo RFC 2231, rechazo de CR/LF, base64, ajuste de línea base64), extracción del cuerpo en distintos encuestados de caracteres, composición de respuestas y reenvíos, flujos de token de Google, la lista de permitidos del inicio de sesión, los controles de CSRF y de vinculación de estado que protegen el lado de la navegador del inicio de sesión, así como las propias herramientas contra un stand-in Gmail — propiedad de sesión, composición de los mensajes to-recipientes, selección de adjuntos y lo que devuelve una lectura parcialmente fallida.

Además, todas las acciones de comprobado contra las cuentas reales de Gmail, y con una cuenta aparte que verificaba lo que llegaba:

Área

Resultado

Codificación

Asuntos japoneses plegados conforme a palabras codificadas; emojis, secuencias ZWJ, árabe RTL, marcas de combinación y CJK poco comunes viajaron ida y vuelta sin cambios

Adjuntos

Un CSV llamado 請求書.csv enviado, entregado y descargado, volvió byte a byte idéntico; una imagen cid: llegó y se mostró correctamente

Hilos

-- ** reply_all respondió al remitente, conservó el Cc del tercero, omitió su propia dirección y citó el original en el mismo hilo

Dos cuentas

Las dos conectadas a un mismo despliegue, y un id de mensaje de una devolvía 404 en la otra

Organización

Una etiqueta CJK anidada creada, renombrada, aplicada por bloques y borrada; el descarte en la papel era conocido y ambos casos se revirtió

Escala

Un buzón de 15.000 mensajes encontrado con los operadores de Gmail y paginación sin sobrepasar un límite de frecuencia


Desarrollo

bun run dev     # wrangler dev on :8788
bun run check   # biome + tsc
bun test        # 253 unit tests
bun run assets  # regenerate the light and dark diagrams
bun run deploy

Preguntas y errores

Abre una incidencia.


Licencia

Copyright © 2026 mkpoli. Publicado bajo la Licencia MIT.

src/workers-oauth-utils.ts deriva de la demo remote-mcp-github-oauth en cloudflare/ai, Copyright © 2025 Cloudflare, Inc., utilizada bajo la Licencia MIT. Ver THIRD-PARTY.md.

-
license - not tested
Not graded
quality - not tested
C
maintenance

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

  • MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.

  • Shipmail MCP server for AI agent custom-domain email inboxes with REST API and webhooks.

  • Read, search, send, organize, draft and schedule email across your inboxes from any MCP client.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/eubin-create/gmail-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server