Multi-Account Gmail について
Multi-Account Gmailは、複数のGmail受信トレイを管理する人向けのMCPサーバーで、メールの読み取り、検索、下書き作成、ラベル管理に対応します。1つのOAuthクライアントで複数アカウントを認証し、トークンをローカルのSQLiteに保存します。メールは送信せず、下書きとして作成します。
主な機能
- 011つのクライアントで複数アカウントを認証
- 02アカウント別の結果付きで横断検索
- 03メール、スレッド、添付ファイルの読み取り
- 04下書きの作成と一覧表示
- 05ラベル、フィルター、メールの一括操作
活用シーン
- 01複数の受信トレイから請求書メールを検索
- 02スレッドの確認と添付ファイルの取得
- 03確認後に手動送信する返信下書きの作成
- 04クエリに一致するメールの一括アーカイブ、ラベル付け、ゴミ箱移動
MCP 対応
stdio MCPサーバーを通じて、クライアントにGmail操作ツールを提供します。アカウントは専用CLIで認証し、トークンはローカルのSQLiteファイルに保存します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx multi-account-gmail-mcpGMAIL_MCP_CLIENT_SECRETシークレットPath to the Google OAuth "Desktop app" client-secret JSON. Defaults to ~/.gmail-mcp/client_secret.json.GMAIL_MCP_DBPath to the SQLite token store holding per-account refresh tokens. Defaults to ~/.gmail-mcp/tokens.db.GMAIL_MCP_OAUTH_PORTシークレットLocalhost port for the OAuth redirect during account authorization. Defaults to 8765.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
gmail-mcp
1 つの接続から、所有する すべての Gmail アカウントを読み取るMCP サーバーです。
ネイティブコネクターを含む多くの Gmail 連携では、OAuth の許可ごとに 1 つのアカウントが紐付けられます。2 つ目の受信トレイを接続すると、最初の接続が解除されます。
gmail-mcp では、任意の数のアカウントを同時に認証できます。1 つの Google Cloud クライアントですべてのアカウントを認証し、各アカウントをローカルの SQLite ファイルの 1 行として保存します。各ツールは account 引数を使って、適切なメールボックスにアクセスします。
search_all_accounts は 1 回のクエリですべてのアカウントを検索します。
Python 3.12+ · MIT · stdio MCP サーバー + 認証 CLI · ローカル SQLite トークンストア
完全に自分で管理できるように構築されています。stdio 経由でプロセス内実行し、確認、コピー、削除ができる 1 つの SQLite ファイルにトークンを保存します。通信先は Google と MCP クライアントのみで、シークレットはハードコードされていません。
メールの読み取り、検索、下書き作成、ラベル付けができます。送信はしません。create_draft は、ユーザー自身が送信できるように下書きを残します。これは意図的なデフォルトです(理由はセキュリティモデルを参照してください)。ただし、厳格な方針ではありません。自動送信が必要なら、少し追加するか、別のサーバーを利用してください。
目次
- 30 秒でわかる概要
- 設計上のポイント
- ツール
- アーキテクチャ
- ID と認証モデル
- セキュリティモデル
- インストール
- クイックスタート
- 設定
- MCP クライアントへの登録
- 開発
- プロジェクト構成
- ライセンス
30 秒でわかる概要
CLI で N 個のアカウントを一度だけ認証します。その後、すべてのツールで account を指定し、search_all_accounts を使うとすべてのアカウントを一度に検索できます。
search_all_accounts(query="invoice newer_than:30d")
── [email protected] ───────────────────────────────
from: [email protected] subject: Invoice #4821 (id 18f...)
── [email protected] ─────────────────────────────────
from: [email protected] subject: March invoice (id 19a...)
1 回のクエリですべての受信トレイを検索でき、各結果にはアカウントとメッセージ ID が付与されます。そのため、エージェントは次に read_message(account, id) や create_draft(...) を連続して呼び出せます。
設計上のポイント
1 つの OAuth クライアントで、多数の受信トレイに対応。 1 つの Google Cloud プロジェクトと 1 つの client_secret.json で、すべてのアカウントを認証できます。10 個目の受信トレイを追加する方法も、最初のアカウントと同じ 1 コマンドの手順です。
シンプルなストレージ。 トークンは ~/.gmail-mcp/ の 1 つの SQLite ファイルに保存されます。デーモンも、キーリングへの依存も、クラウドもありません。ファイルをコピーしてバックアップし、行を削除してアカウントのアクセスを取り消し、任意の SQLite ツールで内容を確認できます。
最小権限。 粒度の細かい 4 つのスコープ、gmail.readonly、gmail.compose、gmail.modify、gmail.settings.basic を使用し、メールボックス全体へのアクセスを許可する https://mail.google.com/ は使いません。メールの読み取り、下書き作成、ラベル付け、フィルターの管理ができます。メールを送信することはなく、作成したフィルターがアカウント外にメールを転送することもありません。
ヘッドレス環境に対応。 サーバーにブラウザーがない場合を想定した認証フローです。同意 URL を表示して固定ポートにバインドし、SSH でリダイレクトを転送します。デスクトップでも問題なく使えます。
ツール
list_accounts と search_all_accounts を除くすべてのツールには account
(メールアドレス)が必要です。不明なアカウントを指定すると、認証済みのアカウント一覧を含むエラーが返されます。
| ツール | 引数 | 戻り値 |
|---|---|---|
list_accounts | — | 認証済みアカウントと最終使用時刻。有効な account 値を確認できます。 |
search_messages | account、query、max_results=20 | ID 付きのメッセージ概要(Gmail の検索構文)。 |
read_message | account、message_id、format="full"、max_body_chars? | デコード済みヘッダー、プレーンテキスト本文(必要に応じて HTML を除去)、添付ファイルのメタデータ。本文はデフォルトで上限が設定されています。全文を取得するには max_body_chars=0 を指定します。 |
read_thread | account、thread_id、max_body_chars? | スレッド内のすべてのメッセージを順番に返します。各本文はデフォルトで上限が設定されています。全文を取得するには max_body_chars=0 を指定します。 |
download_attachments | account、message_id、index? | メッセージの添付ファイルをディスクに保存し、絶対パスを返します。read_message に表示される #N で指定します。すべてを対象にする場合は index を省略します。ダウンロード先は固定で、保存先を指定する引数はありません。危険なファイル形式、および迷惑メールのラベルが付いたメッセージの添付ファイルは拒否されます。 |
search_all_accounts | query、max_results_per_account=10 | すべてのアカウントを対象に一括検索し、各結果にアカウントを表示します。 |
create_draft | account、body、to?、subject?、cc?、bcc?、html=false、reply_to_message_id?、reply_all=false、from_addr? | 下書き(送信されません)。下書き ID を返します。reply_to_message_id を指定すると、そのメッセージのスレッド内に返信の下書きが作成され、宛先、件名、In-Reply-To、References、スレッド ID がそのメッセージから引き継がれます。また、to と subject は任意の上書き値になります。指定しない場合は、to と subject が必須です。from_addr には、認証済みの送信元エイリアスの From ヘッダーを設定します。デフォルトはアカウントのアドレスです。 |
list_drafts | account、max_results=20 | アカウント内の下書き ID。 |
list_labels | account | アカウントのラベル(名前と ID)。 |
modify_labels | account、選択対象(message_id | message_ids | query)、add?、remove? | 選択対象(単一 ID、ID のリスト、またはクエリに一致するすべてのメッセージ)のラベルを追加/削除します。1 回の呼び出しにつき 1000 件をバッチ処理します。汎用の変更ツールです。アーカイブ = INBOX を削除、既読にする = UNREAD を削除、スターを付ける = STARRED を追加。 |
trash | account、選択対象(message_id | message_ids | query) | 選択対象をゴミ箱に移動します(30 日間は復元可能。完全削除ではありません)。選択対象が空の場合は拒否されます。 |
bulk_action | account、action、選択対象(message_id | message_ids | query) | modify_labels の使いやすい動詞レイヤーです。action ∈ archive/unarchive/mark_read/mark_unread/star/unstar/spam/unspam/trash/untrash。1 回の呼び出しにつき 1000 件をバッチ処理します。選択対象が空の場合は拒否されます。 |
read_messages | account、message_ids | query、max_results=25 | 1 回の呼び出しで複数のメッセージの全内容を一括で読み取ります(N 回の read_message 呼び出しの代わりに使用できます)。 |
count_messages | query、account?、all_accounts=false | 内容を取得せずに一致件数を数えます。一括操作の影響範囲を事前に確認できます。all_accounts を指定すると、アカウントごとの内訳と合計を返します。 |
list_filters | account | アカウントのフィルター(ID、条件、アクション。ラベル ID は名前で表示されます)。 |
create_filter | account、from_address/to_address/subject/query/has_attachment のいずれかと、アクション(archive/mark_read/delete/star または add_labels/remove_labels) | 受信メールに適用されるサーバー側ルールです。アカウント外への転送はできません。 |
delete_filter | account、filter_id | ID でフィルターを削除します(すでに処理済みのメールには影響しません)。 |
アーキテクチャ
flowchart TD
subgraph client[Your machine]
Agent[MCP client / agent]
CLI[gmail-mcp-auth CLI]
Server[gmail-mcp stdio server]
Store[("SQLite<br/>~/.gmail-mcp/tokens.db")]
Secret["client_secret.json<br/>one OAuth client"]
end
Google[Google OAuth + Gmail API]
CLI -->|"loopback OAuth, once per account"| Google
CLI -->|"store refresh token"| Store
Secret -.-> CLI
Agent -->|"tool call (account=...)"| Server
Server -->|"look up + refresh creds"| Store
Secret -.-> Server
Server -->|"read / draft / label"| Google
Server --> Agent
アカウントごとの認証は、CLI を通じて一度だけ行います(ブラウザーが必要です)。 その後、stdio サーバーは SQLite からトークンを直接読み取り、必要に応じてアクセストークンを更新し、更新したトークンを保存します。このセクションの残りでは、「この仕組みがこのように動作する理由」を詳しく説明します。
ID と認証モデル
gmail-mcp が Gmail に認証し、1 つの OAuth クライアントで複数のアカウントを扱い、トークンを継続的に更新し、ヘッドレスサーバーでアカウントを認証する方法について説明します。すぐに使い始めたい場合は、クイックスタートに進んでください。
OAuth モデル
gmail-mcp は、google-auth-oauthlib の InstalledAppFlow ヘルパーを使い、Google の 「デスクトップアプリ」 OAuth クライアント(OAuth 2.0 用語では インストール型アプリケーション)で認証します。
インストール型アプリ/デスクトップクライアントを使用する理由。 インストール型アプリはエンドユーザーが管理するマシンで動作するため、OAuth では パブリッククライアント として扱われます。つまり、ダウンロードした client_secret.json 内の client_secret は、機密情報として扱われることを前提としていません。これはローカルの CLI/デスクトップツールに適した信頼モデルです。秘密情報を真に秘密に保てるサーバーサイドのコンポーネントがなく、セキュリティは秘密情報の機密性ではなく、ユーザーがリダイレクト先(ループバックアドレス)を管理していることに依存します。Google がコマンドラインツールやデスクトップツールに推奨しているクライアントタイプです。
ループバックリダイレクトフロー。 ブラウザーで同意を承認すると、Google は認証コードを http://localhost:<port>/ にリダイレクトします。ここで、InstalledAppFlow.run_local_server が起動する一時的な小さな HTTP サーバーがコードを受け取ります。gmail-mcp はこれを固定ポート(デフォルトは 8765。GMAIL_MCP_OAUTH_PORT で変更可能)に設定し、open_browser=False で実行するため、ブラウザーのないマシンでも動作します。ヘッドレス認証の方法を参照してください。
要求されるスコープ。 4 つの詳細なスコープを要求します。メールボックス全体を対象とする https://mail.google.com/ は要求しません。
| スコープ | 付与される権限 |
|---|---|
gmail.readonly | メールとメタデータの読み取り:メッセージ/スレッドの検索、本文の読み取り、ラベルと下書きの一覧表示。読み取り専用のため、変更はできません。 |
gmail.compose | 下書きの作成、更新、管理。create_draft のみで使用されます。 |
gmail.modify | メッセージへのラベルの追加/削除。modify_labels で使用されます。 |
gmail.settings.basic | フィルターの一覧表示、作成、削除。list_filters/create_filter/delete_filter で使用されます。転送先アドレスの変更権限は 付与されません(その権限には要求していない gmail.settings.sharing が必要です)。 |
gmail.send は要求されません。これがないと、認証情報にはメールを送信する Gmail API の手段がありません。下書きのみを扱う動作は、ツールを省略しただけではなく、付与された権限によるものです。同様に gmail.settings.sharing も要求されないため、フィルターでメールを別のアドレスに転送することはできません。スコープ一覧は src/gmail_mcp/config.py の SCOPES にまとめられています。
既存のインストールにフィルタースコープを追加する場合:
SCOPESを拡張しても、すでに認証済みのアカウントに遡って権限が付与されることはありません。各アカウントでgmail-mcp-auth addを再実行し、新しいスコープへの同意が必要です。同意するまでは、フィルターツールは403 insufficient scopeエラーを返します。
マルチアカウントモデル
- 1 つの OAuth クライアントで複数のアカウントを認証します。 Google Cloud プロジェクトを 1 つ作成し、「デスクトップアプリ」の OAuth クライアントを 1 つ用意します。その後、追加する Gmail アカウントごとに、追加するアカウントにログインして同意フローを実行します。1 つの
client_secret.jsonで任意の数のアカウントを認証できます。 - 各アカウントは SQLite の 1 行として保存されます。 認証済みの各アカウントは
accountsテーブル(~/.gmail-mcp/tokens.db。GMAIL_MCP_DBで変更可能)に保存され、メールアドレスをキーとして管理されます。この行には、長期間有効なリフレッシュトークン、最新のアクセストークンのデータ、付与されたスコープ、タイムスタンプが含まれます。 - ツール呼び出しは
accountパラメーターで振り分けられます。list_accountsとsearch_all_accountsを除くすべてのツールでaccountを指定します。サーバーはそのメールアドレスを検索し、そのアカウントの認証情報を作成して、該当アカウントとして Gmail API を呼び出します。不明なアカウントが指定された場合は、認証済みアカウントの一覧を示す明確なエラーが返されます。search_all_accountsは保存されているすべての行を順に処理します。
flowchart LR
Client[MCP client / agent] -->|"[email protected]"| Server[gmail_mcp.server]
Server --> Store[("accounts table<br/>keyed by email")]
Store -->|"row [email protected]"| CredsA[Credentials a]
Store -->|"row [email protected]"| CredsB[Credentials b]
CredsA --> InboxA["Gmail: [email protected]"]
CredsB --> InboxB["Gmail: [email protected]"]
Secret["client_secret.json<br/>one OAuth client"] -.->|"shared by all rows"| CredsA
Secret -.-> CredsB
トークンのライフサイクル
初回の付与(アカウントごとに一度、CLI 経由)。OAuth フローにはブラウザーが必要です。MCP ツールではブラウザーをスムーズに操作できないため、認証はツールではなく gmail-mcp-auth CLI で行います。
sequenceDiagram
actor User
participant CLI as gmail-mcp-auth add
participant Browser
participant Google as Google OAuth + Gmail API
participant Store as SQLite token store
User->>CLI: run `gmail-mcp-auth add`
CLI->>CLI: load client_secret.json,<br/>start loopback server on :8765
CLI-->>User: print consent URL (open_browser=False)
User->>Browser: open URL, sign into target account
Browser->>Google: consent + approve scopes
Google-->>Browser: redirect with authorization code
Browser->>CLI: GET http://localhost:8765/?code=...
CLI->>Google: exchange code for tokens
Google-->>CLI: access token + refresh token
CLI->>Google: users.getProfile (discover email)
Google-->>CLI: emailAddress
CLI->>Store: upsert(email, refresh_token, token, scopes)
CLI-->>User: "Authorized and stored: [email protected]"
- CLI は
prompt="consent"を渡して、必ずリフレッシュトークンを発行させます。Google は新たに同意した場合にのみリフレッシュトークンを返します。リフレッシュトークンが返されなかった場合、CLI は明確なエラーを表示します(https://myaccount.google.com/permissions でアプリの許可を取り消し、再実行してください)。 - アカウントのメールアドレスは入力するのではなく、取得されます。トークン交換後、CLI は
users.getProfileを呼び出し、返されたアドレスをキーとして保存済みの行を特定します。
リクエストごとの更新(ツール呼び出しのたびに実行)。アクセストークンの有効期間は短く(約1時間)です。呼び出しのたびにサーバーは対象アカウントの認証情報を再構築し、google-auth に必要に応じて更新させ、更新後のデータを保存し直します。
sequenceDiagram
participant Client as MCP client / agent
participant Server as gmail_mcp.server
participant Store as SQLite token store
participant Google as Google OAuth + Gmail API
Client->>Server: tool call ([email protected])
Server->>Store: get(account) → refresh_token + last token
Server->>Server: build Credentials
alt access token still valid
Server->>Google: Gmail API request
else access token expired
Server->>Google: refresh using refresh_token
Google-->>Server: new access token
Server->>Store: update_token(account, new blob)
Server->>Google: Gmail API request
end
Google-->>Server: response
Server->>Store: touch(account) → last_used_at
Server-->>Client: result (email content wrapped as untrusted)
更新に失敗した場合(許可の取り消し、リフレッシュトークンの期限切れなど)、サーバーはクラッシュするのではなく、「gmail-mcp-auth add を再実行してください」というメッセージとともに GmailAuthError を発生させます。
テストモードと公開済みアプリ — 7日間の落とし穴。 よくある「1週間後に動かなくなった」という問題です。
- OAuth 同意画面がテストモードの場合、認証できるのは登録済みのテストユーザーのみです。また、未確認アプリに発行されたリフレッシュトークンは7日後に期限切れになるため、毎週
gmail-mcp-auth addを再実行する必要があります。 - アプリを公開(同意画面 → アプリを公開)すると、リフレッシュトークンの有効期間が長くなります。Google から「未確認」と警告されますが、配布しないセルフホストの個人用ツールであれば想定内で、問題ありません。長期間使用するには、アプリを公開してください。具体的な手順は SETUP.md をご覧ください。
ヘッドレス認証の手順
一般的な利用先はヘッドレスサーバー(デスクトップもブラウザーもない環境)ですが、OAuth の同意にはブラウザーが必要です。このフローでは、次のように連携します。
-
open_browser=False— CLI はブラウザーを起動せず、同意用 URL を表示します。追加するアカウントにログインした状態で、自分のノートパソコンから URL を開きます。 -
固定のループバックポート — 承認後、Google は
http://localhost:<port>/にリダイレクトします。この「localhost」は CLI が待ち受けるサーバー側のループバックアドレスです。ポートは固定(デフォルトは8765、GMAIL_MCP_OAUTH_PORT)なので、確実にポート転送できます。 -
SSH ポート転送 — ノートパソコンのブラウザーをサーバーのループバックアドレスに接続します。
ssh -L 8765:localhost:8765 you@your-server
リダイレクトがノートパソコンの localhost:8765 に届くと、SSH がサーバーへトンネルし、そこで CLI がコードを受け取ってトークン交換を完了します。
セキュリティモデル
受信トレイには他の人が書いたテキストがあふれているため、プロンプトインジェクションが発生しやすい場所です。標準的な捉え方は致命的な三要素です。エージェントが次の3つすべてを備えている場合、インジェクションは危険になります。
flowchart LR
A[Private data<br/>your mailboxes] --- C{Injection<br/>risk}
B[Untrusted content<br/>any email you receive] --- C
D[Egress channel<br/>a way to send data out] --- C
C -.->|drafts-only removes the obvious one| D
style D stroke-dasharray: 5 5
メールリーダーは、その性質上、最初の2つを備えています。3つ目のリスクを低く抑えるために、いくつかの選択をしています。
-
送信ではなく下書き。
create_draftが送信操作の上限です。送信ツールもgmail.sendスコープもありません。下書きはあなたが送信するまで下書きフォルダーに残るため、メールに埋め込まれた指示によって、エージェントがあなたのデータをどこかへ送ることはできません。妥当なデフォルト設定ですが、送信したい場合は簡単に変更できます。 -
メールの内容には信頼できないデータとして印を付けます。 ツールが返すメッセージ本文は、単一のヘルパー(
gmail.pyのwrap_untrusted)によって⟦UNTRUSTED EMAIL CONTENT⟧区切りで囲まれます。ツールの連鎖が引き続き機能するよう、IDは区切りの外側に保持されます。また、読み取りツールの説明にも、内容は指示ではなくデータであることが記されています。複数メッセージを含むレスポンス(検索結果、スレッド、複数アカウントをまたぐ一括確認)では、区切りをメッセージごとではなく、内容全体を囲むように1回だけ出力し、各本文は区切りの外側にある信頼できる#NIDマニフェストに対応付けます。これにより、区切りに使うトークンのオーバーヘッドを削減し、実際のIDを信頼できる領域にのみ保持できるため、攻撃者がエージェントに権威ある情報として扱わせる場所へ偽造IDを紛れ込ませることも防ぎます。 -
添付ファイルの保存先は1か所に固定され、一部のファイルは保存されません。
download_attachmentsが書き込むのは~/.gmail-mcp/attachments/<message_id>/(GMAIL_MCP_ATTACHMENT_DIR) の下だけです。保存先を指定する引数は意図的に用意していません。そのような引数は、メールに埋め込まれた指示によって~/.zshrcなどを狙える、任意のファイルへの書き込み機能になってしまうためです。ファイル名は攻撃者が指定するため、無害なASCIIのベース名に変換します(パス区切り文字を削除し、先頭のドットを除去し、双方向テキストの上書き制御文字を削除し、長さを制限し、インデックスを先頭に付加します)。さらに、書き込み前に解決済みパスがルートディレクトリ内にあることを再確認します。ファイルは所有者のみがアクセスできる権限で、事前に仕込まれたシンボリックリンクによる転送を防ぐO_NOFOLLOWを指定して書き込まれます。バイト列を取得する前にスクリーニングを行います。Gmailが転送中にブロックするすべてのファイル形式(Gmailが転送中にブロックするファイル形式)(
.exe、.jar、.js、.vbs、.iso、.pyなど約50種類)、マクロ有効のOffice文書、実行可能なMIMEタイプ、そしてGmailがSPAMとラベル付けしたメッセージの添付ファイルは、すべて拒否されます。最後の拡張子だけでなくファイル名に含まれるすべてのドット付き拡張子を確認するため、invoice.pdf.exeも検出されます。アーカイブは保存しますが、その中身を確認する機能はないため、警告を付けます。これはファイル形式のスクリーニングであり、ウイルススキャンではありません。 Gmailはサーバー側で添付ファイルをスキャンしますが、その判定結果をAPI経由で公開していません。メッセージにも添付ファイルのリソースにもマルウェアのフィールドはなく、
attachments.getはGmailのウェブUIではダウンロードを拒否されるバイト列も返します。ここで「問題なし」と判定されても、それは「明らかな危険物ではない」という意味であり、「スキャン済みで安全」という意味では決してありません。保存したファイルの内容は、引き続き信頼できない第三者のデータとして扱われます。
既知の制限事項。 これは、このサーバーの機能範囲だけに適用されます。同じエージェントのセッションに、オープンインターネットへアクセスできるツール(ウェブ取得、HTTP)もある場合、それは別の外部送信経路であり、gmail-mcp では対処できません。任意の外部送信が可能なツールと組み合わせると、別の場所で三要素が再びそろってしまいます。同じセッションで共有するツールは慎重に選んでください。
補足が2点あります。監査ログは実装していません(意図的に対象範囲外としています)。また、秘密情報はハードコードされていません。client_id/client_secret はダウンロードした client_secret.json から取得し、トークンはローカルのSQLiteストアにのみ保存されます。
インストール
Python 3.12以降が必要です。PyPIの配布パッケージ名は multi-account-gmail-mcp です(gmail-mcp という名前はすでに使用されています)。インストールすると、gmail-mcp コマンドと gmail-mcp-auth コマンドが利用できるようになります。
# From PyPI
pip install multi-account-gmail-mcp
# or, to get the commands on PATH globally:
uv tool install multi-account-gmail-mcp # or: pipx install multi-account-gmail-mcp
# or run without installing:
uvx multi-account-gmail-mcp
ソースからインストールする場合(開発向け):
git clone https://github.com/cunicopia-dev/gmail-mcp.git
cd gmail-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e . # add ".[dev]" for ruff + pytest
これにより、2つのコンソールスクリプトがインストールされます。gmail-mcp(stdio サーバー)と gmail-mcp-auth(アカウント認証用CLI)です。
クイックスタート
Google の「デスクトップアプリ」OAuth クライアント(client_secret.json)と、アカウントごとの認証が必要です。Google Cloud プロジェクトの作成、Gmail API の有効化、同意画面の公開、ヘッドレス環境での SSH 転送手順を含む、クリックごとの詳しい手順は docs/SETUP.md に記載されています。概要は次のとおりです。
# 1. Drop your downloaded OAuth client here:
mkdir -p ~/.gmail-mcp && mv ~/Downloads/client_secret_*.json ~/.gmail-mcp/client_secret.json
# 2. Authorize an account (prints a URL to open in a browser; repeat per account).
# On a headless server, SSH in with -L 8765:localhost:8765 first.
gmail-mcp-auth add
# 3. Confirm what's authorized.
gmail-mcp-auth list
# 4. Point your MCP client at the `gmail-mcp` command (see below).
後からアカウントを削除するには、gmail-mcp-auth remove [email protected] を実行します。
設定
すべて省略可能です。~/.gmail-mcp/ 以下に適切なデフォルト値が設定されています。
| 変数 | デフォルト値 | 用途 |
|---|---|---|
GMAIL_MCP_DB | ~/.gmail-mcp/tokens.db | SQLite トークンストアのパスです。 |
GMAIL_MCP_CLIENT_SECRET | ~/.gmail-mcp/client_secret.json | ダウンロードした Google OAuth クライアントです。 |
GMAIL_MCP_OAUTH_PORT | 8765 | 認証フロー用の固定ループバックポートです(ヘッドレス環境では SSH 経由で転送します)。 |
GMAIL_MCP_ATTACHMENT_DIR | ~/.gmail-mcp/attachments | download_attachments のダウンロード先ルートです。ファイルはメッセージごとのサブディレクトリに保存されます。サーバーが書き込みを行うのはこの場所だけです。 |
GMAIL_MCP_MAX_ATTACHMENT_BYTES | 26214400 (25 MB) | 添付ファイルごとのサイズ上限です。Gmail 自体の上限は 25 MB なので、Gmail が配信するファイルが拒否されることはありません。0(または負の値)は無制限を意味します。 |
GMAIL_MCP_MAX_BODY_CHARS | 500 | read_message/read_thread のメッセージ本文に対するデフォルトの上限です。デフォルトで読み取りのコストを抑えられるよう、意図的に低く設定しています。0(または負の値)は無制限を意味し、呼び出しごとの max_body_chars 引数で上書きできます。 |
MCP クライアントへの登録
サーバーは stdio で通信します。クライアントの mcpServers 設定で、
gmail-mcp コマンドを指定します。
{
"mcpServers": {
"gmail": {
"command": "/path/to/gmail-mcp/.venv/bin/gmail-mcp"
}
}
}
gmail-mcp が PATH にある場合は、"command": "gmail-mcp" だけで十分です。必要に応じてパスを明示的に指定してください(一部のクライアントは ~ を展開しません)。
{
"mcpServers": {
"gmail": {
"command": "/path/to/gmail-mcp/.venv/bin/gmail-mcp",
"env": {
"GMAIL_MCP_DB": "/home/you/.gmail-mcp/tokens.db",
"GMAIL_MCP_CLIENT_SECRET": "/home/you/.gmail-mcp/client_secret.json"
}
}
}
}
開発
pip install -e ".[dev]"
ruff check .
pytest # 48 tests, no network — the Gmail client is mocked
テストでは、MIME の解析/デコード、ラベル名から ID への解決、信頼できないコンテンツのラッパー、出力のフォーマット、テンポラリ SQLite データベースを使ったトークンストアの CRUD など、純粋なレイヤーを対象にしています。
プロジェクト構成
src/gmail_mcp/
server.py MCP tool definitions + dispatch + per-account routing
gmail.py Gmail service build, token refresh/persist, MIME parse/format,
wrap_untrusted(), label resolution, MIME message build
store.py TokenStore — sqlite3 accounts table CRUD
auth.py gmail-mcp-auth CLI: add / list / remove (loopback OAuth)
config.py SCOPES + env-overridable paths
docs/
SETUP.md step-by-step Google Cloud + account authorization
tests/ store / gmail / server, Gmail client mocked
ライセンス
MIT — 詳細は LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。