0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

プリザンターのMCPサーバーとblastengine MCPをつないで、期限超過レコードの督促メールを送る

0
Posted at

プリザンター(Pleasanter)は、バージョン1.5.2.0(2026年3月10日リリース)でMCPサーバー機能を本体に取り込みました。プラグインを別途立てるのではなく、プリザンター自身が/mcpエンドポイントを提供します。

一方blastengineにも公式のMCPサーバーがあります。この2つを1つのAIエージェントに繋ぐと、「案件テーブルから期限を過ぎたレコードを探して、担当者に督促メールを送り、送信した事実をレコードに書き戻す」という一連の作業を会話から回せます。本記事ではその構成をClaude Codeで組みます。

blastengine MCPの導入手順は導入記事、各ツールの入出力は全15ツールの検証記事を参照してください。

全体構成

                 ┌──────────────────────────────┐
                 │        Claude Code           │
                 └───────┬──────────────┬───────┘
              HTTP       │              │ stdio
        (X-Api-Key)    │              │
        ┌────────────────▼───┐      ┌───▼──────────────────┐
        │  プリザンター      │      │  blastengine MCP     │
        │  /mcp(本体機能)  │      │                      │
        └────────────────────┘      └───────────┬──────────┘
                                                │
                                    ┌───────────▼──────────┐
                                    │     blastengine      │
                                    └──────────────────────┘

プリザンター側のMCPは本体に内蔵されたHTTPサーバー、blastengine側は手元でビルドするstdioサーバーです。トランスポートが違うので、登録方法も変わります。

準備1:プリザンター側でMCPを有効化する

MCPサーバー機能は既定で無効です。Parameters/McpServer.jsonを編集して有効化します。初期値は次のようになっています。

{
    "Enabled": false,
    "ReadOnlyMode": false,
    "LogExportLimit": 10000,
    "RateLimit": {
        "FixedWindow": { "Enabled": false, "PermitLimit": 30, "WindowSeconds": 60 },
        "SlidingWindow": { "Enabled": false, "PermitLimit": 30, "WindowSeconds": 60, "SegmentsPerWindow": 5 },
        "TokenBucket": { "Enabled": false, "TokenLimit": 10, "TokensPerPeriod": 1, "ReplenishmentPeriodSeconds": 2 },
        "Concurrency": { "Enabled": false, "PermitLimit": 3 }
    },
    "Logging": {
        "EnableLoggingToDatabase": true,
        "EnableLoggingToFile": false,
        "NotLoggingIp": [],
        "ResponseDataMaxLength": 65536
    }
}

最低限、Enabledtrueにして再起動すれば動きます。あわせて確認しておきたい項目は3つです。

  • ReadOnlyModetrueにすると参照系のツールしか使えなくなります。後述しますが、レコードへの書き戻しをするかどうかで設定が変わります。
  • RateLimit … 既定ではどの方式も無効です。AIは人間より短時間に多くのリクエストを投げるので、FixedWindowあたりを有効にしておくと事故の影響を抑えられます。
  • Logging … 既定でデータベースへのログ出力が有効です。誰がどのツールを呼んだかを後から追えるので、そのまま有効にしておくのがおすすめです。

APIキーはプリザンターにログインしたうえで、ユーザーのメニューから発行します。ここで発行したキーの権限は、そのユーザーの権限そのものです。AIに見せたくないサイトがあるなら、権限を絞った専用ユーザーを作ってそのキーを使うのが確実です。

準備2:Claude Codeに2つのMCPを登録する

プリザンターはHTTPトランスポートで、ヘッダーにX-Api-Keyを付けて接続します。

claude mcp add pleasanter \
  --transport http \
  --scope local \
  https://pleasanter.example.com/mcp \
  --header "X-Api-Key: $PLEASANTER_API_KEY"

ヘッダー名はX-Api-Keyです。マニュアルの記載と実装で表記が揺れていた時期があるので、認証で弾かれたらまずここを疑ってください。

なお、公式が配布しているPleasanter MCP拡張.mcpbファイル)はClaude Desktop向けで、中身はmcp-remoteを介したプロキシです。自己署名証明書に対応するためNODE_TLS_REJECT_UNAUTHORIZED=0を設定しており、TLS証明書の検証を無効化する点がリポジトリでも明記されています。Claude Codeから上のように直接繋ぐ場合、正規の証明書を使っていれば検証を切る必要はありません。社内のプリザンターに自己署名証明書を使っているなら、まずは証明書を正すほうを検討してください。

