notify-mcp
notify-mcp
Доставка на себя по электронной почте и SMS для сотрудников Example Corp, как удалённый MCP-сервер с аутентификацией Entra. Это путь отправки для развертывания claude.ai для руководителя аппарата: агенты могут отправлять по электронной почте или SMS вошедшему в систему пользователю их собственный контент, и структурно ничего больше.
Инвариант (почему существует этот сервер)
Агенты, которые читают недоверенный контент (входящая почта, тикеты, чаты), никогда не должны обладать неограниченной возможностью отправки — инъекция подсказок может превратить её в канал эксфильтрации. Этот сервер решает эту проблему конструктивно:
Получатели не являются параметрами инструмента. Электронная почта отправляется на UPN вызывающего, взятый из проверенного токена Entra. SMS отправляется на мобильный номер вызывающего, указанный в записи. Полностью скомпрометированная модель может изменить что отправляется, но никогда куда.
FROM заблокирован на
<agent>approver@example.com— сервер не может отправлять от имени человека, поэтому не может выдавать себя за кого-либо.Ключи Resend + Inteliquent живут только в этом контейнере. Пользователи никогда не видят ключ; они аутентифицируются с помощью своего собственного входа M365.
Почасовые бюджеты на пользователя + строка журнала аудита для каждой отправки.
Related MCP server: Mailbuttons MCP Server
Инструменты
Инструмент | Что делает |
| Возвращает адрес электронной почты и замаскированный мобильный номер, на которые будут доставляться отправления. Сначала проверьте подключение с помощью этого. |
| Отправляет электронное письмо вызывающему. |
| Отправляет SMS на мобильный номер вызывающего с корпоративного DID 13105550100. ≤640 символов. |
| Запускает настройку SMS: отправляет 6-значный код на номер. |
| Завершает настройку: проверяет код, сохраняет номер, отправляет пользователю уведомление об изменении. |
Как сервер узнаёт, кто вы
Claude → вход в Entra (собственный логин пользователя) → каждый вызов инструмента несёт bearer JWT → AzureJWTVerifier проверяет подпись/эмитента/аудиторию → утверждение preferred_username = получатель. Никаких переменных окружения на пользователя, никакой конфигурации; идентичность криптографическая.
Мобильные номера не в токене, поэтому SMS использует подтверждённую саморегистрацию (создано для тенантов, которые не заполняют mobilePhone в Entra — наш не заполняет):
Пользователь (обычно во время интервью по настройке CoS): «зарегистрируй мой мобильный 310-555-1212» → сервер отправляет 6-значный код на этот номер.
Пользователь вводит код →
confirm_my_mobile→ номер сохраняется в/data/sms_directory.jsonс привязкой к их UPN + отправляется подтверждающее письмо.Затем изменения блокируются (
NOTIFY_ALLOW_MOBILE_CHANGE=false): подтверждённый номер может быть изменён только администратором, редактирующим реестр. Проверка кода доказывает владение; блокировка изменений + уведомление по электронной почте устраняют атаку с переназначением через инъекцию (враждебный контент, перенаправляющий тексты в другое место).
Порядок разрешения: файл реестра (ручные записи — простые строки, саморегистрируемые записи — объекты) → необязательный mobilePhone в Entra через Graph (NOTIFY_GRAPH_LOOKUP_ENABLED=true + -GrantGraphUserRead; не требуется, если используется саморегистрация).
Долговечность сеанса коннектора (исправление отключения)
Три вещи не дают коннектору показывать «отключено»:
offline_accessрекламируется в метаданных защищённого ресурса (NOTIFY_ADVERTISE_OFFLINE_ACCESS=true), поэтому вход Claude получает токен обновления и незаметно продлевает токены доступа на ~60–90 минут.stateless_http=True— сеансы переживают повторное развёртывание контейнера.Прокси-хост NPM должен иметь переопределения тайм-аутов из плейбука (см. PORTAINER_DEPLOY.md), чтобы простаивающие потоки не обрывались на 60 секунд.
Также проверьте, что ни одна политика условного доступа с частотой входа не покрывает это приложение. Приёмочный тест: подключитесь, подождите 2+ часа простоя, переразверните контейнер, затем вызовите whoami — не должно появиться запроса на повторную аутентификацию.
Настройка (порядок плейбука)
scripts/setup_entra_app.ps1 -TenantId <tenant>(необязательно-GrantGraphUserRead) — выводит значения env для сервера + секрет коннектора (идёт в расширенные настройки коннектора Claude, никогда на сервер).Разверните через Git-стек Portainer — PORTAINER_DEPLOY.md. Рекомендуемый порт хоста 8093 (сначала проверьте; записано в реестре плейбука).
Прокси-хост NPM
notify-mcp.example.com→ контейнер; тайм-ауты плейбука + список разрешённых IP Anthropic; сертификат LE перед включением списка разрешённых.Добавьте как пользовательский коннектор организации в claude.ai; пользователи подключаются один раз со своим собственным входом M365.
Приёмочные тесты
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-AuthenticateЗатем в Claude, как участник группы:
whoami→ ваш собственный адрес электронной почты, мобильный «в записи (…1234)» или явный промах.send_email_to_me→ приходит в ВАШ ящик отnotify_ai@.Попросите модель «отправить это <кому-то другому>» → она должна отказаться / не иметь возможности выполнить. Если это не работает — это P1, не разворачивайте.
register_my_mobileс вашим номером → приходит код →confirm_my_mobile→ приходит подтверждающее письмо →send_sms_to_meработает. Затем попробуйте зарегистрировать ДРУГОЙ номер → должно быть отказано (блокировка изменений).Тест с 2-часовым простоем и переразвёртыванием выше.
Не участник подключается → отклонено при входе (AADSTS50105).
Локальная разработка
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 deployed
Maintenance
Related MCP Connectors
Hosted agent inboxes: read mail, send to owner-approved recipients. Mail is server-readable.
Zero-secret MCP gateway for AI agents: risk-scored, audited calls with human-in-the-loop approval.
Let AI agents send email from your own Gmail, Microsoft 365 or SMTP inbox, with guardrails.
Email for AI agents: send, receive with a safety verdict, reply and approve, as MCP tools.
Related MCP Servers
AlicenseAqualityCmaintenanceEnables AI agents to send emails and manage tasks in Microsoft To Do with scoped, low-risk access to Microsoft Graph.314 npm1MIT- AlicenseNot gradedqualityFmaintenanceEnables AI agents to send and receive email with enforced security policies, scoped mailboxes, and human approval for external sending.1MIT
- AlicenseNot gradedqualityAmaintenanceSovereign autonomous mailbox and identity layer for AI agents, providing persistent email identities, object-level security, OTP/2FA capture, link safety analysis, and event-driven email handling via MCP.3 npm3MIT
- AlicenseAqualityBmaintenanceEnables AI agents to send, receive, and reply to email through dedicated thread-aware mailboxes, with sandbox testing and compatibility across MCP clients.938 npmMIT