MCPが「ステートレス」になった。2026-07-28仕様で自作サーバーは何を直すべきか
MCP 2026-07-28仕様でinitialize/initializedハンドシェイクとセッションIDが廃止され、プロトコルが要求/応答型のステートレス設計に変わった。Claude Codeの利用者(クライアント側)とMCPサーバーを自作・自己ホストしてる人で、対応の要否がどう分かれるかを一次情報から整理する。
エンジニアのゆとです。
7月28日、MCP(Model Context Protocol)の新しい仕様「2026-07-28」がリリースされた。タイトルにも書いた通り、目玉は「ステートレス化」。今までinitializeしてMcp-Session-Idをやり取りしながら会話みたいに続けてたやり取りが、根本から作り変えられた。
正直、最初にニュースを見たとき「また仕様変更か、自分のMCPサーバー直さなきゃいけないやつだ」と身構えた。でも中身を読んでいくと、影響を受ける人と受けない人がはっきり分かれる話だった。この記事では、その線引きをはっきりさせるところまで書く。
まず結論。あなたは「使う側」か「作る側」か
MCPには大きく2つの立場がある。既存のMCPサーバー(GitHub、Slack、Sentryなどの公式・サードパーティ製)をclaude mcp addでつないで使う「クライアント側」と、自分でMCPサーバーを書いて動かしてる「サーバー側」だ。
先に言っておくと、クライアント側、つまり普段Claude Codeで既存のMCPサーバーをつないで使ってるだけの人には、今回の変更で今すぐやることはほとんどない。プロトコルバージョンのネゴシエーションはクライアントとサーバーの間で自動的に行われる設計になっていて、Claude Code自体のドキュメントにも「2026-07-28」というバージョン文字列を名指しした対応表は今のところ出てきていない。
一方、自分でMCPサーバーを書いて自己ホストしてる人、あるいは社内向けにMCPサーバーを公開してる人には、直接効いてくる話がいくつかある。以前
何が変わったか:セッションという概念そのものが消えた
一次情報を読み込むと、変更の核はここに尽きる。従来のMCPはステートフルな双方向プロトコルだった。クライアントがinitializeを送り、サーバーがinitializedを返し、その後はMcp-Session-Idヘッダで同じ会話の続きだと認識させながらやり取りする。HTTP的に言えば、ずっと同じセッションにぶら下がり続ける設計だった。
2026-07-28仕様では、このinitialize/initializedハンドシェイクとMcp-Session-Idヘッダが両方とも廃止された。代わりに、1つ1つのリクエストが完全に独立している。プロトコルバージョン・クライアントの認証情報・クライアントの機能(capabilities)を、リクエストごとに_metaフィールドで自己申告する形に変わった。
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search
この設計だと、ロードバランサーの背後で複数のサーバーインスタンスがラウンドロビンで動いてても、どのインスタンスにリクエストが飛んでも成立する。今までのステートフル設計だと「セッションが張られたインスタンスに毎回ルーティングし続ける」仕組み(スティッキーセッション)が必要で、これがサーバーレスやエッジ環境へのデプロイを難しくしていた。今回の変更で、MCPサーバーをCloudflare WorkersやLambdaのような環境に素直に乗せられるようになる。
自己ホストでMCPサーバーを動かしてる人がスケーリングで苦労してた部分は、この変更で構造的に楽になる方向だと思う。
セッションが要らないなら、状態はどこに持たせるのか
ここが一番実装に効いてくる部分だと思う。ステートレスにしたからといって「状態を扱えなくなった」わけじゃない。サーバー側がリクエストをまたいで状態を持ちたい場合は、明示的なハンドル(識別子)をツールの戻り値として発行して、モデルがそのハンドルを次の引数として渡す設計にする、という指針が示されている。隠れたセッション状態に依存するより、モデルから見える形で状態を受け渡す設計の方が、挙動が予測しやすいという理屈だ。
これは実際、Claude Codeがサブエージェントやバックグラウンドセッションの結果を会話に戻す設計とも思想が近い。
もう1つ、双方向のやり取りが必要な場面(サーバーからクライアントに追加の入力を求めたいケース)への対応として、MRTR(Multi Round-Trip Requests)という仕組みが入った。サーバーがresultType: "input_required"を返して、クライアントがinputResponsesに回答を添えて元の呼び出しをやり直す。これで旧仕様にあったelicitation/createやsampling/createMessage、roots/listを置き換えている。
認可まわりも地味だけど重要な変更が入ってる
MCPサーバーでOAuth連携をやってる人向けの変更もある。RFC 9207に準拠して、クライアントはトークンを償還する前にissパラメータを検証する必要が出てきた。加えて、Dynamic Client Registration(DCR)が正式に非推奨になり、Client ID Metadata Documents(CIMD)への移行が推奨ルートになった。DCR自体は後方互換のためまだ動くが、将来的に削除される予定として明記されている。
デスクトップアプリやCLIツール向けには、application_typeの設定でlocalhostリダイレクトに対応する仕組みも整理された。これはClaude Code自体のような、ローカルで動くクライアントがOAuth連携するときの認可フローに関わる部分になる。認証情報の使い回しを防ぐ観点も強化されていて、クライアントの認証情報を発行元にひも付けて、複数の認可サーバーをまたいだ再利用ができないようにしている。
secrets管理を絡めてMCPサーバーを運用してる人は、

Tasks・Roots・Samplingは「拡張」に格下げされた
もう1つ構造的な変更として、Tasks(長時間実行するタスクの進捗管理)が実験的なコア機能からio.modelcontextprotocol/tasksという正式な拡張に切り出された。ポーリングベースのtasks/getに加えて新しいtasks/updateが入り、変更通知はsubscriptions/listenストリームに統合されている。Roots・Sampling・Loggingについても、正式にコアからの廃止が予告された(最低12ヶ月のサポート期間は確保される)。
これは「コアプロトコルを軽くして、必要な人だけが拡張を足す」という設計思想の表れだと理解してる。全員が全機能を実装しなくていい代わりに、拡張のバージョニングをちゃんと管理する責任がサーバー実装側に移った形だ。
移行はどのくらい大変か
一次情報では「セッション識別子に依存した実装をしてる開発者にとっては特にコストがかかる」と正直に書かれている。裏を返せば、シンプルなツール呼び出し中心のMCPサーバー(DBに問い合わせるだけ、APIを叩くだけのようなステートレスに近い実装)を書いてた人は、影響がかなり小さい。
SDK側の対応も早い。TypeScript・Python・Go・C#のTier 1 SDKはすでに新仕様に対応済みで、移行ノートも用意されている。廃止サイクルも「最低12ヶ月」という方針が明文化されているので、いきなり全部書き直しを迫られる話ではない。
自分がやったこと
正直、今回は「今すぐ手を動かす」ほどの変更ではなかった。個人用に立ててるMCPサーバーは元々ステートレスに近い作りだったので、実質的な影響はゼロに近い。ただ、OAuth連携してる別の社内向けサーバーについては、DCRから将来的にCIMDへの移行を見据えて、依存してるSDKのバージョンだけ確認しておいた。
MCPサーバーを「使うだけ」の人は今回は静観でいい。自分で書いて公開してる人、特にセッション状態に依存した実装をしてる人は、SDKのアップデートノートに目を通しておくくらいのタイミングだと思う。仕様のPDFを全部読む必要はないけど、自分のサーバーが「セッションIDに依存してるかどうか」だけは今のうちに確認しておいた方がいい。