blastengine側はstdioで登録します。今回はトランザクション送信だけを使うので、有効にするフラグはBLASTENGINE_ENABLE_SENDのみです。一斉配信とCSVインポートは切っておきます。

claude mcp add blastengine \
  --scope local \
  --env BLASTENGINE_LOGIN_ID="$BLASTENGINE_LOGIN_ID" \
  --env BLASTENGINE_API_KEY="$BLASTENGINE_API_KEY" \
  --env BLASTENGINE_ENABLE_SEND=true \
  --env BLASTENGINE_ENABLE_BULK=false \
  --env BLASTENGINE_ENABLE_CSV_IMPORT=false \
  -- node /absolute/path/to/blastengine-mcp/dist/index.js

/mcpで両方が接続済みになっていれば準備完了です。

プリザンター側のツールを把握する

繋いだら、まずツール一覧を確認します。プリザンターのバージョンによって提供されるツールが違うためです。手元の環境でtools/listを取るのが確実で、MCP Inspectorを使ってもいいですし、Claude Codeのセッション内なら/mcpから一覧できます。

手元の1.5.7.1では18ツールでした。

分類 ツール
レコード GetItem / GetItems / AddItem / UpdateItem / DeleteItem / CreateItemJson
ビュー CreateViewJson / GetView / GetViewIdByViewName / AddView / UpdateView / CopyView / DeleteView
サイト GetSite / GetSiteIdByTitle
ユーザー GetUsers / GetUserIdByName
メール SendEmail

Claude Desktop向けに配布されている拡張のmanifest(1.0.0)は16ツールで、レコードの追加・削除がなく、メール送信はSendMail、JSON生成はCreateUpdateItemJsonという名前です。ツール名も引数名もバージョンで動くので、記事の記載よりも手元のtools/listを優先してください。

使い方には独特の作法があります。検索条件は生のJSONを書くのではなく、いったんCreateViewJsonでView JSONを生成し、それをGetItemsviewJsonに渡します。CreateViewJsonは次のような引数を取ります。

引数 内容
siteId 検索対象のサイトID
incomplete 未完了レコードのみ対象にする
overdue 期限超過レコードのみ対象にする
nearCompletionTime 期限が近いレコードのみ対象にする
delay 遅延レコードのみ対象にする
search 全文検索キーワード
apiGetMailAddresses GetUsersでメールアドレスを取得する

今回ほしい「期限を過ぎた未完了レコード」は、incompleteoverdueの組み合わせで表現できます。

手順1:期限超過のレコードを取る

サイトIDが分からなくても、サイト名から引けます。

プリザンターの「案件管理」サイトから、期限を過ぎている未完了のレコードを取得して。
タイトル、担当者、期限、状況を一覧にして。

AIはGetSiteIdByTitleでサイトIDを引き、CreateViewJsonincompleteoverdueを立てたView JSONを作り、GetItemsに渡す、という順で動きます。GetItemsの1回あたりの取得件数は200件で、それ以上はoffsetに200、400と指定して続きを取ります。件数が多いときは、AIが2ページ目以降を取り漏らしていないかを確認してください。

手順2:担当者のメールアドレスを解決する

レコードの担当者はユーザーIDで持っているので、メールアドレスはGetUsersで引きます。ここで必要なのがapiGetMailAddressesです。CreateViewJsonでこのフラグを立てたView JSONを作り、GetUsersに渡すと、メールアドレスを含んだユーザー情報が返ります。

さっき取得したレコードの担当者について、メールアドレスを取得して。
担当者ごとに、担当している期限超過レコードの件数と一覧をまとめて。

担当者単位でまとめておくと、1人に何通も送らずに済みます。

手順3:blastengineで督促メールを送る

送信はblastengine_send_transactionを使います。必須項目はfrom_email / to / subject / text_partで、html_partcc / bcc(各最大10件)、reply_to_emailは任意です。

担当者ごとに文面を変えたいときは、差し込みコード(insert_code、最大50件)を使います。本文中に__prop1__のように書いた箇所が置き換わります。キーの書式は__key__または%%key%%で、使えるのはASCIIの英数字だけです(スキーマ上も^(__|%%)[0-9a-zA-Z]+\1$で検証されます)。日本語のキーは弾かれます。

{
  "from_email": "pm@example.com",
  "to": "tanaka@example.com",
  "subject": "【ご確認】期限超過の案件があります",
  "text_part": "__prop1__ 様\n\n期限を過ぎている案件が __prop2__ 件あります。",
  "insert_code": [
    { "key": "__prop1__", "value": "田中" },
    { "key": "__prop2__", "value": "3" }
  ]
}

