MCPの進捗通知(progress notifications)を実装するパターン
MCPの長時間処理向け進捗通知の仕様を解説します。progressTokenの発行ルール・progress値の単調増加・レート制限の必須事項を仕様原文から示します。
MCPには、時間のかかる処理の進み具合をクライアントへ伝えるための進捗通知(progress notifications)という任意機能があります。大きなファイルのインデックス作成や、外部APIへの多段リクエストのように、応答までに数秒〜数十秒かかるツール呼び出しで使う仕組みです。MCPサーバーを自作する際、ユーザーを待たせるツールがあるなら実装を検討する価値があります。
MCPの進捗通知はなぜ「任意」の機能なのか
進捗通知はMCP仕様の中でも珍しく、サーバーが実装するかどうかを完全にサーバーの裁量に委ねている機能です。クライアントがリクエストに進捗トークンを含めても、サーバー側は通知を送らないという選択肢(MAY)を持ちます。これは他の多くの仕様がMUST/SHOULDで挙動を縛るのと対照的です。
理由は、進捗通知が処理の正しさに影響しない付加情報だからです。通知が1つも届かなくても、最終的な結果(レスポンス)さえ正しく返ればMCPとしての契約は満たされます。進捗通知はあくまでUX向上のための仕組みであり、進捗バーやスピナーの表示に使う情報という位置づけです。
もう1つ興味深いのは、進捗通知の配送経路です。2026-07-28リビジョンでは、サーバーからクライアントへの変更通知(toolsListChanged等)をsubscriptions/listenという専用の長時間ストリームに一本化する変更が入りました。ですがnotifications/progressとnotifications/messageはこの対象外で、元のリクエストの応答ストリーム上に流れ続ける仕組みのままです。進捗通知は「どのリクエストの進捗か」が自明である必要があるため、リクエストごとの経路と紐づいたままにする設計判断です。
進捗通知と混同しやすいのが、同じ2026-07-28リビジョンで導入されたMulti Round-Trip Requests(MRTR)です。どちらも「1回のツール呼び出しで終わらない、時間のかかるやり取り」を扱う点は共通していますが、性格は異なります。
MRTRは、サーバーが処理を完了するために追加情報を要求し、クライアントが情報を添えて同じリクエストをやり直すパターンで、リクエストの往復そのものが複数回に分かれます。一方、進捗通知は単一のリクエストが処理され続けている間の経過を伝えるだけで、リクエストのやり取り自体は1往復のままです。「追加の入力が要るか」がMRTR、「今どこまで進んだか」が進捗通知、という切り分けで覚えると混同しにくくなります。処理そのものを途中で打ち切りたい場合はどちらでもなく、MCPのCancellationとはが定めるnotifications/cancelledの役目です。
progressTokenと通知メッセージの仕様
進捗通知を受け取りたいクライアントは、リクエストの_metaフィールドにprogressTokenを含めます。
{
"jsonrpc": "2.0",
"id": 1,
"method": "some_method",
"params": {
"_meta": {
"progressToken": "abc123"
}
}
}進捗トークンの仕様上のルールは次の2つです。
- 文字列または整数のいずれかでなければならない(MUST)
- クライアントが任意の方法で選んでよいが、アクティブな全リクエストの中で一意でなければならない(MUST)
このトークンを受け取ったサーバーは、処理の途中で次のような通知を任意のタイミングで送ることができます。
{
"jsonrpc": "2.0",
"method": "notifications/progress",
"params": {
"progressToken": "abc123",
"progress": 50,
"total": 100,
"message": "Reticulating splines..."
}
}通知に含まれるフィールドは4つで、必須なのは最初の2つだけです。
| フィールド | 必須 | 内容 |
|---|---|---|
progressToken | 必須必須 | 内容どのリクエストに対する通知かを示す元のトークン |
progress | 必須必須 | 内容ここまでの進捗値 |
total | 必須任意 | 内容全体量。不明なら省略してよい |
message | 必須任意 | 内容人間が読める進捗メッセージ |
仕様が定める必達事項の中でもとりわけ見落としやすいのが、progressの値のルールです。「progressの値は、totalが不明であっても、通知のたびに増加しなければならない(MUST)」と明記されています。全体量が分からない処理(たとえば「あと何件残っているか事前に分からないクロール処理」)でも、進捗値そのものは単調増加を保つ必要があるということです。
実装するなら、経過時間や処理済みバイト数、処理済み件数のような、後戻りせず必ず増え続ける値をprogressに使うのが安全です。progressとtotalはどちらも浮動小数点数を許容しており、パーセンテージ(0.0〜1.0)のような表現も仕様上は問題ありません。
実装時の注意点とレート制限
進捗通知には、トークンの参照先に関する制約があります。通知が参照してよいトークンは「アクティブなリクエストで提供されたもの」かつ「進行中の操作に紐づいたもの」に限られます(MUST)。完了済みのリクエストや、存在しないトークンに対する通知を送ってはなりません。実際、仕様は「進捗通知は完了後に止まらなければならない(MUST)」と明記しており、レスポンスを返した後に遅れて届く進捗通知は仕様違反です。
レート制限についても言及があります。仕様は、クライアントとサーバーの両方がアクティブな進捗トークンを追跡すべき(SHOULD)としています。そのうえで、通知の発行頻度を追跡し、フラッディング(過剰な頻度での通知送信)を防ぐレート制限を双方が実装すべき(SHOULD)とも定めています。サーバー側が「1%進むごとに毎回通知する」ような実装にすると、進捗が細かい処理では通知の量がリクエスト本体のトラフィックを圧迫しかねません。時間間隔(たとえば200ミリ秒に1回)か、進捗の変化量(たとえば5%刻み)のどちらかで間引く実装が現実的です。
サーバー側に許されている裁量は3つあります。
- 進捗トークンを受け取っても、一切通知を送らないことを選んでよい(MAY)
- 通知を送る頻度は、サーバーが適切と判断する任意の頻度でよい(MAY)
totalの値が不明なら省略してよい(MAY)
この3つのMAYは、いずれも「実装しない・簡略化する」方向の自由度です。仕様が強制しているのは、通知を送ると決めた場合の挙動(トークンの妥当性・progressの単調増加・完了後の停止)だけであり、通知を送るかどうかの判断自体はサーバー実装者に委ねられています。裏を返せば、最小限の実装として「通知を一切送らない」を選んでも仕様違反にはならないため、まずはレスポンスを正しく返すことを優先し、進捗通知は余力があれば追加する機能として扱うのが妥当です。
この裁量の広さから分かるのは、クライアント側は「進捗通知が来ない」ことを異常とみなしてはいけないという点です。進捗通知に依存したUI設計をするなら、通知が0件のまま処理が完了するケースを正常系として扱う必要があります。
もう1つ、仕様が明言していない領域として、進捗通知とリクエストのタイムアウトの関係があります。進捗通知が届き続けている間はリクエストがタイムアウトしないという保証は、仕様のどこにも書かれていません。クライアント実装によっては、進捗通知の受信をもってタイムアウトのカウントダウンをリセットする独自ロジックを持つものもありますが、それはMCPの仕様ではなく各SDK・各クライアントの実装判断です。長時間ツールを提供するサーバー側は、進捗通知を送っていればタイムアウトを回避できるとは考えず、別途タイムアウト値そのものの調整や、処理の分割を検討する必要があります。
進捗通知を実装する価値があるツールをどう選ぶか
進捗通知はキャッシュ仕様やページネーション仕様とは性格が異なります。キャッシュとページネーションは「レスポンスの中身をどう構成するか」という応答の形そのものに関わる仕様ですが、進捗通知は応答とは別チャンネルで流れる、いわば処理中の実況です。
この違いは実装の優先順位にも表れます。キャッシュとページネーションは仕様適合のために対応が必須になる領域が広い一方、進捗通知はサーバーの裁量が大きく、「対応しなくても壊れない」機能です。だからこそ、実装する価値があるのは「体感時間が長く、失敗しても影響が小さい」ツールに絞るのが現実的な判断です。大量データの一括インポートや、外部APIへの連続呼び出しを伴うツールは好例です。
逆に、数百ミリ秒で終わる単純なツールにまで律儀に進捗通知を実装するのは、レート制限の実装コストに見合いません。判断に迷ったら「このツールが1秒以上かかることがあるか」を基準にするのが目安になります。1秒未満で終わる処理は、通知が届く前に結果自体が返ってくることが多く、実装の手間に対してユーザー体験の改善が見合わないためです。MCP Inspectorで自作サーバーの動作を確認する際は、notifications/progressが実際に届いているか、progressの値が単調増加しているかを合わせて見ておくと、リリース後のクライアント側の不具合報告を減らせます。
まとめ
MCPの進捗通知は、progressTokenをリクエストの_metaに含めることで有効化される、実装が任意の付加機能です。サーバーは通知を送るかどうか、頻度をどうするかを自由に選べますが、送ると決めた場合はprogress値の単調増加とレート制限、完了後に通知を止めることが必須事項として定められています。2026-07-28リビジョンではsubscriptions/listenへの通知の一本化が進みましたが、進捗通知はリクエストの応答ストリームに留まる例外として明記されています。Claude CodeでMCPサーバーに接続する構成で長時間ツールを扱うなら、まずレスポンスを正しく返す実装を固め、そのうえでレート制限を組み込んでから進捗通知を追加するのが、手戻りの少ない安全な順序です。