notify-mcp
notify-mcp
Example Corp スタッフ向けの自己宛てメール+SMS配信を、Entra 認証付きリモート MCP サーバーとして実現します。これは claude.ai チーフ・オブ・スタッフ展開における送信経路であり、エージェントはサインイン中のユーザー自身のコンテンツをメールまたはテキストで送信でき、構造的にそれ以外のことはできません。
不変条件(このサーバーが存在する理由)
信頼できないコンテンツ(受信メール、チケット、チャット)を読み取るエージェントは、無制限の送信機能を保持してはなりません。プロンプトインジェクションによって、それがデータ流出経路に変わる可能性があるからです。このサーバーは、その問題を構造的に解決します:
受信者はツールのパラメータではありません。 メールは、検証済みの Entra トークンから取得した呼び出し元の UPN に送信されます。SMS は、記録上の呼び出し元の携帯電話番号に送信されます。完全に侵害されたモデルでも、何を送信するかは変更できますが、どこへ送信するかは変更できません。
FROM は
<agent>approver@example.comに固定されています。サーバーは人間になりすまして送信できないため、誰にもなりすますことはできません。Resend と Inteliquent のキーは、このコンテナ内にのみ存在します。ユーザーがキーを見ることはなく、各自の M365 ログインで認証します。
ユーザーごとの時間あたり予算と、送信ごとの監査ログ行。
Related MCP server: Mailbuttons MCP Server
ツール
ツール | 機能 |
| 送信先となるメールアドレスとマスクされた携帯電話番号を返します。まずこれで配線をテストします。 |
| 呼び出し元にメールを送信します。 |
| 会社の DID 13105550100 から呼び出し元の携帯電話番号にテキストを送信します。640 文字以内。 |
| SMS 設定を開始します:その番号に 6 桁のコードをテキスト送信します。 |
| 設定を完了します:コードを検証し、番号を保存し、変更通知メールをユーザーに送信します。 |
サーバーがあなたを識別する仕組み
Claude → Entra サインイン(ユーザー自身のログイン)→ すべてのツール呼び出しにベアラー JWT が付与 → AzureJWTVerifier が署名/発行者/対象者を検証 → preferred_username クレーム = 受信者。ユーザーごとの環境変数も設定も不要で、ID は暗号的に保証されます。
携帯電話番号はトークンに含まれないため、SMS は検証済み自己登録を使用します(Entra の mobilePhone を設定していないテナント向けに構築されています。当社も未設定です):
ユーザー(通常は CoS セットアップ面談中):「register my mobile 310-555-1212」→ サーバーはその番号に 6 桁のコードをテキスト送信します。
ユーザーがコードを入力 →
confirm_my_mobile→ 番号が UPN をキーとして/data/sms_directory.jsonに保存され、確認メールが送信されます。その後、変更はロックされます(
NOTIFY_ALLOW_MOBILE_CHANGE=false):確認済みの番号は、管理者がレジストリを編集することでのみ変更できます。コード検証は所有を証明し、変更ロック+メール通知は、インジェクションによる再バインド攻撃(悪意のあるコンテンツがテキストを別の場所にリダイレクトする)を無効化します。
解決順序:レジストリファイル(手動エントリはプレーン文字列、自己登録エントリはオブジェクト)→ オプションで Graph 経由の Entra mobilePhone(NOTIFY_GRAPH_LOOKUP_ENABLED=true + -GrantGraphUserRead。自己登録を使用している場合は不要)。
コネクタセッションの持続性(切断問題の修正)
コネクタが「切断」と表示されないようにするための 3 つの要素:
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)— サーバーの環境変数値とコネクタシークレットを出力します(シークレットは Claude のコネクタ詳細設定に入力し、サーバーには入れません)。Portainer Git スタックでデプロイ — PORTAINER_DEPLOY.md を参照。推奨ホストポートは 8093(事前にプローブし、プレイブックレジストリに記録)。
NPM プロキシホスト
notify-mcp.example.com→ コンテナへ。プレイブックのタイムアウト+Anthropic IP 許可リスト。許可リストを有効にする前に 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→ 自分のメールアドレス、携帯電話番号「on record (…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
AlicenseAqualityDmaintenanceEnables AI agents to send emails and manage tasks in Microsoft To Do with scoped, low-risk access to Microsoft Graph.33 npm1MIT- AlicenseNot gradedqualityBmaintenanceEnables AI agents to send and receive email with enforced security policies, scoped mailboxes, and human approval for external sending.264 npm1MIT
- 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.9 npm3MIT
- AlicenseAqualityBmaintenanceEnables AI agents to send, receive, and reply to email through dedicated thread-aware mailboxes, with sandbox testing and compatibility across MCP clients.957 npmMIT