送信が通るとdelivery_idが返ります。ただし、これはblastengineが受け付けたという意味であって、届いたという意味ではありません。配信可能アドレスに登録していない宛先だと、送信ツールは成功としてdelivery_idを返す一方、配信ログ側ではDROP、レスポンスコード554(rejection)(「宛先が配信可能なアドレスではありません」)になります。

エージェントは戻り値だけを見て「送信しました」と報告するので、到達の確認まで指示に含めてください。そのIDでblastengine_mail_results_listを引けば、SENTとレスポンスコード(成功なら250)まで分かります。

送信前に、必ず内容を確認する手順を挟みます。

担当者ごとに督促メールの下書きを作って。送信元は pm@example.com。
件名は「【ご確認】期限超過の案件が◯件あります」、
本文には該当レコードのタイトルと期限を箇条書きで入れて。
まだ送らないで、全員分の下書きを表で見せて。

内容を確認してから送信させます。

いま確認した内容で、3名に送信して。1通ずつ送って、
送信できたかどうかを宛先ごとに報告して。

ここでBLASTENGINE_ENABLE_BULKを切ってあるのが効いてきます。一斉配信のツールが実行時に弾かれるので、AIが気を利かせて一斉配信に切り替えることがありません。1通ずつのトランザクション送信に固定されます。

差し込みコードのキーは、指示しなければエージェントが自分で決めます。実際に試すと__tantou____kensu__のような分かりやすい名前を付けてきました。本文とキーの対応さえ取れていれば動きますが、テンプレートを固定して運用するなら、キーもこちらで指定しておくほうが後から読みやすくなります。

なお、送信のような取り消せない操作の手前では、エージェントは自分から止まって確認を求めてきます。対話で使う分にはこれが承認ゲートとして働きますが、claude -pで自動実行するときは、止まったまま何も送らずに終わります。バッチに載せるなら、プロンプトの中で承認済みであることを明示する必要があります。

手順4:送信した事実をプリザンターに書き戻す

やりっぱなしにせず、レコード側に記録を残します。更新はUpdateItemで行い、更新用のJSONはCreateUpdateItemJson(バージョンによってはCreateItemJson)で作ります。

督促メールを送ったレコードのコメント欄に、送信した旨と日付を追記して。
更新前に、対象レコードIDと更新内容を一覧で見せて。

ここに、実際に動かして分かった大きな落とし穴があります。UpdateItemitemDataJsonは、認識できない項目名を渡しても成功として返ってきます。

{"Comments":"2026-08-26 督促しました"}   → 200 更新しました(実際に書き込まれる)
{"コメント":"2026-08-26 督促しました"}   → 200 更新しました(何も書き込まれない)

どちらもStatusCode: 200と「更新しました」が返るのに、後者はレコードに何も残りません。バージョンも更新日時も変わらないままです。ユーザーの言語設定を日本語にしても同じでした。

CreateItemJsonを通せば表示名を内部名に変換してくれそうなものですが、手元で試した限り、渡したJSONがそのまま返ってくるだけで変換はされませんでした。

これがエージェント運用だと厄介です。日本語で指示すると、エージェントは自然に{"コメント": ...}を組み立て、返ってきた200を見て「更新しました」と報告します。実際にはプリザンター側に何も残っていません。指示の中で内部項目名(CommentsStatusCompletionTimeなど)を使うよう明示するか、更新後にGetItemで読み直して確認させるのが確実です。

更新後に GetItem で読み直して、実際に反映されているか確認して報告して。

ReadOnlyModeをどう扱うか

McpServer.jsonReadOnlyModetrueにすると、参照系のツールだけが使える状態になります。許可されるのは次の10ツールです。

CreateItemJson / GetItem / GetItems / GetSite / GetSiteIdByTitle / GetUserIdByName / GetUsers / CreateViewJson / GetView / GetViewIdByViewName

つまり、レコードの更新(UpdateItem)もメール送信(SendMail / SendEmail)も、ReadOnlyModeでは実行できません。手順4の書き戻しをやるならReadOnlyModefalseにする必要があります。

安全側に倒すなら、次のどちらかを選ぶことになります。

  • 書き戻しを諦め、プリザンターはReadOnlyMode=trueの参照専用にする。送信はblastengine側だけが行い、記録はblastengineの配信ログに任せる
  • 書き戻しをする代わりに、権限を絞った専用ユーザーのAPIキーを使い、そのユーザーが触れるサイトを限定する

