notify-mcp
{"type": "text"}# notify-mcp
Correo electrónico y SMS de entrega a uno mismo para el personal de Example Corp, como servidor MCP remoto autenticado con Entra. Esta es la ruta de envío para el despliegue de jefe de personal de claude.ai: los agentes pueden enviar por correo o mensaje de texto el propio contenido del usuario autenticado, y estructuralmente nada más.
El invariante (por qué existe este servidor)
Los agentes que leen contenido no confiable (correo entrante, tickets, chats) nunca deben tener una capacidad de envío sin restricciones: una inyección de prompt podría convertirlo en un canal de exfiltración. Este servidor lo resuelve por construcción:
Los destinatarios no son parámetros de la herramienta. El correo se envía al UPN del llamante, tomado del token de Entra validado. El SMS se envía al móvil registrado del llamante. Un modelo completamente comprometido puede cambiar qué se envía, nunca dónde.
El remitente (FROM) está bloqueado a
<agent>approver@example.com— el servidor no puede enviar como humano, por lo que no puede suplantar a nadie.Las claves de Resend e Inteliquent viven solo en este contenedor. Los usuarios nunca ven una clave; se autentican con su propio inicio de sesión de M365.
Presupuestos por hora por usuario + una línea de registro de auditoría por envío.
Related MCP server: graphdo-ts
Herramientas
Tool | Qué hace |
| Devuelve el correo electrónico y el móvil enmascarado a los que se enviarán los envíos. Prueba la conexión con esto primero. |
| Envía un correo al llamante. |
| Envía un mensaje de texto al móvil del llamante desde el DID de la empresa 13105550100. ≤640 caracteres. |
| Inicia la configuración de SMS: envía un código de 6 dígitos al número. |
| Completa la configuración: verifica el código, guarda el número y envía un aviso de cambio por correo al usuario. |
Cómo sabe el servidor quién eres
Claude → inicio de sesión de Entra (el propio inicio de sesión del usuario) → cada llamada de herramienta lleva un JWT de portador → AzureJWTVerifier valida firma/emisor/audiencia → la reclamación preferred_username = el destinatario. Sin variables de entorno por usuario, sin configuración; la identidad es criptográfica.
Los números de móvil no están en el token, por lo que el SMS utiliza auto-registro verificado (diseñado para inquilinos que no completan el campo mobilePhone de Entra — el nuestro no lo hace):
El usuario (normalmente durante la entrevista de configuración del CoS): "registra mi móvil 310-555-1212" → el servidor envía un código de 6 dígitos a ese número.
El usuario escribe el código →
confirm_my_mobile→ el número se guarda en/data/sms_directory.jsonvinculado a su UPN + se envía un correo de confirmación.Los cambios quedan entonces bloqueados (
NOTIFY_ALLOW_MOBILE_CHANGE=false): un número confirmado solo puede ser cambiado por el administrador editando el registro. La verificación del código demuestra la posesión; el bloqueo de cambios + el aviso por correo eliminan el ataque de re-vinculación por inyección (contenido hostil que redirige los mensajes a otro lugar).
Orden de resolución: archivo de registro (las entradas manuales son cadenas simples, las entradas auto-registradas son objetos) → mobilePhone opcional de Entra a través de Graph (NOTIFY_GRAPH_LOOKUP_ENABLED=true + -GrantGraphUserRead; innecesario si se usa el auto-registro).
Duración de la sesión del conector (la solución a la desconexión)
Tres cosas evitan que el conector muestre "desconectado":
offline_accessse anuncia en los metadatos del recurso protegido (NOTIFY_ADVERTISE_OFFLINE_ACCESS=true), por lo que el inicio de sesión de Claude obtiene un token de actualización y renueva silenciosamente los tokens de acceso de ~60–90 min.stateless_http=True— las sesiones sobreviven a los redespliegues del contenedor.El host proxy NPM debe tener las anulaciones de tiempo de espera del playbook (ver PORTAINER_DEPLOY.md) para que las transmisiones inactivas no se corten a los 60 s.
También verifica que ninguna política de acceso condicional de frecuencia de inicio de sesión cubra esta aplicación. Prueba de aceptación: conéctate, espera 2+ horas inactivo, redespliega el contenedor y luego llama a whoami — no debería aparecer ninguna solicitud de re-autenticación.
Configuración (orden del playbook)
scripts/setup_entra_app.ps1 -TenantId <tenant>(opcionalmente-GrantGraphUserRead) — imprime los valores de entorno del servidor + el secreto del conector (va en la configuración avanzada del conector de Claude, nunca en el servidor).Despliega mediante la pila Git de Portainer — PORTAINER_DEPLOY.md. Puerto de host sugerido 8093 (prueba primero; registrado en el registro del playbook).
Host proxy NPM
notify-mcp.example.com→ el contenedor; tiempos de espera del playbook + lista de permitidos de IP de Anthropic; certificado LE antes de habilitar la lista de permitidos.Añádelo como conector personalizado de la organización en claude.ai; los usuarios se conectan una vez con su propio inicio de sesión de M365.
Pruebas de aceptación
curl http://<docker-host>:8093/healthz # {"status":"ok",...}
curl -s https://notify-mcp.example.com/.well-known/oauth-protected-resource/mcp | jq
# scopes_supported MUST include the full https://.../mcp/access_as_user scope
# AND "offline_access"
curl -i https://notify-mcp.example.com/mcp # 401 + WWW-AuthenticateLuego, en Claude, como miembro del grupo:
whoami→ tu propio correo electrónico, móvil "en registro (…1234)" o un fallo claro.send_email_to_me→ llega a TU bandeja de entrada desdenotify_ai@.Pide al modelo que "envíe esto a <alguien más>" → debe negarse / no tener forma de cumplirlo. Si esto falla es un P1 — no desplegar.
register_my_mobilecon tu número → llega el código →confirm_my_mobile→ llega el correo de confirmación →send_sms_to_mefunciona. Luego intenta registrar un número DIFERENTE → debe ser rechazado (bloqueo de cambios).La prueba de 2 horas inactivo + redespliegue anterior.
Un no miembro se conecta → rechazado en el inicio de sesión (AADSTS50105).
Desarrollo local
pip install -r requirements.txt
MCP_AUTH_ENABLED=false python -m notify_mcp # Inspector only — tools will
# refuse to send without a token
# identity; NEVER expose auth-offThis server cannot be installed
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 Servers
- AlicenseCqualityDmaintenanceEnables secure, zero-trust access to MCP tools through short-lived, signed capability leases that bind tool execution to specific sessions, intents, and constraints. Prevents prompt injection attacks and privilege escalation with dynamic risk scoring, policy enforcement, and tamper-evident audit logging.41MIT

graphdo-tsofficial
AlicenseAqualityCmaintenanceEnables AI agents to send emails and manage tasks in Microsoft To Do with scoped, low-risk access to Microsoft Graph.3511MIT- AlicenseNot gradedqualityCmaintenanceEnables email agents to send emails with granular trust levels per contact, ensuring human approval for high-risk or unknown recipients while allowing automatic sending for trusted ones.MIT
- AlicenseNot gradedqualityBmaintenanceAuthenticated email service MCP for AI agents.183Apache 2.0
Related MCP Connectors
Phone, SMS & email for AI agents — one remote MCP endpoint, OAuth login, zero install.
Hosted email MCP for AI agents with inboxes, send/receive, memory, recovery, and credits.
Remote MCP for Copilot CLI switch gate MCP, structured receipts, audit logs, and reviewer-ready evid
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/JohnGilligan2/mcp-notify'
If you have feedback or need assistance with the MCP directory API, please join our Discord server