Email Agent Mcp について
email-agent-mcpは、AIエージェントをMicrosoft 365 / OutlookおよびGmailのメールボックスに接続するオープンソースのTypeScript製MCPサーバーです。メールの閲覧、検索、下書き、操作を提供し、許可リストと慎重な初期設定で送信や削除を制御します。
主な機能
- 01メールの閲覧と検索
- 02スレッドの確認
- 03下書きの作成と更新
- 04許可リストによる送信と返信
- 05メールとフォルダーの整理
- 06読み取り専用の権限プロファイル
活用シーン
- 01受信トレイからメールを検索
- 02メールの下書きや返信を作成
- 03エージェントの送信先を許可された相手に限定
- 04読み取り専用のメールボックスを設定
MCP 対応
stdio経由でMCPクライアントにメールおよびメールボックス管理ツールを提供します。Microsoft 365 / OutlookとGmailに対応し、利用可能なツールはプロバイダーと権限プロファイルによって異なります。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
26掲載時のツール一覧 · 3 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| mailbox | string | いいえ | |
| unread | boolean | いいえ | |
| limit | number | いいえ | |
| offset | number | いいえ | |
| folder | string | いいえ |
詳細
Agent Email
English | Español | 简体中文 | Português (Brasil) | Deutsch
email-agent-mcp by UseJunior -- AI エージェント向けのローカルメール接続機能です。
Agent Email はオープンソースの TypeScript MCP サーバーです。Claude Code、Cursor、Gemini CLI、OpenClaw、その他の MCP 互換ランタイムから、自分のメールボックスを通じてメールの閲覧、スレッドの検索、返信の下書き作成、メッセージへのラベル付け、既読状態の変更、メッセージの移動、メールの送信を行えます。現在、Microsoft 365 / Outlook と Gmail に対応しています。セキュリティを最優先したデフォルト設定により、許可リストを明示的に設定するまでは、エージェントはメールを送信できません。
クイックスタート
npx -y email-agent-mcp
対話型セットアップウィザードで、OAuth の設定とメールボックスの選択を順に進められます。
現在利用できる機能
- MCP stdio 経由での Microsoft 365 / Outlook メールボックスへのアクセス
list_emails、read_email、search_emails、get_threadcreate_draft、update_draft、send_draft、send_email、reply_to_emaillabel_email、mark_read、move_to_folder- 送信許可リスト、デフォルトで無効化された削除機能、サニタイズされたエラー
現在のリリース準備段階では、実際の Outlook メールボックスを使用して、閲覧、下書き、送信、分類、移動、既読状態の各フローを検証しました。
開発の背景
AI エージェントには、メールの閲覧や返信、メールに対する操作が必要ですが、メール API は複雑です。OAuth フロー、Graph の差分クエリ、Gmail のプッシュサブスクリプション、HTML から Markdown への変換、スレッドのセマンティクスなど、プロバイダーごとに特有の動作があります。
Agent Email はこうした複雑さを、セキュリティガードレールを備えた決定論的な MCP ツールにまとめています。
- エージェントが連絡できる相手を制御する送信・受信許可リスト
- デフォルトでは削除機能が無効(明示的なオプトインが必要)
- API キー、ファイルパス、スタックトレースを除去するエラーのサニタイズ
- パストラバーサル対策を備えた本文ファイルのサンドボックス化
Claude Code での使用
~/.claude/settings.json またはプロジェクトの .claude/settings.json に追加します。
{
"mcpServers": {
"email-agent-mcp": {
"type": "stdio",
"command": "npx",
"args": ["-y", "email-agent-mcp"]
}
}
}
Cursor での使用
// .cursor/mcp.json
{
"mcpServers": {
"email-agent-mcp": {
"command": "npx",
"args": ["-y", "email-agent-mcp"]
}
}
}
Gemini CLI での使用
gemini extensions install https://github.com/UseJunior/email-agent-mcp
OpenClaw での使用
~/.openclaw/openclaw.json に mcp ブロックを追加します。
{
// ... existing config ...
mcp: {
servers: {
email: {
command: "npx",
args: ["tsx", "/path/to/email-agent-mcp/packages/email-mcp/src/serve-entry.ts"],
transport: "stdio"
}
}
}
}
バージョンに関する注意:
mcp設定キーを使用するには、OpenClaw アプリが 2026.3.24 以降である必要があります。CLI のバージョンがアプリより古い場合、ゲートウェイでは受け入れられても、検証時にこのキーが拒否されることがあります。NemoClaw ディレクトリでnpm install openclaw@latestを実行して CLI を更新するか、launchctl kickstart -k gui/501/ai.openclaw.gatewayを実行してゲートウェイを直接再起動してください。
メール監視
監視機能はメールボックスを定期的に確認し、新着メールが届くと OpenClaw に起動シグナルを送信します。
# Set the hooks token (must match hooks.token in openclaw.json)
export OPENCLAW_HOOKS_TOKEN="your-hooks-token"
# Start the watcher (defaults to http://localhost:18789/hooks/wake)
npm run dev:watch
監視機能を使用するには、少なくとも1つのメールボックスを設定する必要があります。最初に npx email-agent-mcp または npm run dev:configure を実行して、OAuth フローを完了してください。
デモ録画前のスモークテスト
デモを録画する前に、実際のメールボックスと安全な送信許可リストを使って、ライブスモークテストスクリプトを実行してください。スクリプトでは、次の項目をテストします。
get_mailbox_statuslist_emails+read_emailmark_read未読 -> 既読 -> 未読- 安全な受信トレイ候補に対する
label_email create_draft- 下書きのみの
reply_to_email send_email(任意)
例:
EMAIL_AGENT_MCP_HOME=/tmp/email-agent-mcp-live \
AGENT_EMAIL_SEND_ALLOWLIST=/tmp/email-agent-mcp-live/send-allowlist.json \
npm run launch:prep:smoke -- --live-write --send-to [email protected]
デフォルトの安全な候補の選択では、受信トレイにある [email protected] を検索します。これにより、顧客のメールではなく、一般に公開しても安全なメッセージを使って録画の流れをリハーサルできます。
メールボックスのステータス名がメールアドレスでない場合は、--reply-sender <email> を渡すか、EMAIL_AGENT_MCP_REPLY_SENDER を設定して、下書き返信の確認に使用する自分が送信したメッセージをスクリプトが検索できるようにしてください。
ツールリファレンス
スコーププロファイル
エージェントに公開する権限を選択するには、サーバーの設定と起動の前に
EMAIL_AGENT_MCP_SCOPE_PROFILE を設定してください。後方互換性のため、
デフォルトは full です。
| プロファイル | Microsoft の委任スコープ | 公開されるツール |
|---|---|---|
observe | Mail.Read、User.Read、offline_access | 読み取り専用のメールツール(list_inbox_rules を除く。下記参照) |
full(デフォルト) | Mail.Read、Mail.ReadWrite、Mail.Send、MailboxSettings.ReadWrite、User.Read、offline_access | すべてのツール |
監視のみのデプロイでは、OAuth の同意と MCP ツール一覧が一致するように、 設定時と実行時の両方でプロファイルを設定してください。
export EMAIL_AGENT_MCP_SCOPE_PROFILE=observe
npx email-agent-mcp configure
npx email-agent-mcp serve
observe のスコープは、意図的に full の厳密なサブセットになっています。
そのため、このプロファイルは導入しやすくなっています。すでにスコープ一式に同意済みのテナントでは、
observe は追加の同意を求めずに認可されるため、full から observe への切り替えで新たな同意は不要です。
一方、observe から full への切り替えでは、これまで許可されていないスコープを要求するため、新たな対話型の同意が必要です。
同じ理由から、observe では list_inbox_rules は公開されません。
Graph では /mailFolders/inbox/messageRules へのアクセスに MailboxSettings が必要です。また、Entra では
MailboxSettings.Read は full の MailboxSettings.ReadWrite に含まれるものとはみなされず、
独立したスコープとして扱われます。これを要求するとサブセットの性質が損なわれ、
observe をデプロイするたびに新たな同意が必要になります。ユーザーによる同意を制限するテナントでは、
管理者の承認も求められます。受信トレイのルールを参照する必要がある場合は、full を使用してください。
無効なプロファイル値が指定されると、より広いアクセス権を暗黙に許可することなく、起動が停止します。 キャッシュされた資格情報がプロファイルのスコープを満たさない場合、サーバーは対話型サインインで処理を停止させず、 具体的な対処方法を示すエラーを返して速やかに終了します。
observe で保証されることと、保証されないこと
observe は MCP ツールの一覧から書き込みツールを常に除外するため、
エージェントはそれらを呼び出せません。この点はどの環境でも変わりません。
書き込みスコープにまだ同意していないメールボックスでは、OAuth トークンのスコープのみが狭まります。
Entra は、トークン取得時に要求されたサブセットだけでなく、そのアプリケーションに対してユーザーまたはテナントが
すでに同意したすべてのスコープを含むアクセストークンを発行します。そのため、以前 full として設定した
メールボックスで observe を使用すると、基盤となるトークンには引き続き Mail.ReadWrite と
Mail.Send が含まれます。縮小されるのはツールの一覧だけです。
最小権限のトークンを実際に使用するには、書き込みスコープが一度も許可されていないメールボックスから
observe に同意してください。つまり、委任アクセス許可が Mail.Read/User.Read までに限定された
アプリ登録に対して、新たに configure を実行します。許可を管理できない場合は、
ツール一覧の縮小を OAuth の境界としてではなく、多層防御の一環として扱ってください。
ツール
full プロファイルでは27個の MCP ツールが公開されます。observe では、メールボックスを変更する操作として
マークされたすべてのツールが除外されます。
| ツール | 説明 | 種類 |
|---|---|---|
list_emails | フィルターを指定して最近のメールを一覧表示します | 読み取り |
read_email | メールの全文を Markdown として読み取ります。format: "html" を指定すると生の HTML を読み取ります | 読み取り |
search_emails | メールボックス全体を対象に全文検索します | 読み取り |
list_mailboxes | 設定済みのメールボックス、そのステータス、およびデフォルトを一覧表示します | 読み取り |
get_mailbox_status | 接続ステータスと警告を取得します | 読み取り |
get_thread | 会話全体のコンテキストを取得します | 読み取り |
list_attachments | メールの添付ファイルのメタデータを一覧表示します | 読み取り |
download_attachment | 添付ファイルを base64 としてダウンロードするか、save_to を指定してサンドボックス化されたディレクトリに保存します | 読み取り |
download_message | メッセージ全体を、生の .eml ファイルとしてサンドボックス化されたディレクトリに保存します | 読み取り |
send_email | 新しいメールを送信します(許可リストによる制限あり) | 書き込み |
reply_to_email | スレッド内で返信します(送信時に許可リストによる制限あり) | 書き込み |
create_draft | メールの下書きを作成します | 書き込み |
update_draft | 下書きの内容を更新します | 書き込み |
send_draft | 保存済みの下書きを送信します | 書き込み |
list_scheduled_sends | 保留中の、プロバイダー側で保持されている予約送信を一覧表示します(Microsoft 365) | 読み取り |
cancel_scheduled_send | 保留中の予約送信をキャンセルします(Microsoft 365) | 破壊的 |
label_email | ラベル/カテゴリを適用します | 書き込み |
flag_email | メールにフラグを設定/解除します | 書き込み |
mark_read | 既読/未読に設定します | 書き込み |
move_to_folder | フォルダー間で移動します | 書き込み |
delete_email | メールを削除します(オペレーターの環境変数と呼び出し元のフラグが必要) | 破壊的 |
list_folders | フォルダーと算出されたパスを再帰的に一覧表示します(Microsoft 365) | 読み取り |
create_folder | カスタムの子フォルダーを作成します(Microsoft 365) | 書き込み |
delete_folder | カスタムフォルダーを削除します(オペレーターの環境変数と呼び出し元のフラグが必要)。システムフォルダーは保護されています(Microsoft 365) | 破壊的 |
list_inbox_rules | サーバー側の受信トレイルールを一覧表示します(Microsoft 365) | 読み取り |
create_inbox_rule | 永続的で安全な受信トレイルールを作成します。転送、リダイレクト、削除、および「削除済みアイテム」への破棄はブロックされます(Microsoft 365) | 書き込み |
delete_inbox_rule | サーバー側の受信トレイルールを削除します(オペレーターの環境変数と呼び出し元のフラグが必要)(Microsoft 365) | 破壊的 |
これは、複数のプロバイダーで共通のツールセットです。label_email、
flag_email、mark_read、move_to_folder は公開されていますが、Gmail
アダプターではこれらの変更機能を意図的に実装していません。これらのツールは
Gmail の変更リクエストを送信する前に NOT_SUPPORTED で失敗します。デフォルトの
gmail.readonly と gmail.compose の権限でも、これらの変更は許可されません。
ツールを利用可能にするために gmail.modify を追加しないでください。これらの
ツールは、アダプターと権限が対応しているプロバイダーでのみ利用できます。
Gmail では、delete_email は users.drafts.delete を使って下書きのみを
削除します。この操作は gmail.compose で許可されています。下書き ID(r…)または
下書きのメッセージ ID(folder: "drafts" を指定して list_emails が返す ID)の
いずれかを渡します。Gmail には下書き用のゴミ箱がないため、削除は完全に行われますが、
同じ AGENT_EMAIL_DELETE_ENABLED ゲートと
user_explicitly_requested_deletion フラグによる保護は適用されます。
AGENT_EMAIL_HARD_DELETE_ENABLED は必要ありません。送信済みまたは受信済みの Gmail
メッセージを削除しようとすると、gmail.modify が必要となるため NOT_SUPPORTED が
返されます。update_draft も Gmail ではどちらの ID も受け付けます。Gmail は下書きを
更新するたびに新しいメッセージ ID を割り当てますが、下書き ID は変わりません。そのため、
編集後は下書き ID を使うか、下書きを再度一覧表示してください。
list_emails、search_emails、get_thread が返すすべての行と、read_email のレスポンスには、常に isDraft ブール値が含まれます。isDraft: true は、そのメッセージが未送信の下書きであることを意味します。つまり、まだ送信されておらず、receivedAt はプロバイダーが提供するメタデータであり、配信された証拠ではありません。このフィールドが省略されることはないため、利用側のエージェントは「下書きではない」と「下書きかどうかが報告されていない」を区別できます。ただし、false が示すのは、プロバイダーがそのメッセージを未送信の下書きとしてマークしていないことだけであり、メールボックスの所有者が送信したという意味ではありません(受信メールも false です)。それ以外では、下書きはこれまでどおり一覧や検索結果に表示されます。
フォルダーと受信トレイルールの管理には、Microsoft Graph の MailboxSettings.ReadWrite 同意が必要です。既存の Microsoft メールボックス接続は、アップグレード後に再同意する必要があります。Gmail では階層型フォルダーやサーバー側の Exchange ルールではなくラベルを使用するため、これら6つのツールは Gmail メールボックスに対して NOT_SUPPORTED を返します。
本文の形式
双方向とも、本文はデフォルトで Markdown として送受信されます。このデフォルト設定には意図があります。Markdown はトークン効率がよく、通常の読み取りにかかるコストを抑えられます。どちらの方向も、この設定をオプトアウトできます。
書き込み — send_email、reply_to_email、create_draft、update_draft では、省略可能な format を指定できます。
format | 動作 |
|---|---|
markdown(デフォルト) | marked を使用して HTML にレンダリングします(GFM、breaks: true)。Markdown 内に埋め込まれた生の HTML は保持されます。 |
html | そのまま通過します。HTML はそのまま送信されます。 |
text | レンダリングせず、プレーンテキストとして送信します。 |
html はサニタイズされず、そのまま通過します。サニタイザーも許可リストもなく、マークアップの書き換えもありません。インライン CSS や任意のタグは送信時まで保持されます。これにより装飾付きメールを作成できますが、送信する内容には自分で責任を負う必要があります。デフォルトで行われる変更は、後述の黒色強制ラッパーのみです。force_black: false の場合、本文はバイト単位でそのまま通過します。
markdown と html では、レンダリングされた HTML が <div style="color: #000000;"> で囲まれます。これにより、Outlook のダークモードでテキストが白地に白で表示されるのを防ぎます。
本文ファイル — send_email、create_draft、update_draft では body_file も指定できます。.md、.html、.txt ファイルへのパスを指定すると、EMAIL_MCP_SAFE_DIR(デフォルトはプロセスの作業ディレクトリ)と、追加の AGENT_EMAIL_ALLOWED_DIRS のルートを基準にファイルが読み込まれ、body の代わりに本文として使用されます。.md 本文ファイルの先頭には、YAML フロントマターのブロックを含めることができます。
update_draft では、body と body_file は返信ではない下書きに限り指定でき、replace_body: true が必要です。この場合、保存済みの本文全体が置き換えられます。返信の下書き本文にはプロバイダーが組み立てた引用履歴が含まれているため、安全に編集できません。そのため、代わりに新しい下書きを作成してください。返信の下書きでも、件名、宛先、添付ファイルは引き続き更新できます。
---
to: [email protected]
subject: Quarterly summary
format: html
force_black: false
---
<p>The body starts after the closing delimiter.</p>
認識されるキーは to、cc、bcc、subject、reply_to、draft、format、force_black です(draft: true を指定すると、send_email の呼び出しは下書きの保存に切り替わります)。bcc は create_draft と update_draft に適用されます。send_email では、これを設定した本文ファイルは拒否され、Bcc なしで送信されることはありません。フロントマターの値は、同じ名前のツールパラメーターより優先されます。フロントマターが解析されるのは .md ファイルのみです。また、ファイル拡張子によって形式が選ばれることはありません。format ツールパラメーターを明示しない場合、.html 本文ファイルもデフォルトの Markdown レンダリングになります。そのまま通過させるには format: "html" を指定してください。
読み取り — read_email では、省略可能な format として markdown(デフォルト)または html を指定できます。
{ "id": "AAMkAD...", "format": "html" }
format: "html" を指定すると、メッセージの生の本文 HTML がそのまま返されます。Markdown では保持できない装飾(color、background-color、text-decoration、<u> など)が必要な場合に使用してください。たとえば、書式付き本文の残りの部分には手を加えず、1つの文だけを変更できます。Markdown 経由では、こうした装飾は出力時に気づかないうちに失われます。
これに伴い、次の2つのフィールドも返されます。
bodyFormat— 常に存在します:markdown、html、またはtextです。htmlを指定してもメッセージに HTML パートがない場合はtextが返され、その場合はプレーンテキストの本文が返されます。本文を書き戻す前に、これを確認してください。bodyTruncated— 本文がformat: "html"のレスポンス上限 256 KB を超えた場合にのみ存在し、値はtrueになります(これまでどおり、markdown の経路には上限がありません)。切り詰められた本文を下書きに書き戻さないでください。
生の HTML は、markdown に変換した場合よりもはるかに多くのトークンを消費するため、スタイル設定が必要な場合を除き、デフォルトのままにしてください。strip_quoted_history と strip_signatures は markdown 形式のテキスト変換であり、format が html の場合は適用されません。生の HTML がそのまま返されます。
書き戻す場合。 format: "html" と force_black: false を渡してください:
{ "draft_id": "AAMkAD...", "body": "<edited html>", "format": "html", "force_black": false }
force_black のデフォルトは true で、送信した HTML を <div style="color: #000000;"> で囲みます。自分で作成した HTML には適切ですが、読み戻したばかりの本文に使うと、サイクルごとにラッパーがさらに 1 つネストされます。修正を 15 回行うと、ネストされた div が 15 個になります。force_black: false にすると、ラウンドトリップ後もバイト列が変更されずに保たれます。
予約送信
send_email と send_draft は、明示的なタイムゾーンを含む ISO 8601 形式の未来のタイムスタンプである scheduled_send_at を受け付けます。Microsoft 365 がメッセージをサーバー側で保持するため、このプロセスが終了しても配信されます。保留中は、返された messageId を cancel_scheduled_send とともに使ってキャンセルするか、list_scheduled_sends で保留中の項目を確認してください。この一覧には、このサーバー経由で予約したものだけでなく、Outlook 自体から予約したメッセージも含まれます。Outlook は保持中のメッセージを任意の場所(多くの場合は「削除済みアイテム」)に置くため、検出時にはフォルダーではなくメールボックスがスキャンされ、送信予定時刻がまだ先のものだけが報告されます。
Microsoft Graph は、保持中の下書きが「送信済みアイテム」に移動するとメッセージ ID を変更します。そのため、返される ID は配信前の管理用ハンドルであり、送信済みメッセージの永続的な ID ではありません。Gmail の公開 API は予約送信を公開していません。Gmail では、即時送信の動作は変わらず、予約送信のすべてのインターフェースが NOT_SUPPORTED を返します。
送信する添付ファイル
send_email、reply_to_email、create_draft、update_draft では、省略可能な
attachments 配列を指定できます。各要素には、サンドボックス化されたファイルの path(
EMAIL_MCP_SAFE_DIR を基準に読み込みます。デフォルトはプロセスの作業ディレクトリです。また、以下で説明する
AGENT_EMAIL_ALLOWED_DIRS の各ルートも対象です)、またはインラインの base64 を指定し、
省略可能な filename/mimeType の上書きも指定できます。
{
"to": "[email protected]",
"subject": "Signed agreement",
"body": "Attached as requested.",
"attachments": [
{ "path": "./out/agreement.pdf" },
{ "base64": "iVBORw0KGgo...", "filename": "screenshot.png" }
]
}
ファイルの上限はそれぞれ 25MB です。ファイルが小さなインラインリクエストのサイズに収まらない場合、Microsoft Graph はチャンクアップロードセッションを自動的に使用します。メッセージが 5MB を超える場合、Gmail は raw MIME メディアアップロードを自動的に使用します。どちらの方法も、送信、返信、下書きの作成/更新で機能します。update_draft で attachments を省略すると、下書きに既存のファイルが保持されます。配列を渡すと(空の配列でも)、既存のファイルが置き換えられます。
作業ディレクトリ外のファイルを添付する場合 — AGENT_EMAIL_ALLOWED_DIRS に、区切り文字で区切った絶対パスのディレクトリ一覧を設定します(macOS/Linux では :、Windows では ;。先頭の ~ は展開されます)。これらのディレクトリも attachments[].path と body_file から読み取れるようになります。
{
"mcpServers": {
"email-agent-mcp": {
"command": "npx",
"args": ["-y", "@usejunior/email-agent-mcp"],
"env": { "AGENT_EMAIL_ALLOWED_DIRS": "~/Downloads:/Volumes/Shared/Contracts" }
}
}
}
呼び出し元のパスが解決される仕組み — 以下の 2 つのルールでは、どちらも FILE_NOT_FOUND が返されます。ファイルが存在しないと誤解しやすいため、ご注意ください。
| 渡すパス | 解決先 | 許可されたルート内のファイルが見つかるか |
|---|---|---|
contract.pdf | EMAIL_MCP_SAFE_DIR(デフォルト:cwd) | ❌ 相対パスでは追加のルートを検索しません |
~/Downloads/contract.pdf | EMAIL_MCP_SAFE_DIR — ~ は展開されません | ❌ |
/Users/you/Downloads/contract.pdf | 各ルートを順番に検索 | ✅ |
~ の省略表記は AGENT_EMAIL_ALLOWED_DIRS(オペレーターの設定)では展開されますが、attachments[].path や body_file(呼び出し元の引数)では展開されません。これらには絶対パスを渡してください。また、相対パスは意図的に安全なディレクトリ内に限定されています。単なる contract.pdf を許可されたすべてのルートから検索すると、最初に見つかったコピーが知らないうちに添付される可能性があるためです。
包含チェックの前に、各ルートは realpath で正規化されます。許可リストに登録されたルート自体がシンボリックリンクの場合は実際の場所に解決され、正規化できないルートは何も許可しません。いずれのルートからも外れるシンボリックリンクも、引き続き拒否されます。未設定の場合(デフォルト)は作業ディレクトリだけがルートになります。そのため、ファイルにアクセスできないエージェントは、機密文書を git の作業ツリーにコピーするのではなく、そのディレクトリを許可リストに追加するよう依頼してください。
ディレクトリを許可リストに追加すると、そこに書き込み可能なすべてのユーザーが信頼されます。パスの検証とファイルのオープンは別々の操作であるため、許可されたルート内のディレクトリをその間に置き換えられる主体がいる場合、読み取り先を変更される可能性があります。信頼できないユーザーが親ディレクトリに書き込めないルートだけを許可リストに追加してください。検証後にファイル自体がシンボリックリンクに差し替えられないよう、最終的なファイルは O_NOFOLLOW を付けてオープンされます。
添付ファイルとメッセージをディスクに保存する
download_attachment はデフォルトでインラインの base64 を返します(デフォルトの上限は 5 MB、最大 25 MB)。代わりにサーバーにファイルを書き込ませるには、save_to を指定します。返されるのはメタデータのみなので、大きな添付ファイル(画面録画、音声、大きな PDF)がエージェントのコンテキストを通過することはありません。
{ "message_id": "…", "attachment_id": "…", "save_to": "/Users/you/Downloads/records" }
{ "success": true, "path": "/Users/you/Downloads/records/Signed_Agreement.pdf",
"filename": "Signed_Agreement.pdf", "original_filename": "Signed Agreement.pdf",
"mimeType": "application/pdf", "size": 782957, "sha256": "…" }
download_message は、受信したメッセージをそのまま RFC 822 MIME の生データ(Graph の /$value、Gmail の format=raw)として <subject>.eml に書き込み、同じメタデータを返します。添付ファイルと一緒に記録用のコピーを残す場合に使用します。
save_to はディレクトリを指定し、body_file および attachments[].path とまったく同じ方法で解決されます。相対パスは EMAIL_MCP_SAFE_DIR を基準に解決され、AGENT_EMAIL_ALLOWED_DIRS のルートには絶対パスが必要です。..、先頭の ~、およびサンドボックス外に抜けるシンボリックリンクは拒否されます。存在しないサブディレクトリは作成されます。既存のファイルが上書きされることはありません。名前が衝突した場合は数値の接尾辞が付きます(report.pdf、report-1.pdf、…)。ファイルはモード 0600 で作成されます。size と sha256 は書き込まれた正確なバイト列を示します。これは、プロバイダーが MIME のオーバーヘッドを数えるため、list_attachments が報告するサイズとわずかに異なる場合があります。save_to を指定した場合、max_size_mb のデフォルト値と上限は 150 MB です。上限を超えるインラインダウンロードは ATTACHMENT_TOO_LARGE で失敗し、save_to を使うよう案内されます。
プロバイダーのサポート状況
| プロバイダー | 状況 | パッケージ |
|---|---|---|
| Microsoft 365(Graph API) | 完全にサポート | @usejunior/provider-microsoft |
| Gmail | インタラクティブな CLI OAuth(デフォルトのクライアントまたは独自のクライアント)または手動でのリフレッシュトークン設定でサポート | @usejunior/provider-gmail |
email-agent-mcp configure --provider gmail を使ってローカルブラウザーでの OAuth フローを実行するか、~/.email-agent-mcp/tokens/ の下に手動でメールボックスのトークンファイルを追加してください。下記の Gmail のセットアップ と packages/provider-gmail/README.md を参照してください。
Gmail のセットアップ
Gmail では、サポートされている OAuth の方法が 2 つあります。どちらも最終的には同じ結果になります。マシン上にリフレッシュトークンが保存され、Gmail API 呼び出しがマシンから Google に直接送信されます。
| 方法 | コマンド | Google Cloud プロジェクトは必要ですか? |
|---|---|---|
| デフォルトの OAuth クライアント | email-agent-mcp configure --provider gmail | いいえ |
| 独自のキーを使用(BYOK) | 同じコマンドに --client-id / --client-secret を追加 | はい(ご自身のプロジェクト) |
現時点でのおすすめ:BYOK。 Google による検証が進行中のため、デフォルトの OAuth クライアントは引き続き Google の公開ステータスが「Testing」となっています。そのため、登録できるテストユーザーは 100 人に制限され、同意画面の前に「Google hasn’t verified this app」という中間画面が表示されます。Gmail の制限付きスコープの検証には CASA セキュリティ評価が必要で、数週間かかります。進捗は issue #112 で確認できます。BYOK を使うと、共有のユーザー数 100 人の上限を回避でき、アプリの公開ステータスを自分で管理できます。ただし、独自のアプリも公開するまでは Google の Testing に関する制約を受けます。
BYOK を選ぶその他の理由として、専用の API クォータ、独自のプライバシーポリシーと検証ステータスを利用できること、ホスト型ブローカー https://oauth.usejunior.com に依存しないことが挙げられます。
要求されるスコープ
Agent Email では、デフォルトで次の2つの Gmail スコープのみを要求します。
https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/gmail.compose
gmail.readonly はメッセージとスレッドの読み取りに必要です。
gmail.compose は下書きの管理と送信を行いますが、
users.threads.get または users.messages.get の権限は付与しません。デフォルトの許可には
gmail.modify は含まれません。また、Gmail アダプターでは意図的にラベルの
変更、既読状態の変更、移動、ゴミ箱への移動、および送信済みまたは受信済み
メールの削除をサポートしていないため、これらのツールは NOT_SUPPORTED で安全側に失敗します。下書きの削除はデフォルトの許可で実行できます。OAuth
同意画面に両方のスコープを追加してください。
GMAIL_OAUTH_SCOPES を明示的に設定しているデプロイでは、値を上記の2つの
スコープをスペースで区切ったものに更新してください。新規認証と再認証では、
新しいスコープの組み合わせへの再同意が必要です。既存のメールボックスファイルと、そこに保存されている
リフレッシュトークンのメタデータは変更されません。
BYOK:独自の Google OAuth クライアントを作成する
- Google Cloud Consoleでプロジェクトを作成するか、 既存のプロジェクトを選択します。
- APIs & Services → Library → Gmail API → Enable でGmail API を有効にします。
- APIs & Services → OAuth consent screen でOAuth 同意画面を設定します。
- 個人の
@gmail.comアカウントではユーザータイプを外部にします。Google Workspace を使用しており、 自分の組織だけがアクセスする場合は内部にします。 https://www.googleapis.com/auth/gmail.readonlyとhttps://www.googleapis.com/auth/gmail.composeの両方を追加します。- アプリが Testing の間は、Test users に自分の Gmail アドレスを追加してください。 追加しないと同意が拒否されます。
- 個人の
- APIs & Services → Credentials → Create
credentials → OAuth client ID でOAuth クライアントを作成します。アプリケーションの種類にはDesktop appを選択します。
configureは一時的なリスナーをエフェメラルな ループバックポート(http://127.0.0.1:<port>/oauth2callback)で起動し、Desktop クライアントの場合のみ、正確なリダイレクト URI を事前登録せずに任意のループバックポートを Google が受け入れるため、Desktop が必須です。Web application クライアントではredirect_uri_mismatchが発生します。 - クライアント ID とクライアントシークレットをコピーします。
BYOK:認証情報を email-agent-mcp に渡す
両方の値をフラグとして渡します。
npx email-agent-mcp configure \
--provider gmail \
--mailbox personal \
--client-id YOUR_GOOGLE_CLIENT_ID \
--client-secret YOUR_GOOGLE_CLIENT_SECRET
または、名前空間付きの2つの環境変数を設定し、フラグを省略します。
export AGENT_EMAIL_GMAIL_CLIENT_ID=YOUR_GOOGLE_CLIENT_ID
export AGENT_EMAIL_GMAIL_CLIENT_SECRET=YOUR_GOOGLE_CLIENT_SECRET
npx email-agent-mcp configure --provider gmail --mailbox personal
両方の値が必要です。片方だけを指定すると、デフォルトのクライアントに 暗黙的にフォールバックせず、エラーで終了します。どちらも指定しない場合は、デフォルトの OAuth クライアントが選択されます。
ブラウザーで Google の同意画面が開き、CLI がループバックでコールバックを受け取り、
PKCE を使用してコードを交換した後、メールボックスを
~/.email-agent-mcp/tokens/<safe-key>.json に保存します。このファイルには、
clientId、clientSecret、取得した refreshToken とともに "source": "byok" が
記録されます。その後のトークン更新は Google のトークンエンドポイントに直接送信され、ブローカーは介在しません。
すでに保存されているメールボックスに対して configure を再実行すると、保存済みの認証情報が再利用されるため、
フラグを渡すのは最初の一度だけです。デフォルトのクライアントを使って以前設定したメールボックスに対して
--client-id と --client-secret を渡すと、BYOK に移行します。
BYOK:許可が7日後に期限切れにならないようにする
Testing の公開ステータスで あなたの OAuth アプリを使用している間は、Google がリフレッシュトークンを7日後に
期限切れにするため、週に1回ほど再認証を求められます。メールボックスがその期限に近づくと、
email-agent-mcp status が警告します。アプリを公開すると(OAuth consent screen → Publish app)、
7日間の有効期限がなくなります。アプリを所有しているのはあなたで、ユーザーもあなただけなので、
いずれの場合もユーザー数100人のテスト上限は適用されません。
Gmail の接続を解除してアクセス権を取り消す
接続の解除は、次の 2 つの独立した手順で行います。
- 実行中の
email-agent-mcpプロセスをすべて停止します。Finder で~/.email-agent-mcp/tokens/を開き、接続を解除するメールボックスに対応する JSON ファイルを 1 つ特定して、そのファイルだけをゴミ箱に移動します。ファイルの内容を開いたり、貼り付けたり、共有したりしないでください。また、ほかのメールボックスが設定されている場合は、~/.email-agent-mcpディレクトリ全体を削除しないでください。EMAIL_AGENT_MCP_HOMEを設定している場合は、代わりにそのディレクトリ内のtokens/フォルダーを使用します。 - Google アカウントのサードパーティ接続を開き、Email Agent MCP(または BYOK アプリケーションの名前)を選択して、アクセス権を削除します。
ローカルファイルを削除すると、このインストールが保存済みの認証情報を使用できなくなります。Google アカウントの接続を削除すると、Google で付与された権限が取り消されます。その後、email-agent-mcp status を実行して、メールボックスが設定されていないことを確認します。
セキュリティのデフォルト設定
Agent Email は制限の厳しいデフォルト設定で提供されており、必要に応じて緩和できます。
- 送信許可リスト:デフォルトでは空です。受信者を追加するまで、エージェントはメールを送信できません。
- 受信許可リスト:デフォルトではすべてを受け入れます。ウォッチャーを起動する送信者を制御します。
- 削除は無効:デフォルトでは、エージェントはメールを削除できません。次の 2 つの条件を両方満たす必要があります。
- オペレーターが email-agent-mcp のプロセス環境で
AGENT_EMAIL_DELETE_ENABLED=trueを設定します(完全に削除する場合はAGENT_EMAIL_HARD_DELETE_ENABLED=trueも設定します)。変更後は再起動が必要です。Gmail で削除できるのは下書きのみで、下書きの削除は常に完全削除となります。その場合、必要なのはAGENT_EMAIL_DELETE_ENABLEDのみです。 - 呼び出し元がツール呼び出しで
user_explicitly_requested_deletion: trueを渡します。
- オペレーターが email-agent-mcp のプロセス環境で
- エラーのサニタイズ:API キー、ファイルパス、スタックトレースはエラーレスポンスから伏せられます。
- 本文ファイルのサンドボックス化:
../によるディレクトリ遡り、シンボリックリンク、バイナリファイルを検出します。 - 重複配信の防止:デフォルトで有効です。15 分以内に同一のメール送信、返信、または下書き送信が繰り返された場合、二重に配信されないよう拒否します。
重複配信ガード
プロバイダーの送信エンドポイント(Graph の POST /sendMail、Gmail の users.messages.send)は冪等性キーを受け付けないため、Agent Email は各配信を厳密に 1 回だけ実行し、自動的に再試行することはありません。これにより、ライブラリによるメッセージの重複送信は防げます。しかし、呼び出し元による重複送信は防げません。ツールの結果を受け取れなかったエージェント(コンテキストの圧縮、トランスポートの切断、スーパーバイザーによるターンの再起動、応答が止まったように見えて人が再試行する場合など)が、同じ承認済み指示を再実行すると、2 回目の呼び出しは初回とまったく同じように見えます。
そのため、send_email、reply_to_email、send_draft は各配信をインプロセスの台帳に記録します。キーは、有効なアクション入力(メールボックス、宛先、件名、レンダリング済み本文、添付ファイルの内容、返信元メッセージまたは下書きの ID)のダイジェストです。(最終的なワイヤー上のバイト列ではなく、有効な入力を使います。プロバイダーは送信時にメッセージを変換することがあり、たとえば Graph は件名を 255 文字で切り詰めるため、異なる入力が同じメールとして送信される場合があります。このガードが検出するのは、実際に起こるツール呼び出しの再実行です。)ウィンドウ内で同じ内容が繰り返された場合、配信の実行前に拒否されます。
| コード | 意味 | 対処方法 |
|---|---|---|
DUPLICATE_SEND_IN_FLIGHT | 同一の配信がまだ応答を返していません | 最初の呼び出しを待ちます |
DUPLICATE_SEND_BLOCKED | 同一の配信はすでに成功しています | 停止します。応答には元の messageId が含まれています |
DUPLICATE_SEND_UNRESOLVED | 同一の配信が曖昧な結果で終了しました | 再送信する前に「送信済みアイテム」を確認します |
配信されなかったことが確実にわかる失敗(4xx に由来するコード、429、接続失敗)は、記録がすぐに解除されるため、拒否後に再送信してもブロックされることはありません。それ以外は、これまでに確認していないプロバイダーのコードも含め、未解決として保留されます。誤って保留した場合の損失は再送信が 1 回ブロックされることですが、誤って解除した場合は誰かの受信トレイに重複メールが届きます。
意図的に同じメッセージを再送信するには、allow_duplicate: true を指定します。これはリクエストごとの無条件のバイパスです。このフラグを付けて再実行すると、再度配信されます。このフラグは人が送信を決定したことを示すためです。強制送信の試みは以前の記録を置き換えず、その記録と並行して保持されます。そのため、上書き送信が拒否された場合も、元の配信によって通常の再実行は引き続き拒否されます。
記録はメールボックス単位で管理されます。呼び出し元が指定した場合は mailbox、指定がない場合はプロバイダーインスタンスが使われます。運用者は AGENT_EMAIL_DUPLICATE_SEND_WINDOW_MS を設定してウィンドウを変更できます(デフォルトは 900000)。0 に設定するとガードが完全に無効になります。
台帳はサーバープロセス内のメモリ上にあります。稼働中のサーバー内での再試行という、実際に起こる再実行の期間をカバーしますが、サーバーを再起動すると保持されません。
パッケージ
| パッケージ | 説明 |
|---|---|
@usejunior/email-core | メールのコアアクション、コンテンツエンジン、セキュリティ、プロバイダーインターフェイス |
@usejunior/email-mcp | MCP サーバーアダプター、CLI、ウォッチャー |
@usejunior/provider-microsoft | Microsoft Graph API のメールプロバイダー |
@usejunior/provider-gmail | Gmail API のメールプロバイダー |
email-agent-mcp | 配布用ラッパー(npx email-agent-mcp) |
@usejunior/email-agent-mcp | 互換性用ラッパー。バージョンは他のパッケージと同期して公開されます。新規インストールには email-agent-mcp を使用してください |
品質と信頼性の指標
- すべてのプルリクエストと main へのプッシュで CI を実行します(Node 20 + 22 での lint、型チェック、テスト)
- CodeQL と Semgrep によるセキュリティスキャン
- Codecov でカバレッジを公開
npm run check:spec-coverageによる OpenSpec のトレーサビリティ検証- テストスイート全体で 300 件以上のテスト
- メンテナー:Steven Obiajulu
アーキテクチャ
email-agent-mcp/
├── packages/
│ ├── email-core Core actions, content engine, security
│ ├── email-mcp MCP server adapter, CLI, watcher
│ ├── provider-microsoft Microsoft Graph provider
│ ├── provider-gmail Gmail API provider
│ └── email-agent-mcp Distribution wrapper (npx entry point)
├── openspec/ Spec-driven development
└── scripts/ CI and validation scripts
リリース
GitHub Actions によるタグ駆動のリリースと、npm OIDC の信頼された公開を使用します。6 つすべてのパッケージを依存関係の順に --provenance 付きで公開し、その後 mcp-publisher で server.json を公式 MCP Registry に公開します。
FAQ
Claude Code で動作しますか?
はい。npx email-agent-mcp を実行して MCP サーバーを起動し、Claude Code の設定で構成してください。
エージェントは許可なくメールを送信できますか?
いいえ。送信許可リストはデフォルトで空です。許可する宛先を明示的に設定するまで、エージェントはメールを一切送信できません。
メールの認証情報は保存されますか?
OAuth トークンは MSAL(Microsoft)によって管理され、OS のキーチェーンまたは ~/.email-agent-mcp/ 以下のローカル設定ファイルに保存されます。Agent Email が生のパスワードを保存することはありません。
複数のメールボックスを接続できますか?
はい。Microsoft 365 と Gmail を同時に設定できます。読み取り操作ではプライマリメールボックスがデフォルトで使用されます。複数のメールボックスが設定されている場合、書き込み操作ではメールボックスを指定する必要があります。
OpenClaw CLI が「Unrecognized key: mcp」というエラーで設定を拒否します
OpenClaw CLI と macOS アプリのバージョンが異なる場合があります(ゲートウェイを実行するアプリでは、CLI がまだ認識していない設定キーがサポートされていることがあります)。CLI を更新してください:cd ~/Projects/NemoClaw && npm install openclaw@latest。または、ゲートウェイを直接再起動してください:launchctl kickstart -k gui/501/ai.openclaw.gateway。
ウォッチャーは起動しますが、メールボックスが 0 件と表示されます
メールボックスの認証情報は ~/.email-agent-mcp/tokens/ に保存されます。このディレクトリが空の場合は、npx email-agent-mcp または npm run dev:configure を実行して OAuth 認証を行ってください。少なくとも 1 つ設定されるまで、ポーリング対象のメールボックスがないためウォッチャーは終了します。
OpenClaw に「Demo mode -- run email-agent-mcp configure to connect」と表示されます
MCP サーバーは実行中ですが、実際のメールボックスの認証情報がありません。npx email-agent-mcp を実行して OAuth の対話型セットアップを完了し、OpenClaw ゲートウェイを再起動して、有効なトークンで MCP サーバーが再接続するようにしてください。
認証したばかりなのに、1 週間後にトークンの有効期限が切れました
Microsoft のリフレッシュトークンは通常 90 日間有効ですが、Azure AD テナントでより短い有効期間が設定されている場合があります。このコードは OS のキーチェーン永続化機能(@azure/identity-cache-persistence)とともに MSAL を使用しており、サイレントなトークン更新を自動的に処理します。MSAL が interaction_required または invalid_grant を報告した場合は、npx email-agent-mcp を再実行して再認証してください。よくある原因として、条件付きアクセス ポリシー、MFA の再確認要件、または管理者が設定したトークン有効期間ポリシーがあります。
OpenClaw の Telegram ボットはメッセージを受信しますが、応答しません
openclaw status で Telegram チャネルが正常か確認してください。チャネルが OK と表示されるのに応答が返ってこない場合は、次の点を確認してください。(1)Telegram のユーザー ID が openclaw.json の channels.telegram.allowFrom に含まれていること、(2)channel: "telegram" に一致するバインディングがあること、(3)設定変更後にゲートウェイを再起動していること。所有者が 1 人のボットでは、ペアリング承認に頼るのではなく、明示的な allowFrom ID を指定した dmPolicy: "allowlist" を使用してください。
開発
npm ci
npm run build
npm run lint --workspaces --if-present
npm run test:run
npm run check:spec-coverage
関連項目
- Safe DOCX Suite -- コーディングエージェントを使った Word 文書の精密な編集
- Open Agreements -- コーディングエージェントを使った標準的な法的テンプレートへの記入
プライバシー
Agent Email はすべてローカルマシン上で動作します。メールの認証情報は OS のキーチェーン(MSAL)とローカル設定ファイルに保存されます。Agent Email 自体がメールの内容を外部サーバーに送信することはありません。
ガバナンス
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。