運用の実感としては後者が現実的です。督促を送った事実がプリザンター側に残らないと、翌日また同じ督促を送ってしまいます。

プリザンターのメール送信とblastengineの使い分け

プリザンターのMCPにもメール送信ツールがあります。これは「指定したレコードに関連するメールを送る」もので、プリザンターに設定したメール送信の仕組みをそのまま使います。宛先・件名・本文に加えて添付も扱えます。

blastengineを挟む理由は、送信そのものではなく、送信のあとに残るものにあります。

観点 プリザンターのメール送信 blastengine経由
送信元ドメインの認証 プリザンター側のメール設定に依存 SPF・DKIM・DMARCを設定した送信ドメインで送れる
到達の可否 送信できたかどうかが中心 宛先ごとの配信ログ(SENT / HARDERRORなど)を残せる
バウンスの追跡 個別に確認が必要 ログ検索とエラー詳細をAPIから取れる
大量配信 想定外 一斉配信・予約配信の仕組みがある
レコードとの紐付け レコードに直接紐づく 別サービスなので、紐付けは自分で残す

社内の1〜2通の連絡ならプリザンターから送るほうが素直です。取引先や顧客に届く必要があるメール、あるいは届かなかったことを検知したいメールでは、blastengineを挟む価値が出ます。

つまずきやすいポイント

症状 原因と対処
認証が通らない ヘッダー名はX-Api-Key。表記揺れに注意。APIキーの権限は発行したユーザーの権限と同じ
ツールが見つからない McpServer.jsonEnabledfalseのまま、または再起動していない
更新系ツールが拒否される ReadOnlyModetrueになっている。許可されるのは参照系10ツールのみ
記事と提供ツール名が違う プリザンターのバージョン差。手元のtools/listを正とする
検索結果が途中で切れる GetItemsは1回200件。offsetを200、400と進めて続きを取る
更新が成功したのに反映されない itemDataJsonの項目名が内部名でない。未知のキーは200を返して黙って捨てられる。GetItemで読み直して確認する
UpdateItemの引数名が違う 1.5.7.1ではreferenceId。バージョンによってitemIdの場合がある
ReadOnlyModeの拒否がエラーに見えない 拒否メッセージはisError: falseのテキストとして返る。ツールによっては汎用エラーになる
短時間に大量のリクエストが飛ぶ RateLimitは既定で全方式無効。FixedWindowなどを有効にする
一斉配信ツールが使えない 本構成ではBLASTENGINE_ENABLE_BULK=falseにしている。意図的な設定
62日より前の配信ログが出ない blastengineの配信情報は配信開始から62日で削除される
送信は成功したのにメールが届かない 配信可能アドレスに未登録の宛先は送信ツール側でエラーにならず、配信ログでDROP / 554(rejection)になる
MCP Inspectorで認証が通らない InspectorのCLIモードは親シェルの環境変数をサーバーに渡さない。-e KEY=valueで明示的に渡す
blastengine MCPが起動しない Node.js 22.15以上が必要(package.jsonのengines)

まとめ

プリザンターとblastengineを1つのエージェントに繋ぐ構成のポイントは3つです。

  • プリザンターは1.5.2.0以降なら本体が/mcpを提供する。Parameters/McpServer.jsonEnabledtrueにし、Claude Codeからは--transport httpX-Api-Keyヘッダーで直接繋げる
  • 検索はCreateViewJsonでView JSONを作ってからGetItemsに渡す。期限超過はincompleteoverdue、メールアドレスはapiGetMailAddressesで取る
  • 送信はblastengineのblastengine_send_transactionに固定し、ENABLE_BULKは切っておく。書き戻しをするならReadOnlyModefalseにせざるを得ないので、代わりに権限を絞った専用ユーザーのAPIキーを使う

督促のような定型業務は、条件も文面も毎回ほぼ同じです。会話で回せるようになったら、次は非対話での定期実行に持っていくと運用が固まります。


blastengine MCPサーバーへの要望や感想は、以下のアンケートフォームから送ると開発チームに届くみたいです。

https://docs.google.com/forms/d/e/1FAIpQLSdNZ9TswUT3JEv3pMHkJGqOvgmsXuKP1smkJiNEsqbTVDwRyg/viewform

※本記事の手順は、プリザンター1.5.7.1(Docker)とblastengine MCPサーバー v0.2.1をClaude Codeに接続し、期限超過レコードの抽出から実送信・書き戻しまで通しで確認しました。提供ツールや引数名はバージョンにより変わるため、手元のtools/listを確認してください。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?