メインコンテンツまでスキップ

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 で、それぞれ自己識別することが推奨される。バージョンの不一致は UnsupportedProtocolVersionErrorSEP-2575
server/discoverサーバーが必ず実装する RPC。対応バージョン、ケイパビリティ、識別情報を返す。クライアントは任意で呼ぶ。stdio では後方互換のプローブになるSEP-2575
subscriptions/listenHTTP の 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 以降に公開される最初のリビジョン
SamplingLLM プロバイダーの API を直接利用する2026-07-28 (SEP-2577)同上
Loggingstdio では 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 HTTP2025-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 に移す手順の骨格は、「新しい、厳密にステートレスなルートを、既存のセッション付きのルートと併走させ、機能を移し、セッションがなくなってから旧ルートを撤去する」です。次の流れで進めます。

  1. セッション依存の洗い出し: プロトコルのセッションに依存している箇所を探します (次の「移行チェックリスト」を参照)。依存がなければ、ステートレスな実装へ直接移せます
  2. ステートレスなルートの追加: 旧ルートを残したまま、新しいルートを足します。新しいルートは、各リクエストを _meta と HTTP ヘッダーだけで処理します
  3. 新旧の振り分け: 同じ URL で新旧のクライアントを受けるなら、リクエストの形で振り分けます。_meta を持つリクエストは Modern、initialize で始まるものは Legacy です。Dual-era のサーバーは、同じエンドポイントで両方を同時に提供できます
  4. 依存の置き換え: 次の表のように、セッション依存の機能を、ステートレスな設計で作り直します
  5. クライアントの移行: 新しいルートに、クライアントを順に移します
  6. ドレインと撤去: 旧ルートへのトラフィックを監視し、既存のセッションが期限切れになってから、旧ルートを撤去します
セッション依存の機能ステートレスな設計
MCP セッションに紐づけたデータ明示的な境界 (データベースなど) の後ろに保存し、認証されたサーバー発行のハンドルで参照する
複数ステップのやり取りの状態input_required に、完全性を保護した requestState を載せる。ユーザー、元のメソッドとパラメーター、有効期限に結びつける
サーバーからのプッシュの Elicitation、Sampling、Rootsinput_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、サーバー設定でディレクトリやファイルを渡す
SamplingLLM プロバイダーの API を直接利用する
Loggingstdio では 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 が決める
  • 移行は、ステートレスなルートを既存のセッション付きルートと併走させ、依存を置き換え、セッションが尽きてから旧ルートを撤去する
  • 確認すべき点は、セッション依存、サーバー起点のリクエスト、スタンドアロンのストリーム、再開機能への依存、ヘッダーが中継装置を通るか

関連ドキュメント​

参考資料​