MCP最新仕様 2026-07-28 の変更点と移行
2026-07-28 リビジョンの変更点を整理し、既存の MCP サーバー・クライアントを移行する際の判断材料をまとめます。ワイヤーフォーマットの詳細は MCPプロトコル基礎、トランスポートの詳細は トランスポート、全体像は MCP入門 - Model Context Protocolとは を参照してください。
1. このドキュメントで扱うこと
- 主要変更 (Major)
- 軽微な変更 (Minor)
- 非推奨になった機能
- フィーチャーライフサイクル
- 移行の進め方
- 互換性の確認
- 移行チェックリスト
主要変更 (Major)
変更履歴 (changelog) が、主要な変更として挙げているのは次の 9 件です。
| 変更 | 内容 | SEP |
|---|---|---|
| セッションの廃止 | プロトコルレベルのセッションと Mcp-Session-Id ヘッダーを、Streamable HTTP から削除。tools/list、resources/list、prompts/list は接続ごとに変化しない。複数の呼び出しにまたがる状態は、サーバーが発行するハンドルを、通常のツール引数として渡す | SEP-2567 |
| ステートレス化 | initialize / notifications/initialized を削除。すべてのリクエストが、_meta にバージョンとケイパビリティを載せる。クライアントは clientInfo、サーバーは結果の serverInfo で、それぞれ自己識別することが推奨される。バージョンの不一致は UnsupportedProtocolVersionError | SEP-2575 |
server/discover | サーバーが必ず実装する RPC。対応バージョン、ケイパビリティ、識別情報を返す。クライアントは任意で呼ぶ。stdio では後方互換のプローブになる | SEP-2575 |
subscriptions/listen | HTTP の GET エンドポイントと、resources/subscribe / resources/unsubscribe を置き換える。長く開いた POST 応答ストリームで、購読した種類の通知だけを受け取る | SEP-2575 |
ping などの削除 | ping、logging/setLevel、notifications/roots/list_changed を削除。ログレベルはリクエストごとの _meta の logLevel で指定する | SEP-2575 |
| Tasks の拡張化 | 実験的な Tasks をコアから外し、公式の拡張 io.modelcontextprotocol/tasks に移す。ブロッキングの tasks/result を、tasks/get のポーリングに置き換え、クライアントからサーバーへの入力用に tasks/update を追加。tasks/list は削除。サーバーはリクエストごとの opt-in なしに、タスクのハンドルを返せる | SEP-2663 |
| Multi Round-Trip Requests (MRTR) | サーバー起点のリクエスト (roots/list、sampling/createMessage、elicitation/create) を置き換える。サーバーは resultType: "input_required" の InputRequiredResult を返し、クライアントは inputResponses を付けて元のリクエストを再試行する | SEP-2322 |
resultType | すべての結果に必須。"complete" か "input_required"。旧版のサーバーが省略した場合は "complete" として扱う | SEP-2322 |
| SSE 再開の廃止 | Last-Event-ID と SSE のイベント ID による再開と再送を、Streamable HTTP から削除。ストリームが切れると処理中のリクエストは失われ、クライアントは新しいリクエスト ID で再発行する | SEP-2575 |
軽微な変更 (Minor)
extensionsフィールド:ClientCapabilitiesとServerCapabilitiesに追加され、コアにないオプションの拡張を交渉できる- OpenTelemetry のトレースコンテキスト:
_metaのtraceparent、tracestate、baggageの規約を文書化 (SEP-414) tools/listの順序: サーバーは決定的な順序で返すことが推奨される。クライアント側のキャッシュと、LLM のプロンプトキャッシュの命中率のためMcp-Method/Mcp-Nameヘッダー: Streamable HTTP の POST に必須。ツール引数をヘッダーにするx-mcp-headerも追加 (SEP-2243)ttlMs/cacheScope:tools/list、prompts/list、resources/list、resources/read、resources/templates/listの結果に必須。ttlMsは新鮮と見なせるミリ秒数、cacheScope(publicかprivate) は共有の中継装置がキャッシュしてよいかの指定 (SEP-2549)- リソース未検出のコード:
-32002から-32602へ issパラメータの検証: 認可サーバーは認可レスポンスにissを含めることが推奨され (RFC 9207)、クライアントは、存在するissを、記録した発行者と照合してから認可コードを交換しなければならない (SEP-2468)application_type: Dynamic Client Registration で、適切な値の指定が必須に (SEP-837)- 認証情報の発行者への紐づけ: クライアントは永続化した認証情報を発行者の識別子をキーに管理し、別の認可サーバーには再利用せず、認可サーバーが変わったら再登録する (SEP-2352)
- JSON Schema:
inputSchemaとoutputSchemaで JSON Schema 2020-12 の任意のキーワードを許可し、structuredContentは任意の JSON 値に。$refの解決の要件と、合成キーワードの資源の上限を追加 (SEP-2106) - URL 形式 Elicitation:
notifications/elicitation/completeとelicitationIdを削除。MRTR では、クライアントが元のリクエストを再試行して結果を知るため。相関が必要なら、サーバーがrequestStateに識別子を入れる - エラーコードの割り当て方針:
-32000〜-32019は実装定義のまま、-32020〜-32099を仕様の予約に。ドラフトで導入されたコードを、HeaderMismatchは-32020、MissingRequiredClientCapabilityは-32021、UnsupportedProtocolVersionは-32022に振り直した
認可に関する変更の詳細は MCPの認可 - OAuth 2.1とメタデータ探索 と MCPの認可拡張とエンタープライズ導入 を参照してください。
非推奨になった機能
非推奨の機能は、仕様に残りますが、削除が予定されています。新しい実装は採用しないでください。
| 非推奨の機能 | 移行先 | 非推奨の導入 | 最短の削除時期 |
|---|---|---|---|
| Roots | ツール引数、リソース URI、サーバー設定でディレクトリやファイルを渡す | 2026-07-28 (SEP-2577) | 2027-07-28 以降に公開される最初のリビジョン |
| Sampling | LLM プロバイダーの API を直接利用する | 2026-07-28 (SEP-2577) | 同上 |
| Logging | stdio では stderr へ出力、または OpenTelemetry を使う | 2026-07-28 (SEP-2577) | 同上 |
| Dynamic Client Registration (RFC 7591) | Client ID Metadata Documents (DCR は、これに対応しない認可サーバーとの互換用に残る) | 2026-07-28 (PR #2858) | 2027-07-28 以降に公開される最初のリビジョン |
includeContext の "thisServer" / "allServers" | フィールドを省略するか "none" | 2025-11-25 (SEP-2596 で再分類) | Sampling の削除と同時か、それより前 |
| HTTP+SSE トランスポート | Streamable HTTP | 2025-03-26 (SEP-2596 で再分類) | レジストリでは、SEP-2596 が Final になってから 3 か月後 |
非推奨の機能は、移行期間のあいだは完全に動作します。ただし、Roots / Sampling / Logging をこれから実装する理由はありません。Roots / Sampling の入力を MRTR で受ける仕組みは ElicitationとMulti Round-Trip Requests で扱います。
フィーチャーライフサイクル
SEP-2596 で、仕様の個々の機能の寿命を管理する方針が採用されました。機能は、次の 3 つの状態のどれかにあります。
| 状態 | 意味 | 実装者への期待 |
|---|---|---|
| Active | 現行 (Current) のリビジョンに含まれる機能 | 仕様の要件に従って実装する |
| Deprecated | 仕様に残るが、削除が予定されている。移行先が文書化されている | 新しい実装は採用しない。既存の実装は、最短の削除時期までに移行する |
| Removed | 次の Current リビジョンから取り除かれる。最後に載っていた Final のリビジョンには残る | 次のリビジョンを対象にする実装は、その機能に依存してはいけない |
方針の要点は次のとおりです。
- 非推奨にするには SEP が必要で、根拠、移行先、最低 12 か月の非推奨期間を示す。期間は、非推奨が初めて示されたリビジョンの公開から数える
- 非推奨の機能は、スキーマの
@deprecated、仕様本文の注意書き、changelog の「Deprecated」の項、非推奨機能のレジストリ に記録される - 削除は、期間が過ぎたあと、リリースの準備の中で Core Maintainers が決める。最短の削除時期は「削除してよくなる時期」であり、削除の約束ではない。非推奨のまま、はるかに長く残ることもある
- 活発なセキュリティリスクがあるときは、12 か月を短縮できる。ただし、非推奨から最短の削除まで 90 日は確保される
- すでに非推奨と書かれていた HTTP+SSE と
includeContextは、SEP-2596 の移行措置で Deprecated に分類された。12 か月は適用し直さず、HTTP+SSE の最短の削除は SEP-2596 が Final になってから 3 か月後、includeContextの 2 つの値は Sampling の削除に従い、遅くとも Sampling と同時に削除される - 非推奨は、SEP で Active に戻せる
- SDK は、仕様から削除されても、機能を直ちに落とす義務はない。SDK 自身のリビジョン対応方針に従う。Tier 1 の SDK は、非推奨になった機能の API に、言語の標準の仕組みで非推奨の印を付ける
2026-07-28 の時点で、Removed のものはまだありません。
移行の進め方
既存のサーバーを 2026-07-28 に移す手順の骨格は、「新しい、厳密にステートレスなルートを、既存のセッション付きのルートと併走させ、機能を移し、セッションがなくなってから旧ルートを撤去する」です。次の流れで進めます。
- セッション依存の洗い出し: プロトコルのセッションに依存している箇所を探します (次の「移行チェックリスト」を参照)。依存がなければ、ステートレスな実装へ直接移せます
- ステートレスなルートの追加: 旧ルートを残したまま、新しいルートを足します。新しいルートは、各リクエストを
_metaと HTTP ヘッダーだけで処理します - 新旧の振り分け: 同じ URL で新旧のクライアントを受けるなら、リクエストの形で振り分けます。
_metaを持つリクエストは Modern、initializeで始まるものは Legacy です。Dual-era のサーバーは、同じエンドポイントで両方を同時に提供できます - 依存の置き換え: 次の表のように、セッション依存の機能を、ステートレスな設計で作り直します
- クライアントの移行: 新しいルートに、クライアントを順に移します
- ドレインと撤去: 旧ルートへのトラフィックを監視し、既存のセッションが期限切れになってから、旧ルートを撤去します
| セッション依存の機能 | ステートレスな設計 |
|---|---|
| MCP セッションに紐づけたデータ | 明示的な境界 (データベースなど) の後ろに保存し、認証されたサーバー発行のハンドルで参照する |
| 複数ステップのやり取りの状態 | input_required に、完全性を保護した requestState を載せる。ユーザー、元のメソッドとパラメーター、有効期限に結びつける |
| サーバーからのプッシュの Elicitation、Sampling、Roots | input_required を返し、クライアントが応答を付けて再試行する |
| 単独の一覧変更ストリーム (GET) | subscriptions/listen で配信する。終わったらクライアントが開き直す |
| セッションの再生、トランスポートの復旧 | 各リクエストを単独で復旧可能にし、進捗はアプリケーションの保存先に残す |
この表と手順は、Cloudflare Agents の SDK v2 移行ガイドが示す戦略に基づく整理です。SDK ごとにルーティングの API は異なるため、実際の手順は、使っている SDK の移行ガイドで確認してください。requestState はクライアントを経由する値なので、信頼できない入力として扱い、署名と短い有効期限で検証します。
互換性の確認
移行の前後に、次の組み合わせを実際に試します。世代ごとの結果の全体像は MCPプロトコル基礎 の互換性の表を参照してください。
- Modern のクライアント × 自分のサーバー:
server/discoverと通常のリクエストが通るか。対応しないバージョンを送ったとき、supportedの一覧つきのUnsupportedProtocolVersionError(HTTP は 400) が返るか - Legacy のクライアント × 自分のサーバー: 旧クライアントを残すなら、同じエンドポイントで
initializeに応答できるか。Modern だけのサーバーなら、initializeへのエラーに、対応バージョンを含めているか - Modern のクライアント × 旧サーバー: stdio では、
server/discoverのプローブが失敗やタイムアウトで終わり、initializeに切り替わるか。HTTP では、400 のボディを見て切り替えるか - 旧クライアントが送る
Mcp-Session-Id、Last-Event-ID、GET、DELETE に、Modern のサーバーが、無視または405で応じるか - プロキシ、ゲートウェイ、WAF を通っても、
MCP-Protocol-Version、Mcp-Method、Mcp-Name、Mcp-Param-*が欠けずに届くか - 使っている SDK の移行ガイドとリリースノートを確認する。SDK のバージョンは固定し、非推奨の API と削除の予定を把握する
移行チェックリスト
セッションやサーバー起点の機能への依存を、次の観点で洗い出します。
- プロトコルのセッション:
Mcp-Session-Idを発行している、またはセッションごとにメモリや保存先へデータを持っている - サーバー起点のリクエスト:
elicitation/create、sampling/createMessage、roots/listを、サーバーから直接送っている - スタンドアロンのストリーム: GET エンドポイントで通知を配信している
- 再開機能:
Last-Event-IDやイベントストアによる再送に依存している initializeの応答に依存した処理: 初期化時のケイパビリティの保存、バージョンの記録などping、logging/setLevel、notifications/roots/list_changedの送受信- 一覧のキャッシュ:
ttlMs/cacheScopeを返していない*/listの結果 - 非推奨の機能: Roots、Sampling、Logging、HTTP+SSE、Dynamic Client Registration を、新しく使っていないか
- 認可:
issの検証、認証情報の発行者への紐づけ、application_type
2. 非推奨機能と移行先
| 非推奨の機能 | 移行先 |
|---|---|
| Roots | ツール引数、リソース URI、サーバー設定でディレクトリやファイルを渡す |
| Sampling | LLM プロバイダーの API を直接利用する |
| Logging | stdio では stderr へ出力、または OpenTelemetry を使う |
| HTTP+SSE トランスポート | Streamable HTTP |
| Dynamic Client Registration (RFC 7591) | Client ID Metadata Documents (互換用に DCR は残存) |
3. 開発者がつまずきやすいポイント
「非推奨」と「削除」の違い
Roots、Sampling、Logging は、2026-07-28 では非推奨で、削除されていません。動作し、SDK の API も残ります。一方、ping、logging/setLevel、notifications/roots/list_changed、resources/subscribe、initialize は、すでに削除されています。この違いを取り違え、削除済みのメソッドを非推奨と思って使い続けると、2026-07-28 のサーバーに拒否されます。
最短の削除時期を期限と読む
「2027-07-28 以降」は、削除してよくなる時期です。削除が決まった日ではありません。ただし、移行は期間の終わりに行わず、新しい実装では最初から使わない方針が安全です。
ログの出し方を変え忘れる
logging/setLevel は削除され、ログレベルはリクエストごとの _meta で指定します。サーバーは、logLevel を持たないリクエストに、notifications/message を出してはいけません。stdio のサーバーのログは stderr へ出します (stdout はプロトコル専用です。ローカルMCPサーバーの安全な運用 を参照)。
切断したストリームを再開しようとする
Last-Event-ID による再開はなくなりました。ストリームが切れたら、処理中のリクエストは失われます。クライアントは、同じ内容を新しいリクエスト ID で再発行します。したがって、ツールは、再実行されても安全 (冪等) になるように設計します。購読 (subscriptions/listen) も、切れたらクライアントが開き直し、欠落した変更は再取得で補います。
セッション前提の機能を MRTR に置き換えるとき
サーバーからの Elicitation を input_required に置き換えると、クライアントが元のリクエストを再試行します。再試行のあいだ、サーバーのメモリに状態は残りません。途中の状態は requestState に載せ、改ざんと再利用に備えて検証します。
x-mcp-header と Mcp-Param-* の見落とし
プロキシやゲートウェイが、未知のヘッダーを落とす設定になっていると、Mcp-Param-* が欠けて、HeaderMismatch (-32020) で拒否されます。ヘッダーは、本文の複製であって、本文が正です。
新旧の資料の混在
検索で見つかる記事、SDK のサンプル、AI のコード生成が、2025-11-25 以前の知識で書かれていることがあります。Mcp-Session-Id、initialize、GET のストリームが出てきたら、旧版の資料と考え、仕様の版を確認してください。
4. コード例
新旧のクライアントを、同じエンドポイントで受ける (Go)
リクエストの本文を見て、_meta にバージョンがあれば Modern、initialize なら Legacy の処理に振り分ける骨格です。handleModern、handleLegacy は、アプリケーションが実装する関数です。この例は、振り分けの考え方を示すもので、SDK の API ではありません。
package main
import (
"bytes"
"encoding/json"
"io"
"net/http"
)
type rpcRequest struct {
Method string `json:"method"`
Params struct {
Meta map[string]json.RawMessage `json:"_meta"`
} `json:"params"`
}
func isModern(r *rpcRequest) bool {
_, ok := r.Params.Meta["io.modelcontextprotocol/protocolVersion"]
return ok
}
func router(modern, legacy http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// GET / DELETE は、Modern のサーバーでは 405
if r.Method != http.MethodPost {
w.Header().Set("Allow", "POST")
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
body, err := io.ReadAll(http.MaxBytesReader(w, r.Body, 1<<20))
if err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
r.Body = io.NopCloser(bytes.NewReader(body)) // 後続のハンドラーが再び読めるようにする
var req rpcRequest
if err := json.Unmarshal(body, &req); err != nil {
http.Error(w, "bad request", http.StatusBadRequest)
return
}
switch {
case isModern(&req):
modern.ServeHTTP(w, r) // ステートレスに処理する
case req.Method == "initialize":
legacy.ServeHTTP(w, r) // 旧セッションの処理 (ドレイン完了まで残す)
default:
// Modern でも initialize でもない。Mcp-Session-Id 付きの旧クライアントの後続リクエストなど
legacy.ServeHTTP(w, r)
}
})
}
非推奨の Logging から stderr / OpenTelemetry への置き換え
stdio のサーバーは、stdout を汚さないよう、ログを stderr に出します。
import (
"log/slog"
"os"
)
// stdout はプロトコル専用。ログは stderr へ
var logger = slog.New(slog.NewJSONHandler(os.Stderr, nil))
func main() {
logger.Info("server started", "transport", "stdio")
// ...
}
リクエストごとのログレベルとトレースコンテキスト
logLevel で、リクエストごとにログの量を指定し、traceparent でトレースを引き継ぎます。
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "get_weather",
"arguments": { "location": "Tokyo" },
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {},
"io.modelcontextprotocol/logLevel": "warning",
"traceparent": "00-0af7651916cd43dd8448eb211c80319c-00f067aa0ba902b7-01"
}
}
}
移行後の動作確認 (curl)
Modern のリクエストが通ること、対応しないバージョンが UnsupportedProtocolVersionError で返ることを確認します。URL は、自分のサーバーのものに置き換えます。
curl -sS -X POST https://example.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 2026-07-28' \
-H 'Mcp-Method: server/discover' \
-d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'
# 未知のバージョン。400 と UnsupportedProtocolVersionError (-32022) を期待する
curl -sS -i -X POST https://example.com/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'MCP-Protocol-Version: 1900-01-01' \
-H 'Mcp-Method: server/discover' \
-d '{"jsonrpc":"2.0","id":2,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"1900-01-01","io.modelcontextprotocol/clientCapabilities":{}}}}'
5. まとめ
- 2026-07-28 の中心は、ステートレス化。セッション、
initialize、GET のストリーム、SSE の再開を廃止し、各リクエストが自己完結する - サーバー起点のリクエストは MRTR に、実験的な Tasks は拡張に、通知は
subscriptions/listenに移った - Roots、Sampling、Logging、HTTP+SSE、Dynamic Client Registration は非推奨。削除の最短時期は、Roots / Sampling / Logging / DCR が 2027-07-28 以降
- 機能は、Active、Deprecated、Removed の順に進み、新たに非推奨にする機能は、削除までに最低 12 か月 (HTTP+SSE は移行措置で 3 か月後)。削除の時期は Core Maintainers が決める
- 移行は、ステートレスなルートを既存のセッション付きルートと併走させ、依存を置き換え、セッションが尽きてから旧ルートを撤去する
- 確認すべき点は、セッション依存、サーバー起点のリクエスト、スタンドアロンのストリーム、再開機能への依存、ヘッダーが中継装置を通るか
関連ドキュメント
- MCP入門 - Model Context Protocolとは
- MCPプロトコル基礎 - JSON-RPCとステートレス設計
- トランスポート - stdioとStreamable HTTP
- ElicitationとMulti Round-Trip Requests
- MCPの認可 - OAuth 2.1とメタデータ探索