gmail-mcp について
gmail-mcpは、運用者のCloudflareアカウントにデプロイするWorkerを通じて、GmailをClaudeなどのMCPクライアントに接続します。アカウントごとの複数接続に対応し、メールの閲覧、送信、返信、転送、添付ファイル、下書き、ラベル、スレッドを扱えます。
主な機能
- 01アカウントごとの複数接続
- 02メールの検索と閲覧
- 03メールの送信・返信・転送
- 04添付ファイルとインライン画像の処理
- 05下書き・ラベル・スレッドの管理
活用シーン
- 01個人用と仕事用のメールボックスを別々に利用
- 02MCPクライアントからメールを送信または返信
- 03添付ファイルや長いメールスレッドを閲覧
- 04ラベルを使ったGmailメールの整理
MCP 対応
Cloudflare WorkerがMCPエンドポイントでGmailツールを公開し、MCPクライアントのOAuth登録に対応します。各接続は1つのGoogleアカウントを認証し、リフレッシュトークンは運用者のCloudflareアカウントに保存されます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
gmail-mcp は Gmail を Claude およびその他の MCP クライアントに接続します。メールの検索と閲覧、引用履歴付きの送信と全員への返信、転送、添付ファイルやインライン画像の処理、下書き、ラベル、スレッドの管理を、複数の Google アカウントで同時に行えます。
これはご自身の Cloudflare Worker 上でリモートサーバーとして動作するため、同じ接続をノートパソコンの Claude Code、ブラウザーの claude.ai、スマートフォンの Claude から利用できます。各接続は1つの Google アカウントにサインインし、Google の更新トークンはご自身の Cloudflare アカウント内に保管されます。
このツールが選ばれる理由は2つあります。Claude と Google に組み込まれている Gmail コネクターはメールの閲覧と下書きの作成はできますが、送信はできず、アシスタントのアカウントごとに Google アカウントを1つしか保持できません。送信に対応するサーバーは、たいていローカルプロセスです。デスクでは問題ありませんが、スマートフォンからは利用できません。
比較
詳細な比較 — 6 つのプロジェクト、12 項目
| gmail-mcp | Claude · Google の組み込み機能 | taylorwilsdon/ google_workspace_mcp | ArtyMcLabin/ Gmail-MCP-Server | shinzo-labs/ gmail-mcp | aaronsb/ google-workspace-mcp | |
|---|---|---|---|---|---|---|
| 実行場所 | Cloudflare Workers | ベンダーがホスト | 自分のサーバーまたはローカル | ローカル | ローカル | ローカル |
| スマートフォンからアクセス可能 | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
| 複数のメールボックスを同時に利用 | ✅ 接続ごとにバインド | ❌ | ✅ 呼び出しごとに選択 | ❌ エイリアスのみ | ❌ | ✅ 呼び出しごとに選択 |
| メールの送信 | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
添付ファイル · インライン cid: 画像 | ✅ | ドキュメントなし | ✅ | ✅ | ❌ | ✅ |
| 引用履歴付きの全員に返信 | ✅ | ❌ | 下書きのみ | 引用なし | ❌ | ✅ |
| 転送 | ✅ | ❌ | ✅ | ❌ | ❌ | ✅ |
| 各パートの文字セットを尊重 | ✅ | — | ❌ UTF-8 を想定 | ❌ UTF-8 を想定 | ❌ | ❌ |
| CRLF によるヘッダーインジェクションを拒否 | ✅ | — | ✅ フレームワーク | ✅ 除去 | ❌ なし | ✅ |
| メールボックスの設定(フィルター、自動返信) | ❌ 対象外 | ❌ | フィルター | フィルター | ✅ | ❌ |
| ツール数 | 24 | 11–16 | 14(Gmail) | 30 | 64 | 11 |
| リフレッシュトークンの保管者 | あなた | ベンダー | あなた | あなた | あなた | あなた |
google_workspace_mcp は、ここで最も機能が充実したプロジェクトです。Gmail だけでなく Workspace 全体を対象としており、Gmail の署名を追加したり、URL から添付ファイルを直接取得したりできます。これらは gmail-mcp にはありません。 shinzo-labs/gmail-mcp は 64 個のツールを通じて、自動返信、代理人、S/MIME に対応しています。これらの機能は gmail.settings.* のスコープに属しており、gmail-mcp が要求することはないため、付与される権限にかかわらず利用できません。
残りの大部分を左右する設計上の違いが 2 つあります。呼び出しの引数でアカウントを振り分けると、1 つの権限付与で接続済みのすべてのメールボックスにアクセスできます。一方、メールボックスを接続にバインドする場合、引数を間違えても何にもアクセスできません。また、メールの読み取りでは、ローカルサーバーはすべてのパートを UTF-8 としてデコードします。そのため、ISO-2022-JP や Shift_JIS のメールは文字化けし、Gmail が添付ファイルの BLOB として保存する長いメッセージは本文が空で返されます。
デプロイ
所要時間は約 10 分です。Cloudflare アカウント、bun、Google アカウントが必要です。Cloudflare アカウントにドメインを設定する必要はありません。ドメインがない場合、Worker は workers.dev で応答します。
1 · Google OAuth クライアントを作成
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 は次の 2 つの手順のための API を提供していないため、Cloud コンソールで操作します。
- OAuth 同意画面 → 外部 を選び、対象ユーザー で アプリを公開 を押します。テスト中のままにすると、Google は 7 日後にすべてのリフレッシュトークンを失効させ、各接続もトークンとともに使えなくなります。公開すると、サインイン時に未確認アプリの警告が表示され、最大 100 アカウントまで利用できます。
- 認証情報 → 認証情報を作成 → OAuth クライアント ID → ウェブアプリケーション を選び、認証済みリダイレクト URI に
https://<your-host>/callbackを指定します。クライアント ID とシークレットを控えておきます。
<your-host> は Worker に割り当てるドメインか、そうでない場合に割り当てられる workers.dev のホスト名です。先にデプロイしてから戻って値を入力してもかまいません。Worker が / で表示するガイドに正確な値が記載されています。
2 · Worker をデプロイする
このボタンを押すと、リポジトリが GitHub アカウントにコピーされ、KV 名前空間と Durable Object が作成され、4 つのシークレットの入力を求められます。workers.dev にデプロイされます。カスタムドメインは、デプロイ後に Settings → Domains & Routes から追加できます。
代わりにターミナルから実行する場合:
git clone https://github.com/mkpoli/gmail-mcp && cd gmail-mcp
bun install
bun run setup
bun run setup を実行すると、応答するドメインを尋ねられ、OAUTH_KV 名前空間が新規作成または再利用され、クライアント ID とシークレットを入力し、Cookie キーが生成されてデプロイされます。最初の 2 つの回答は wrangler.local.jsonc に保存されます。このファイルは Git の無視対象です。wrangler.jsonc には特定のアカウントの名前空間や誰かのドメインは記載されていないため、クローンしたプロジェクトはどこにでもデプロイできます。単一のシークレットをローテーションするためにセットアップを再実行しても安全です。
3 · クライアントを接続する
クライアント ID とシークレットの欄は空のままにしてください。MCP クライアントが自分で登録します。
claude mcp add --transport http gmail-personal https://<your-host>/mcp
claude mcp add --transport http gmail-work https://<your-host>/mcp/work
Claude Code で /mcp を実行し、各接続を Google アカウントにサインインさせます。claude.ai では、同じ URL を使って Settings → Connectors → Add custom connector を選択します。/mcp/ の後には任意の 1 セグメントのラベルを指定できます。これにより、同じ URL を共有する 2 つのサーバーを受け付けないクライアントに対しても、1 つのデプロイで複数のメールボックスを提供できます。
デプロイ先では、https://<your-host>/ でこのガイドを提供します。
できること
| 📖 読み取り | ✍️ 書き込み | 🏷 整理 |
|---|---|---|
|
|
|
|
メールクライアントと同じ形式でメッセージを送信します。プレーンテキストに HTML の代替パート、ファイル添付、cid: で参照するインライン画像を加え、multipart/mixed › multipart/related › multipart/alternative の構造で入れ子にします。件名と表示名には RFC 2047、ファイル名には RFC 2231 を使用するため、日本語、中国語、絵文字もそのまま届きます。
reply_all は元のメールの Reply-To、From、To、Cc を読み取り、自分のアドレスと自分が差出人としてメールを送るすべてのアドレスを除外し、差出人が宛先に指定したアドレスから返信します。また、References の連鎖を引き継ぎ、送信するパートで元のメールを引用します。forward_message は転送時のヘッダーを再現し、元の添付ファイルも再添付できます。すべてのファイルを添付できない場合は、何も送信されません。
replyToMessageId を指定した create_draft は、送信前に編集できる返信の下書きを作成します。元のスレッドに追加され、In-Reply-To と References を引き継ぎ、全員への返信の宛先と Re: の件名を生成して、元のメールを引用します。update_draft は指定されたフィールドのみを変更します。宛先、本文、任意のクライアントで手動追加されたファイル、下書きが返信するスレッドは読み戻され、そのまま保持されます。ツールの引数で送るには base64 が大きすぎるファイルは、代わりにステージングします。stage_attachment_begin は、curl -T で生のバイト列を一度に送信できるアップロード URL を返します。stage_attachment_append は base64 を分割して受け取り、すべての attachments フィールドで、結果として得られる stagingId を指定できます。
読み取り量には意図的に上限を設けています。メッセージとスレッドの本文には文字数の上限があり、レスポンス全体にはバイト数の上限があります。また、添付ファイルは読み取れる小ささの場合に限り、インラインで返されます。長いメーリングリストのスレッドは、アシスタントのコンテキストを埋め尽くすのではなく、切り詰められたうえでその旨を示す注記とともに返されます。大きなファイルは、セッションが開いている間の 1 時間有効なダウンロードリンクとして返されます。curl -o を使えば、バイト列を会話に通すことなくディスクに保存できます。
仕組み
1 つの Worker で 2 つの OAuth フローが連携します。MCP クライアントは Worker に対して認証し、Worker はユーザーに代わって Google に対して認証します。どちらも相手の認証情報を保持しません。
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
| レイヤー | ファイル | 機能 |
|---|---|---|
| 🔐 MCP 側の OAuth | workers-oauth-provider | 動的なクライアント登録、PKCE、Google トークンを封印して KV に保存するグラント |
| 🔗 Google 側の OAuth | src/google-handler.ts | オフラインアクセスを伴う認証コード、ブラウザーセッションに紐付けたワンタイムの state、二重送信 CSRF、検証済みメールアドレスに対する許可リスト |
| 🤖 エージェント | src/index.ts | MCP セッションごとに 1 つの Durable Object を作成し、セッションを開いたアカウントに紐付けます。トークン更新の単一実行制御と、スロットリングされたファンアウトを行います |
| ✉️ メール | src/gmail.ts | RFC 822 の構築、MIME ツリーの走査、文字セットのデコード、返信と転送の作成 |
使用技術
- TypeScript と Cloudflare Workers — Durable Objects が MCP セッションを 1 つずつ保持し、KV が OAuth グラントを保持します
- Hono — OAuth エンドポイント、Google コールバック、
/のセットアップページのルーティング @cloudflare/workers-oauth-provider— MCP クライアントが登録する OAuth 2.1 サーバーagents— Durable Objects 上で MCP トランスポートを提供するMcpAgent@modelcontextprotocol/sdkと Zod — ツール定義と引数の検証- Bun、Biome、Wrangler — インストール、テスト、Lint、デプロイ
Gmail は REST API に対して通常の fetch を使って呼び出します。公式の googleapis SDK は Node を前提としており、Worker に含めるには大きすぎるため、メッセージの構築、MIME の解析、トークンの更新は src/gmail.ts と src/utils.ts で行います。
エンドポイント
| パス | 用途 |
|---|---|
/mcp | MCP エンドポイント |
/mcp/<label> | 同じ URL を共有するサーバーを拒否するクライアント向けに、任意の単一セグメントのラベルで同じサーバーを公開します |
/ | セットアップガイド |
/authorize · /token · /register · /callback | OAuth の処理 |
サインインできるユーザー
ALLOWED_EMAILS でサインインできるユーザーを決定します。Google が検証済みとして報告するアドレスと照合します。これは同意後、グラントが作成される前に行われます。
| 値 | アクセスできるユーザー |
|---|---|
| (空) | 誰もアクセスできません |
[email protected], [email protected] | それらのアカウント |
*@company.com | そのドメインに属する全員 |
* | 検証済みの Google アカウントすべて |
各グラントからアクセスできるのは、そのグラントの認証に使用したメールボックスだけです。そのため、このリストを広げても、すでに接続済みのメールボックスへのアクセス範囲は広がりません。* を設定すると、見知らぬ人があなたのデプロイと Google クライアントの割り当て量を使って、自分のメールを操作できるようになります。
制限
共有デプロイの使い尽くしを防ぐ上限が2つあり、どちらも wrangler.jsonc で設定します。
| 設定 | 場所 | デフォルト | 制限する内容 |
|---|---|---|---|
MAX_ACCOUNTS | vars | 25 | サインインを完了できるGoogleアカウントの概算数です。上限に達しても、すでに接続済みのアカウントは引き続き利用できますが、新しいアカウントは拒否されます。同時に届いたサインインは、いずれも記録される前に件数を読み取るため、合計がこの数を少し超えることがあります。Googleは未確認アプリのユーザー数を100人に制限しているため、それを下回る余裕を残してください。 |
RATE_LIMITER.simple.limit | unsafe.bindings | 60秒あたり120 | その時間枠内に1つのアカウントが行えるGmail呼び出し数です。すべてのセッションを通じた合計です。Cloudflareはこの数をロケーションごとに管理するため、アカウントが2つのリージョンから接続すると、それぞれでおよそこの数だけ呼び出せます。広範囲の読み取りでは複数回分を消費します。たとえば、search_messages が50件を返す場合、51回の呼び出しになります。 |
REGISTER_LIMITER.simple.limit | unsafe.bindings | 60秒あたり10 | その時間枠内に1つのアドレスから行えるクライアント登録数です。クライアントは一度だけ登録し、割り当てられたIDを保持するため、通常の利用でこの上限に近づくことはありません。この上限があるのは、登録に認証情報が不要で、登録のたびにKVへ書き込みが行われるためです。 |
WorkersのFreeプランでは、1回の呼び出しにつきアウトバウンドリクエストが50件までという上限も適用されます。広範囲の読み取りではメッセージごとに1件を消費するため、このプランでは search_messages と list_drafts の maxResults を45以下にしてください。それを超えると、余分な分は結果ではなくメッセージごとのエラーとして返されます。有料プランでは1000件まで許可されます。
いずれかの上限を引き上げる場合は、再デプロイしてください。Cloudflareのレートリミッターはビルド時にバインディングから上限を読み取るため、変更できるのは各設定の simple.limit だけです。単一ユーザーでデプロイする場合は、どちらもそのままにしてかまいません。通常のアシスタント利用が上限を大きく下回るためです。
セキュリティ
セルフホストにすると信頼に関する問題は解消されず、移るだけです。ここでは、すべてがどこに保存されるかを説明します。
- トークンはお客様の手元にあります。 リフレッシュトークンは、お客様のKVネームスペース内のOAuthグラントに暗号化して保存されます。セッションのDurable Objectは1時間有効なアクセストークンを保持し、MCPエージェントフレームワークはオブジェクトが存続する間、リフレッシュトークンを含むグラントのコピーをそこに保持します。どちらのストアもお客様自身のCloudflareアカウントにあり、保存時に暗号化されます。メールは保存されず、通過するだけです。
- 1つのセッションにつき1つのメールボックスです。 MCPセッションは、そのセッションを開いたアカウントに紐づけられるため、借用したセッションIDを介して、あるメールボックスのグラントから別のメールボックスを操作することはできません。
- スコープは最小限です。
gmail.modifyは読み取り、送信、ラベル、ゴミ箱への移動を許可します。完全な削除とgmail.settings.*のすべては対象外であり、自動転送ルールやフィルターを使った情報流出といった、よくあるメールボックスのバックドアは、盗まれたグラントであっても操作できません。これに加えて読み取り専用スコープのuserinfo.emailとuserinfo.profileもリクエストします。許可リストとセッションの紐付けがサインインしたアカウントを把握するために使われ、メールにはアクセスしません。 - ヘッダーを紛れ込ませることはできません。 すべての送信ヘッダー値について、CR、LF、NULが含まれていないか検査し、含まれていれば拒否します。そのため、引数が自身のフィールドを抜け出してヘッダーを追加することはできません。たとえば、件名行に
Bccを紛れ込ませることはできません。メディアタイプは検証され、引用された履歴はHTMLエスケープされます。ただし、引数そのものは検査しません。bccは実際のパラメーターであるため、メッセージ本文に隠された指示に従ってモデルが動作した場合、値が入力される可能性はあります。それを確認するのは、引き続きクライアントの承認プロンプトです。 - アクセスを取り消せます。
ALLOWED_EMAILSを絞り込むと、新しいサインインを停止できます。1つのアカウントのアクセスは、myaccount.google.com/connections で取り消せます。Googleクライアントシークレットをローテーションすると、すべてのグラントが一度に無効になります。
Workerはリクエストを処理する間、メモリ上でメールを復号します。ホスト型の中継サービスであれば、これは避けられません。特定のメールボックスでそれが許容できない場合は、そのメールボックス用にローカルのMCPサーバーを実行してください。
テスト方法
260 件のユニットテストで、メッセージの構築(MIME のネスト、RFC 2047 の折り返し、RFC 2231 のファイル名、CR/LF の拒否、base64 の分割)、各種文字セットでの本文抽出、返信と転送の作成、Google のトークンフロー、サインインの許可リスト、サインインのブラウザー側を保護する CSRF と状態バインディングのチェック、および Gmail のスタンドインを使用した各ツール(セッションの所有権、宛先の作成、添付ファイルの選択、一部失敗時に読み取りで返される内容)を網羅しています。
さらに、すべてのツールを実際の Gmail アカウントで実行し、別のアカウントで受信内容を確認しました。
| 領域 | 結果 |
|---|---|
| エンコード | 日本語の件名がエンコードされたワードをまたいで折り返され、絵文字、ZWJ シーケンス、右から左に書くアラビア語、結合文字、まれな CJK 文字が変更なく往復しました |
| 添付ファイル | 請求書.csv という名前の CSV を送信し、受信して再ダウンロードしたところ、バイト単位で一致しました。インラインの cid: 画像は受信者側で表示されました。ダウンロードリンク経由で取得した 2 MB の zip は、宣言されたサイズで届き、開くことができました |
| スレッド | reply_all は送信者を宛先に指定し、第三者の Cc を維持し、自分のアドレスを除外して、元のメッセージを同じスレッド内で引用しました |
| 2 つのアカウント | 両方を同時に 1 つのデプロイに接続しました。一方のアカウントのメッセージ ID は、もう一方では 404 を返しました |
| 整理 | 入れ子になった CJK ラベルを作成、名前変更、一括適用、削除しました。スレッドとメッセージの両方のゴミ箱への移動を取り消せました |
| 規模 | Gmail の演算子とページネーションを使用して 15,000 件のメールボックスを検索し、レート制限に達しませんでした |
開発
bun run dev # wrangler dev on :8788
bun run check # biome + tsc
bun test # 260 unit tests
bun run assets # regenerate the light and dark diagrams
bun run deploy
質問とバグ
issue を作成してください。
ライセンス
Copyright © 2026 mkpoli. MIT License の下で公開されています。
src/workers-oauth-utils.ts は cloudflare/ai の remote-mcp-github-oauth demo を元にしており、Copyright © 2025 Cloudflare, Inc.、MIT License の下で使用されています。THIRD-PARTY.md を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。