GitHubのリリースノートは、開発者が開発者に向けて書くものです。「Fix all Dependabot alerts」「bump version」のような書き方では、ツールを使っているだけの利用者には何をすればいいのかが伝わりません。リリースのたびに、利用者向けにお知らせを書き直して送る作業が発生します。
GitHubの公式MCPサーバーとblastengineのMCPサーバーを1つのエージェントにつなぐと、この作業を会話で回せます。リリースノートと関連するプルリクエストを読ませて利用者向けの文面に直し、blastengineの一斉配信の下書きにします。人が内容を確かめてから確定する流れです。本記事ではこの構成をClaude Codeで組み、実際に1通送るところまで確認します。
題材には、blastengine MCPサーバー自身のリリース(v0.2.0〜v0.2.2)を使います。社内でblastengine MCPを配っている担当者が、営業やCSを含む利用者に更新をお願いする、という場面です。
※記事中の会社名と送信元メールアドレスは、掲載用に置き換えています。
blastengine MCPの導入手順は導入記事、各ツールの入出力は全15ツールの検証記事を参照してください。
全体構成
┌──────────────────────────────┐
│ Claude Code │
└───────┬──────────────┬───────┘
stdio │ │ stdio
(Docker) │ │
┌────────────────▼───┐ ┌───▼──────────────────┐
│ GitHub MCP │ │ blastengine MCP │
│ (読み取り専用) │ │ (一斉配信を有効化)│
└────────┬───────────┘ └───────────┬──────────┘
│ GitHub API │
┌────────▼───────────┐ ┌───────────▼──────────┐
│ GitHub │ │ blastengine │
└────────────────────┘ └──────────────────────┘
GitHub MCPサーバーは公式のDockerイメージ(ghcr.io/github/github-mcp-server)を使い、stdioで動かします。今回はリリースとプルリクエストを読むだけなので、読み取り専用で起動します。
準備1:GitHubのトークンを用意する
GitHub MCPサーバーは、環境変数GITHUB_PERSONAL_ACCESS_TOKENに渡したトークンでGitHub APIを呼びます。
お知らせを作るのに必要なのは、リリースとプルリクエストを読む権限だけです。普段使っているrepoスコープ付きのトークンを流用せず、対象のリポジトリだけを読めるfine-grained personal access tokenを発行して渡すのが安全です。
準備2:Claude Codeに2つのMCPを登録する
{
"mcpServers": {
"github": {
"type": "stdio",
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
"ghcr.io/github/github-mcp-server:latest",
"stdio", "--read-only", "--tools=list_releases,get_release_by_tag,pull_request_read"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
}
},
"blastengine": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/blastengine-mcp/dist/index.js"],
"env": {
"BLASTENGINE_LOGIN_ID": "${BLASTENGINE_LOGIN_ID}",
"BLASTENGINE_API_KEY": "${BLASTENGINE_API_KEY}",
"BLASTENGINE_ENABLE_SEND": "false",
"BLASTENGINE_ENABLE_BULK": "true",
"BLASTENGINE_ENABLE_CSV_IMPORT": "false"
}
}
}
}
GitHub側はイメージ名の後ろにstdioサブコマンドと起動オプションを並べます。--read-onlyで書き込み系のツールを外し、--toolsで公開するツールを3つに絞っています。
blastengine側は、kintoneの記事やスプレッドシートの記事とは逆に、一斉配信(BLASTENGINE_ENABLE_BULK)だけを有効にしています。お知らせは全員に同じ文面を送るので、宛先ごとに1件ずつ送るトランザクション配信より、一斉配信が向いています。
GitHub MCPのツールを絞る
GitHub MCPサーバー2.0.3は、何も指定しないとcontext、copilot、issues、pull_requests、repos、usersのツール群が有効になります。手元では46個のツールが公開され、その中にはファイルの作成や削除、プルリクエストのマージといった書き込み系も含まれていました。
起動オプションを変えてtools/listを取り、claude -pに「OKとだけ返して」と指示したときの入力トークン数も比べました。
| 起動オプション | ツール数 | 入力トークン | MCPなしとの差 |
|---|---|---|---|
| MCPサーバーなし | ― | 5,462 | ― |
| 指定なし(既定) | 46 | 25,803 | +20,341 |
--read-only --toolsets=repos,pull_requests |
16 | 13,689 | +8,227 |
--read-only --tools=list_releases,get_release_by_tag,pull_request_read |
3 | 7,672 | +2,210 |
既定のままだと、ツール定義だけで2万トークンを超えます。読み取り専用にしてツール群を2つに絞ると約8,200トークン、使うツールだけを名指しすると約2,200トークンで、既定の約1割になりました。
--toolsetsはツール群の単位で、--toolsは個々のツールの単位で指定します。--read-onlyと組み合わせると、読み取り系のツールだけが残ります。
--allowedToolsではコンテキストは減らない
検証の途中で、kintoneやスプレッドシートのMCPサーバーも登録したままの設定で、同じ指示を実行してしまった回がありました。Claude Codeの--allowedToolsではGitHubの3ツールだけを許可していたのですが、結果は5ターンで約0.43ドルでした。GitHubとblastengineだけを登録した設定で実行し直すと、6ターンで約0.13ドルです。
--allowedToolsやpermissionsは、ツールの実行を許可するか止めるかを決める仕組みです。登録されたMCPサーバーのツール定義は、許可していないものも含めてすべてエージェントに渡ります。コンテキストを減らしたいなら、使わないサーバーは設定ファイルから外し、使うサーバーはサーバー側のオプションでツールを絞る必要があります。
手順1:リリースノートとプルリクエストを読ませる
あなたは社内で blastengine MCP サーバー(GitHub: rakus-lc/blastengine-mcp)を配布・管理している担当者です。
社内の利用者(エンジニアではない営業・CSのメンバーも含む)に、アップデートのお知らせメールを書きます。
1. GitHub の rakus-lc/blastengine-mcp のリリース一覧を取得し、v0.2.0 より後に出たリリース(v0.2.1, v0.2.2)の本文を読んでください。
2. 本文の「What's Changed」に出てくるプルリクエストは、必要に応じて内容を読み、何が変わったのかを確認してください。
エージェントはlist_releasesを1回呼び、続けてpull_request_readをプルリクエスト#2〜#5の4件分呼びました。
list_releasesの返り値には、各リリースの本文がそのまま含まれていました。そのため、タグを指定して1件ずつ取るget_release_by_tagは使われていません。リリースの数が少ないリポジトリなら、list_releasesとpull_request_readの2つで足ります。
リリースノートの「What's Changed」は、プルリクエストのタイトルを並べただけのものです。v0.2.2の場合は次の1行でした。
* Fix all Dependabot alerts and bump version to 0.2.2 by @rakus-shota-yamada in https://github.com/rakus-lc/blastengine-mcp/pull/5
これだけでは、利用者に影響があるのかどうか判断できません。プルリクエスト#5の本文には、解消したアラートの件数と深刻度、変更したファイルがpackage.jsonとpackage-lock.jsonの2つだけであることが書かれていました。エージェントはこれを読んで、「機能の追加や使い方の変更はない」と判断しています。
また、v0.2.0とv0.2.1のリリース本文の冒頭には、成果物を取り下げたという警告が入っていました。エージェントはこの警告を拾い、「v0.2.0とv0.2.1を使っている人は更新が必要」というお知らせの軸を組み立てています。
手順2:利用者向けの下書きを作らせる
3. 利用者向けのお知らせメールの件名と本文(テキスト)の下書きを作ってください。
- 利用者がやるべきこと(更新が必要か、どの版を使えばよいか)を最初に書く
- 誤字修正やメタデータの変更など、利用者に影響しない変更は載せないか、まとめて一言にする
- リリースノートとプルリクエストに書かれていないことは書かない。推測で補った箇所や、ある時点での状態を述べている箇所があれば、下書きの後に別に列挙する
- 送信元・署名は「株式会社example 情報システム担当」とする
メールはまだ送らないでください。下書きと、読んだリリース・プルリクエストの一覧を報告してください。
返ってきた下書きの本文は次のとおりです。
各位
株式会社example 情報システム担当です。
blastengine MCP サーバーの新しい版(v0.2.2)が公開されました。
■ お願いしたいこと
v0.2.0 または v0.2.1 をお使いの方は、v0.2.2 への更新をお願いします。
v0.2.0 と v0.2.1 の配布ファイルは、同梱していた部品(依存パッケージ)に
既知の脆弱性が含まれていたため、公開元で取り下げられています。
今後は v0.2.2 以降をご利用ください。
■ 更新方法
配布ページから v0.2.2 のファイル(blastengine-mcp-server-0.2.2.mcpb)を
ダウンロードし、README のインストール手順に従って入れ替えてください。
(配布ページと README のURL)
■ 変更内容
・v0.2.1: 同梱部品の脆弱性(15件)を修正しました。
・v0.2.2: 同梱部品の脆弱性(11件)を追加で修正しました。
・そのほか、README の表記修正など、使い方に影響しない軽微な変更が含まれます。
(以下略)
利用者がやるべきことが冒頭にあり、誤字の修正やマニフェストの変更は「軽微な変更」の一言にまとめられています。指示どおりの形です。
「その時点の状態」を言い切らせない
指示の3つ目にある「ある時点での状態を述べている箇所」の一文は、最初の指示にはありませんでした。その一文がないときの下書きには、次の文が入っていました。
v0.2.2 の時点で、既知の脆弱性は残っていません。
出どころは、プルリクエスト#5の本文にある「残存する脆弱性: なし(npm auditは0件)」という記載です。でたらめではありません。ただ、これはプルリクエストをマージした時点の話です。お知らせを送る日には、新しい脆弱性が見つかっているかもしれません。利用者が読めば「v0.2.2は安全」と受け取ります。
しかも、このときの下書きの後には、推測で補った箇所が8つ列挙されていたのに、この文はその中に入っていませんでした。資料に書いてあることなので、エージェントにとっては推測ではないからです。
指示に一文を足して実行し直すと、この文は本文から消え、下書きの後に次のように列挙されました。
ある時点の状態を述べている箇所
- 「15件」「11件」は、各 PR 作成時点の Dependabot アラート件数です。
- PR には「残存する脆弱性なし」「npm audit 0件」とありますが、これもマージ時点の話です。
そのため本文では「現在は安全」とは書いていません。
- PR #4 と #5 の脆弱性の一部は開発用の依存でした(tmp、vitest など)。
バンドルに入る本番依存かどうかは項目ごとに違います。
本文では「同梱部品」とまとめましたが、厳密には全件が配布物に入っていたわけではありません。
リリースノートやプルリクエストは、書かれた時点の事実を書いたものです。それを後日のお知らせに転記すると、時点がずれた主張になりやすくなります。資料にない推測を挙げさせるだけでは足りず、時点のある記述も挙げさせておくと、人が確認すべき箇所がはっきりします。
3つ目の項目のとおり、件数を「同梱部品の脆弱性」とまとめた表現は、厳密ではありません。エージェント自身がそう申告しているので、人が確認する段階で「依存パッケージの脆弱性(15件、開発用を含む)」に直しました。
手順3:一斉配信の下書きを作る
直した本文で、blastengineの一斉配信の下書きを作らせます。この段階では、確定(送信)のツールを許可しません。
blastengine で、社内利用者向けのお知らせメールを一斉配信の下書きとして用意します。確定(送信)はしないでください。
1. まず blastengine_deliveries_list で、件名に「v0.2.2」を含む配信がすでにないか確認してください。
送信済みや予約済みのものがあれば、下書きは作らずにそれを報告して終了してください。
2. なければ blastengine_bulk_begin で下書きを作ってください。(送信元・件名・本文を指定)
3. blastengine_bulk_update_recipients で宛先を設定してください。
4. blastengine_bulk_preview で下書きの内容を取得し、指示どおりかを確認して報告してください。
claude -p "(上の指示)" \
--mcp-config .mcp.json --strict-mcp-config --tools "" \
--allowedTools "mcp__blastengine__blastengine_deliveries_list,mcp__blastengine__blastengine_bulk_begin,mcp__blastengine__blastengine_bulk_update_recipients,mcp__blastengine__blastengine_bulk_preview"
エージェントは次の順でツールを呼びました。
-
blastengine_deliveries_listを{"subject": "v0.2.2", "delivery_type": ["BULK"]}で呼ぶ。結果は0件 -
blastengine_bulk_beginで下書きを作る(返り値は{"delivery_id":12}) -
blastengine_bulk_update_recipientsで宛先を設定する -
blastengine_bulk_previewで内容を確認する
ここまでで5ターン、約0.09ドルでした。
bulk_previewでは本文の全文を確認できない
blastengine_bulk_previewの返り値は次のとおりでした。
{
"delivery_id": 12,
"subject": "【要対応】blastengine MCP を v0.2.2 に更新してください",
"from": { "email": "info@example.com", "name": "株式会社example 情報システム担当" },
"recipient_count": 1,
"body_summary": "各位 株式会社example 情報システム担当です。 blastengine MCP サーバーの新しい版(v0.2.2)が公開されました。 ■ お願いしたいこと v0.2.0 または v0.2.1 をお使いの方は、v0.2.2 への更新をお願いします。...",
"note": "This preview is informational only. It does not authorize or block commit. Bulk commit tools execute directly when BLASTENGINE_ENABLE_BULK=true."
}
返ってくるのは件名、送信元、宛先数と、改行を詰めて冒頭だけを切り出したbody_summaryです。配信の状態(下書きかどうか)も本文の全文も含まれません。noteにあるとおり、このツールは確認用の情報を返すだけで、確定を止める働きもありません。
エージェントは、本文が指示と1文字ずつ一致するかと状態については「確認できていない」と報告し、管理画面での確認を勧めてきました。分からないことを分かったように報告しなかったのは良い挙動です。
人が全文を確かめたい場合は、blastengine_delivery_getも許可しておきます。配信情報にはstatus(下書きならEDIT)とtext_part(本文の全文)が含まれます。今回はAPIを直接呼んで、配信ID 12がBULK・EDIT・宛先1件で、本文が指示どおりであることを確認しました。
手順4:人が確認してから確定する
下書きの内容を人が確かめたら、確定のツールだけを許可して実行します。
claude -p "一斉配信の下書き(配信ID 12)を blastengine_bulk_commit_immediate で即時に確定してください。ほかの配信IDには触れないでください。確定後、blastengine_delivery_get と blastengine_mail_results_list で配信ID 12 の状態と宛先ごとの配信結果を確認してください。配信ログが空なら、少し待って引き直してください。" \
--mcp-config .mcp.json --strict-mcp-config --tools "" \
--allowedTools "mcp__blastengine__blastengine_bulk_commit_immediate,mcp__blastengine__blastengine_delivery_get,mcp__blastengine__blastengine_mail_results_list"
下書きを作る実行と確定する実行を分け、それぞれで許可するツールを変えています。こうすると、下書きを作る段階で誤って送ってしまうことはありません。また、確定する段階では配信IDを人が指定するので、確定する配信を取り違えにくくなります。
送信の直前に承認を挟む方法は、ほかに誤送信を防ぐ記事で扱ったhooksもあります。
一斉配信でも確定直後は結果が出ていない
確定の直後にblastengine_delivery_getを呼ぶと、statusはSENTなのにsent_countは0でした。同時に引いたblastengine_mail_results_listも空です。
{
"delivery_id": 12,
"delivery_type": "BULK",
"status": "SENT",
"total_count": 1,
"sent_count": 0,
"drop_count": 0
}
エージェントが引き直すと、配信ログにSENT / 250が現れ、sent_countも1になりました。配信ログの配信時刻が00:44:44、更新時刻が00:44:47で、確定から数秒のずれです。
kintoneの記事とスプレッドシートの記事ではトランザクション配信で同じ現象が起きていましたが、一斉配信でも同様でした。配信情報のstatusのSENTは、配信処理の段階を表すものです。届いたかどうかは、sent_countや配信ログで確かめます。
確定から確認までは6ターン、約0.04ドルでした。
同じリリースを二重に案内しない
手順3の最初に入れた重複チェックは、もう一度同じ指示を実行したときに効きます。確定した後に、重複チェックの部分だけを実行し直しました。
件名に「v0.2.2」を含む一斉配信(BULK)が1件ありました。配信済みなので、新しい下書きは作っていません。
blastengine_deliveries_listのsubjectで件名を部分一致で探しているので、件名にバージョン番号を入れておけば、そのリリースを案内済みかどうかを判定できます。
件名だけで判定すると、作ったまま放置した下書きや、DROPばかりで届いていない配信も「案内済み」に数えてしまう可能性があります。指示では、見つかった配信のstatusやsent_countまで見て判断させるようにします。
なお、blastengineの配信情報の保持期間は配信開始から62日です。それより前のリリースの案内は、この方法では判定できません。
つまずきやすいポイント
| 症状 | 原因と対処 |
|---|---|
| 何もしないうちにコンテキストを2万トークン使っている | GitHub MCPの既定では46ツールが公開される。--read-onlyと--tools(または--toolsets)で絞る |
--allowedToolsで絞ったのにコストが下がらない |
--allowedToolsは実行の許可だけで、ツール定義は登録したサーバーの分がすべて渡る。使わないサーバーは設定から外す |
| お知らせに「現在は安全」のような断定が入る | プルリクエストやリリースノートに書かれた、その時点の状態を転記している。時点のある記述は別に列挙させ、人が確認する |
| リリースノートだけでは利用者への影響が分からない | 「What's Changed」はプルリクエストのタイトルの一覧。pull_request_readで本文を読ませる |
bulk_previewで本文の全文を確認できない |
返るのは冒頭のbody_summaryだけで、状態も含まれない。全文はblastengine_delivery_getのtext_partで確認する |
確定直後にstatusがSENTなのにsent_countが0 |
配信ログの反映待ち。少し待ってblastengine_mail_results_listを引き直す |
| 案内済みかどうかの判定がずれる | 件名だけでなく、見つかった配信のstatusやsent_countまで見て判定させる |
| 下書きの段階で送ってしまいそう | 下書きを作る実行と確定する実行を分け、確定のツールは確定する実行でだけ許可する |
まとめ
GitHubとblastengineを1つのエージェントにつなぐ構成のポイントは3つです。
- GitHub MCPサーバーは
--read-onlyと--toolsで、使う読み取り系のツールだけを公開する。ツール定義のコンテキストは既定の約2万トークンから約2,200トークンに減る - リリースノートだけでなくプルリクエストまで読ませると、利用者への影響を判断した文面になる。ただし、資料に書かれた「その時点の状態」は言い切らせず、別に列挙させて人が確認する
- 一斉配信は、下書きを作る実行と確定する実行を分ける。
bulk_previewは要約しか返さないので、全文の確認にはblastengine_delivery_getを使う
開発者向けの記録から利用者向けのお知らせへの書き換えはエージェントに任せ、何を言い切ってよいかの判断と送信の確定は人が持つ、という分担が、この構成の使いどころです。
blastengine MCPサーバーへの要望や感想は、以下のアンケートフォームから送ると開発チームに届くみたいです。
https://docs.google.com/forms/d/e/1FAIpQLSdNZ9TswUT3JEv3pMHkJGqOvgmsXuKP1smkJiNEsqbTVDwRyg/viewform
※本記事の手順は、GitHub MCPサーバー2.0.3(Dockerイメージ)とblastengine MCPサーバー v0.2.2を接続し、Claude Code(Sonnet)からリリースとプルリクエストの読み取り、下書きの作成、一斉配信の下書き作成、確定、配信結果の確認まで通しで確認しました。提供ツールや引数はバージョンによって変わるため、手元のtools/listを確認してください。