Skip to main content
Glama
README.md
# qs-gmail

**複数の Gmail アカウントを 1 つのサーバーでまとめて扱う MCP サーバー。**
アカウントを「識別子」で引けるので、AI エージェントから業務用メールボックスを横断的に検索・操作できる。

> Model Context Protocol (MCP) server that manages multiple Gmail accounts under a single stdio server. Local, zero API cost.

実際のインサイドセールス業務で運用しているツール。展示会後の追客メール対応など、個人メールとは別の業務用アカウントをエージェントから扱うために作った。

## なぜ作ったか

既製の Gmail コネクタは基本「1 ユーザー = 1 アカウント」前提。業務では用途別の共有メールボックスを複数扱いたいが、それを 1 つのエージェントから区別して操作する手段がなかった。
→ **複数アカウントを 1 DB・1 サーバーで識別子管理する Gmail MCP** を実装した。

## 設計のポイント

- **マルチアカウントを識別子で抽象化** — `exhibition` のような識別子でアカウントを引く。トークンは `node:sqlite` の 1 DB に集約し、アカウント追加は CLI 一発
- **loopback OAuth で認証** — デスクトップアプリ型 OAuth クライアントを使い、ブラウザ承認 → ループバックでトークンを受け取って永続化。リフレッシュ時は自動で再保存
- **認証情報は env もファイルも両対応** — `QS_GMAIL_CLIENT_ID/SECRET` があれば優先、無ければ GCloud からダウンロードした `client_secret` JSON を読む。鍵はリポジトリ外に置く設計
- **副作用ツールを明示分離** — 検索・読取は安全側、送信やアーカイブなど副作用のあるものは別ツールとして切り出し、誤爆しにくくしている

## MCP ツール

| ツール | 役割 |
|---|---|
| `list_accounts` | 登録済みアカウント一覧 |
| `search` | 検索(query / 差出人ドメイン / 期間 / 未読のみ / 件数) |
| `read_message` | 本文取得 |
| `list_labels` | ラベル一覧 |
| `archive` | アーカイブ(INBOX 除去) |
| `mark_read` | 既読 / 未読 |
| `send_message` | 送信(副作用・要確認) |
| `create_draft` | 下書き作成(返信スレッド連結対応・署名は手動付与) |

`send_message` / `create_draft` は本文と添付に加えてインライン画像を扱える。

- `html: true` … 本文を `text/html` で送る(リンクをクリック可能にする)
- `attachments: ["/abs/path.pdf", …]` … `multipart/mixed` で添付(拡張子から MIME 判定・日本語ファイル名可)
- `inlineImages: [{ path: "/abs/logo.png", cid: "qslogo" }]` … `multipart/related` で本文に埋め込む。本文側は `<img src="cid:qslogo">` と書く。`cid` 省略時は拡張子を除いたファイル名。添付と併用すると `mixed[ related[ html, 画像 ], 添付 ]` の入れ子になる

| `list_drafts` | 下書き一覧(`draftId` +宛先 / 件名 / snippet) |
| `delete_draft` | 下書きを完全削除(副作用・要確認) |
| `remove_account` | トークン削除 |

## スタック

Node.js (ESM) / `@modelcontextprotocol/sdk` / `googleapis` / `node:sqlite`

## セットアップ

```bash
npm install
# GCloud でデスクトップアプリ型 OAuth クライアントを作成し、
# client_secret JSON を ~/.gmail-mcp-credentials.json に置く
#   (または QS_GMAIL_CLIENT_ID / QS_GMAIL_CLIENT_SECRET を設定。.env.example 参照)
node authorize.js <識別子>   # 例: node authorize.js work
# → ブラウザで承認するとトークンが DB に保存される
```

MCP ホスト(Claude Code 等)には stdio サーバーとして登録する。

---

<sub>個人で開発した MCP サーバー群の 1 つ。</sub>