28 Temmuz 2026'da yayınlanan MCP 2026-07-28 spesifikasyonu, protokolün temel çalışma modelini değiştirdi: artık her istek kendi başına ayakta duruyor ve sunucu tarafında oturum belleği tutmana gerek kalmıyor. Kendi MCP sunucunu işletiyorsan bu MCP stateless geçiş rehberi sana tam olarak neyin kalktığını, neyin geldiğini ve mevcut sunucunu kırmadan nasıl taşıyacağını adım adım gösteriyor. Rehber, spesifikasyonun resmi blog duyurusuna ve /specification/2026-07-28 sayfalarına dayanıyor.
💡 Pro Tip: Göçe başlamadan önce server/discover RPC'sini implemente et — istemcinin onu çağırması opsiyonel olsa da sunucu tarafında bu RPC'nin bulunması spesifikasyonun zorunlu kıldığı bir gereklilik, aksi halde era-tespiti yapan istemciler seni "eski" sanıp legacy moduna düşer.İçindekiler
- Neden stateless'a geçildi (yatay ölçekleme, LB)
- Legacy ve modern model arasındaki fark
- Kalkanlar: Mcp-Session-Id ve initialize/initialized
- _meta ile per-request capability negotiation
- server/discover: zorunlu implementasyon, opsiyonel çağrı
- Adım adım göç: stdio taşıma
- Adım adım göç: Streamable HTTP taşıma
- Eski SSE transport'tan çıkış
- Geriye dönük uyum ve çift-mod çalıştırma
- Dispatcher'ı çift-mod çalıştıracak şekilde kurmak
- Göç sonrası doğrulama kontrol listesi
- SSS
- MCP 2026-07-28 spesifikasyonunda tam olarak ne değişti?
- Mcp-Session-Id header'ı neden kaldırıldı, yerine ne geldi?
- Mevcut MCP sunucumu stateless spec'e nasıl taşırım?
- server/discover zorunlu mu, initialize handshake'i silmeli miyim?
- DCR'dan CIMD'ye geçişi ne zaman yapmalıyım?
- Legacy HTTP+SSE sunucumu ne zamana kadar çalıştırabilirim?
- Sonuç
- Kaynaklar
Neden stateless'a geçildi (yatay ölçekleme, LB)
Eski MCP, bağlantı bazlı bir initialize/initialized el sıkışması gerektiriyordu: istemci bir kez bağlanır, sunucu o bağlantı için oturum durumu (capability listesi, protokol sürümü, kimlik) tutardı. Bu model, sunucunun aynı istemciyle konuşan her isteğin aynı process'e düşmesini zorunlu kılıyordu — yani sticky session veya paylaşımlı bir oturum deposu (Redis, sunucu-içi bellek senkronu) gerekiyordu.
MCP'nin resmi blog duyurusu bu değişimi net tarif ediyor: "MCP is transforming from a bidirectional stateful protocol into a request/response stateless protocol." Artık her istek, kendi protokol sürümünü ve client capability'lerini _meta alanında taşıyor; bu sayede "Any request can now land on any server instance behind a plain round-robin load balancer without needing shared storage." Pratikte bu, Kubernetes'te yatay ölçeklenen bir MCP sunucusu için sticky-session ingress kuralı yazmana artık gerek kalmadığı anlamına geliyor.
Sunucu tarafında gerçekten kalıcı bir duruma ihtiyacın varsa (örneğin bir alışveriş sepeti veya uzun süren bir iş kimliği), spesifikasyon açık bir çözüm öneriyor: tool'un ürettiği bir "handle" değerini modele argüman olarak geri ver, model bunu sonraki çağrılarda parametre olarak gönderir. Durum artık transport'ta değil, veri katmanında açıkça taşınıyor.
Legacy ve modern model arasındaki fark
Boyut | Legacy (2025-11-25 ve öncesi) | Modern (2026-07-28+) |
|---|---|---|
Bağlantı kurulumu | initialize/initialized el sıkışması | Yok — her istek bağımsız |
Kimlik/versiyon taşıma | Bağlantı-scoped oturum belleği | _meta alanında per-request |
Oturum header'ı | Mcp-Session-Id | Kaldırıldı |
Ölçekleme | Sticky routing / paylaşımlı depo gerekir | Düz round-robin LB yeterli |
Sunucu-durum modeli | Örtük (transport-seviyesi) | Açık handle (tool parametresi) |
Kalkanlar: Mcp-Session-Id ve initialize/initialized
Bu ikisi uzun süredir her MCP bağlantısının önünde duruyordu: initialize el sıkışması 2024-11-05 revizyonundan, Mcp-Session-Id header'ı ise Streamable HTTP'nin geldiği 2025-03-26 revizyonundan beri. Resmi duyuru ikisini birden emekliye ayırdığını yazıyor: "we've officially retired the initialize/initialized exchange along with the Mcp-Session-Id header." Kaldırılan öğeler:
Mcp-Session-Idheader'ı: Streamable HTTP transport'ta artık gönderilmiyor, sunucunun bunu beklemesi de gerekmiyor.initialize/initializedel sıkışması: Bağlantı kurulumunda değişim artık yok; sunucu ilk isteği aldığı anda_metaüzerinden protokol sürümünü öğreniyor.
Yeni bir sunucu yazıyorsan bu ikisini hiç implemente etme. Mevcut bir sunucun varsa bir sonraki bölümdeki göç adımlarını izle, ama şuna dikkat et: bu ikisi deprecated edilmedi, doğrudan kaldırıldı. Changelog'un ilk iki "Major changes" maddesi "Remove protocol-level sessions and the Mcp-Session-Id header" (SEP-2567) ve "remove the initialize/notifications/initialized handshake" (SEP-2575) diyor; deprecated özellikler registry'sinde de bu ikisi yok. Yani spesifikasyonun tanıdığı bir geçiş penceresi yok — legacy akışı ne kadar süre ayakta tutacağın kendi istemci filonun geçiş takvimine bağlı.
_meta ile per-request capability negotiation
Her JSON-RPC isteği artık kendi kimliğini taşıyor. Resmi duyuru örnek bir isteğin header katmanını şöyle gösteriyor:
http
1POST /mcp HTTP/1.12MCP-Protocol-Version: 2026-07-283Mcp-Method: tools/call4Mcp-Name: searchDuyurudaki blok bir de JSON gövdesi içeriyor; burada yalnız header katmanı gösteriliyor. Header seviyesinde protokol sürümü ve metot/isim bilgisi taşınırken, spesifikasyona göre gövde tarafındaki _meta alanı da her istekte protokol sürümünü, client kimliğini ve client capability'lerini birlikte taşıyor — resmi duyurunun ifadesiyle "Each request now travels on its own, carrying its protocol version, client identity, and client capabilities in _meta." Yani sunucu artık bir kez bağlantı açılışında öğrendiği bu bilgileri her isteğin gövdesinden okumak zorunda.
Spesifikasyon bu alanları "Per-request protocol fields" etiketiyle normatif olarak tanımlıyor; anahtar adlarını ve zorunluluk durumlarını birebir bilmen gerekiyor:
_meta anahtarı | Tip | Zorunlu |
|---|---|---|
io.modelcontextprotocol/protocolVersion | string | Evet |
io.modelcontextprotocol/clientInfo | Implementation | Hayır |
io.modelcontextprotocol/clientCapabilities | ClientCapabilities | Evet |
io.modelcontextprotocol/logLevel | LoggingLevel | Hayır |
Zorunlu alanlardan biri eksikse spesifikasyon net: istek malformed sayılır, sunucu onu -32602 (Invalid params) ile reddetmek zorundadır ve HTTP üzerinde yanıt durumu 400 Bad Request olmak zorundadır. Bu kuralı aklında tut, çünkü aşağıdaki HTTP göç bölümündeki era-tespitini doğrudan etkiliyor.
Extension negotiation da aynı mantıkla çalışıyor: capability'ler capabilities.extensions altında bir map olarak sunuluyor ve her extension kimliği kendi ayar objesini taşıyor; kimlikler io.modelcontextprotocol/tasks veya io.modelcontextprotocol/ui gibi ters-domain isimlendirme kuralına uyuyor. Sunucu tarafında yapman gereken, artık bağlantı açılışında değil her istekte bu alanları okuyacak şekilde handler'ını yeniden yazmak.
server/discover: zorunlu implementasyon, opsiyonel çağrı
Bu bölümde net olmak önemli çünkü kolayca yanlış anlaşılıyor: `server/discover` RPC'sinin sunucu tarafında implemente edilmesi zorunlu, opsiyonel olan tek şey istemcinin bu RPC'yi her istekten önce çağırıp çağırmaması. Spesifikasyonun değişiklik listesi (changelog) şöyle diyor: sunucular bu RPC'yi implemente etmek zorunda ("servers MUST implement this RPC"), istemciler ise onu herhangi bir başka istekten önce çağırabilir ("Clients MAY call it before any other request").
Sunucun desteklemediği bir protokol sürümü istendiğinde davranış da net: sunucu UnsupportedProtocolVersionError döndürmeli ve desteklediği sürüm listesini bildirmeli. Bu, hem istemcinin era-tespiti yapmasını hem de gelecekteki sürüm geçişlerinde yumuşak bir düşüş sağlamasını mümkün kılıyor.
server/discover'ı, mevcut bir sunucuyu göç ederken bir prob noktası olarak da kullanabilirsin: istemci tarafı bu RPC'yi çağırıp yanıt alıyorsa sunucunun modern (2026-07-28+) olduğunu, tanımadığı bir hatayla karşılaşıyorsa legacy olduğunu anlar. Bir sonraki bölümde bu prob mantığını stdio ve Streamable HTTP için ayrı ayrı göreceksin.
Adım adım göç: stdio taşıma
stdio transport'ta MCP genelde process ömrü boyunca tek bir istemciyle konuşur, bu yüzden göç görece basit. Ama spec açıkça uyarıyor: stdio process'ini oturum sayma — aynı transport üzerinde ilgisiz istekler araya girebilir, process kimliği konuşma sürekliliğinin yerine geçmez. Spesifikasyonun önerdiği prob mantığı şöyle: "probe with server/discover and fall back on any error that is not a recognized modern error." Yani istemci tarafı önce server/discover'ı çağırır; tanınmayan/beklenmedik bir hata dönerse sunucunun legacy olduğunu varsayıp eski initialize akışına düşer.
bash
1# stdio üzerinde era-tespiti (kavramsal akış)2# server/discover gövde parametresi almaz ama zorunlu _meta alanlarından muaf değildir.3echo '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}' | ./mcp-server4# Modern sunucu: geçerli discover yanıtı döner5# Legacy sunucu: tanınmayan-metot hatası döner -> istemci initialize'a düşerSunucu tarafında yapman gereken üç şey: (1) server/discover handler'ını ekle, (2) her JSON-RPC isteğinde _meta alanını okuyacak şekilde dispatcher'ını güncelle, (3) initialize handler'ını hemen silme — spesifikasyon bu akışı kaldırdığı için sana bir geçiş penceresi tanımıyor, o yüzden ikisini ne kadar paralel çalıştıracağına kendi istemci filonun geçiş takvimine bakarak karar ver.
Client cache kuralı da burada devreye giriyor: istemciler era tespitinin sonucunu stdio'da sunucu process'inin ömrü boyunca önbelleğe almalı, her istekte yeniden prob etmemeli.
Adım adım göç: Streamable HTTP taşıma
HTTP tarafında birden fazla istemci aynı sunucuya farklı origin'lerden bağlanabildiği için prob mantığı biraz farklı: "attempt a modern request and inspect the body of a 400 Bad Request before falling back." İstemci doğrudan modern bir istek dener; sunucu bunu tanımıyorsa döndürdüğü 400 Bad Request gövdesinin içeriğine bakarak legacy olduğuna karar verir. Gövdeye bakma zorunluluğunun sebebi bir önceki bölümdeki kural: modern bir sunucu da zorunlu _meta alanı eksik bir istekte 400 döndürmek zorunda olduğu için durum kodu tek başına era'yı söylemez.
http
1POST /mcp HTTP/1.12MCP-Protocol-Version: 2026-07-283Mcp-Method: tools/call4Mcp-Name: search5Content-Type: application/json6 7{"jsonrpc":"2.0","id":7,"method":"tools/call","params":{"name":"search","_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}Sunucu tarafında dikkat etmen gereken zorunlu değişiklik: Streamable HTTP istekleri artık Mcp-Method ve Mcp-Name header'larını taşımak zorunda (SEP-2243). Bu, bir gateway veya rate-limiter'ın JSON gövdesini parse etmeden route/limit kararı verebilmesini sağlıyor — nginx veya benzeri bir reverse proxy önünde çalışıyorsan, bu iki header'ı loglama ve rate-limit kurallarına dahil etmelisin.
Era tespiti burada origin bazında önbelleğe alınmalı (stdio'daki process-ömrü kuralının HTTP karşılığı), gerekirse restart sonrası da kalıcı tutulabilir.
Eski SSE transport'tan çıkış
Legacy HTTP+SSE transport da bu sürümde resmen deprecated ilan edildi — "The legacy HTTP+SSE transport is also considered to be officially deprecated, with a year-long offramp." Takvimini kurarken bu cümlenin tek başına yetmediğini bil: normatif kayıt olan deprecated özellikler registry'si aynı transport için en erken kaldırma tarihini "Three months after SEP-2596 reaches Final" olarak veriyor ve kendini "per-feature deprecation notices and changelog entries, which are the normative records" ile tutarlı türetilmiş bir görünüm olarak tanımlıyor. SEP-2596'nın kendisi `final` etiketiyle 18 Mayıs 2026'da birleştirildi; üç aylık pencere buna göre Ağustos 2026 ortasında doluyor. Yani elinde hâlâ SSE tabanlı bir MCP sunucu implementasyonu varsa planını "bir yılım var" varsayımına değil registry satırına dayandır, ve yeni geliştirmeyi buraya yapma.
Bununla ilişkili ikinci kırılma: sunucu-başlatımlı istek deseni yalnız legacy SSE'de değil, Streamable HTTP'de de tamamen kalktı — sunucu-başlatımlı elicitation/create, sampling/createMessage ve roots/list çağrılarının yerini artık her transport'ta Multi Round-Trip Requests (MRTR, SEP-2322) alıyor. MRTR akışında sunucu ek girdiye ihtiyaç duyduğunda resultType: "input_required" taşıyan bir InputRequiredResult döner. Bu sonucun iki alanı var ve şekilleri kolayca yanlış hatırlanıyor: inputRequests bir dizi değil, anahtarları sunucunun atadığı string kimlikler olan bir map; değerleri ise ElicitRequest, CreateMessageRequest veya ListRootsRequest olmak zorunda, yani {method, params} biçiminde tam birer istek objesi. İkinci alan requestState, yalnızca sunucu için anlamlı opak bir string; istemcinin içeriğini incelemesi, ayrıştırması veya değiştirmesi yasak. Sunucu her InputRequiredResult yanıtında bu ikisinden en az birini göndermek zorunda — akışı gerçekten stateless yapan da requestState, çünkü sunucu ihtiyaç duyduğu bağlamı bu alana kodlayıp istemciye emanet ediyor, böylece retry başka bir örneğe düşse bile bağlam kaybolmuyor:
json
1{2 "jsonrpc": "2.0",3 "id": 1,4 "result": {5 "resultType": "input_required",6 "inputRequests": {7 "github_login": {8 "method": "elicitation/create",9 "params": {10 "mode": "form",11 "message": "Please provide your GitHub username",12 "requestedSchema": {13 "type": "object",14 "properties": { "name": { "type": "string" } },15 "required": ["name"]16 }17 }18 }19 },20 "requestState": "AEAD-protected blob"21 }22}İstemci orijinal isteği yeni bir JSON-RPC `id` ile tekrarlar, requestState'i birebir geri gönderir ve topladığı cevapları inputRequests ile aynı anahtarlar üzerinden inputResponses map'inde iletir:
json
1{2 "github_login": {3 "action": "accept",4 "content": { "name": "octocat" }5 }6}Sunucu tarafında requestState'i saldırgan-kontrollü girdi kabul etmen gerekiyor: yetkilendirmeyi, kaynak erişimini veya iş mantığını etkiliyorsa bütünlüğünü korumalı (HMAC ya da AEAD) ve doğrulamayı geçemeyen state'i reddetmelisin. Geriye dönük uyum notu: resultType alanı olmayan eski sunucu yanıtlarında istemci bunu otomatik olarak "complete" saymalı.
Geriye dönük uyum ve çift-mod çalıştırma
Göçü bir gecede yapmak zorunda değilsin. Spesifikasyon resmi bir "formal deprecation policy" tanımlıyor: "A formal deprecation policy with a twelve-month minimum window so you can plan upgrades instead of reacting to them." Bu pencere içinde deprecated olan üç özellik — Roots, Sampling, Logging (SEP-2577) — çalışmaya devam ediyor, sen de kademeli geçiş yapabiliyorsun.
Kimlik doğrulama tarafında da benzer bir yumuşak geçiş var: Dynamic Client Registration (DCR) resmen deprecated, yerine Client ID Metadata Documents (CIMD) standart hale geliyor, ama "DCR continues to work for backward compatibility, but will be removed in a future version of the MCP spec." Yani mevcut DCR entegrasyonun hemen kırılmıyor, fakat kalıcı da değil; CIMD'ye geçişi kendi takvimine göre planla ama takvimsiz bırakma.
Çift-mod (dual-era) bir sunucu çalıştırmak istiyorsan mimari şu şekilde: dispatcher seviyesinde önce _meta alanının varlığına bak — varsa modern akışa, yoksa (ve initialize isteği geliyorsa) legacy akışa yönlendir. SDK sürüm desteği de göçü kolaylaştırıyor: "All four Tier 1 SDKs speak 2026-07-28 as of today" — duyuru bunları TypeScript, Python, Go ve C# olarak listeliyor; Rust SDK için ise "the Rust SDK supports the new spec in beta" diyor. Yani hangi dilde yazıyor olursan ol, resmi SDK'ya güncellemek göçün büyük kısmını senin yerine hallediyor.
Dispatcher'ı çift-mod çalıştıracak şekilde kurmak
Aşağıdaki örnek, sunucu tarafındaki istek dağıtıcısının (dispatcher) modern ve legacy isteği nasıl ayırt edebileceğini gösteren kavramsal bir iskelet — SDK'nın kendi iç implementasyonu değil, senin dispatcher katmanına ekleyeceğin karar mantığı:
ts
1type RequestMeta = Record<string, unknown>;2 3type JsonRpcRequest = {4 jsonrpc: "2.0";5 id: string | number;6 method: string;7 params?: { _meta?: RequestMeta; [key: string]: unknown };8};9 10type JsonRpcResponse = { jsonrpc: "2.0"; id: string | number; [key: string]: unknown };11 12declare function respondWithDiscoverInfo(request: JsonRpcRequest): JsonRpcResponse;13declare function dispatchModern(request: JsonRpcRequest, meta: RequestMeta): JsonRpcResponse;14declare function dispatchLegacy(request: JsonRpcRequest): JsonRpcResponse;15declare function invalidParamsError(request: JsonRpcRequest): JsonRpcResponse;16 17function handleIncoming(request: JsonRpcRequest): JsonRpcResponse {18 const meta = request.params?._meta;19 if (meta) {20 // Modern akış: sürüm + capability her istekte geliyor21 if (request.method === "server/discover") {22 return respondWithDiscoverInfo(request); // MUST implement23 }24 return dispatchModern(request, meta);25 }26 27 if (request.method === "initialize") {28 // Legacy akış: istemci filon geçene kadar paralel çalıştır29 return dispatchLegacy(request);30 }31 32 // Zorunlu _meta yok ve legacy de değil: malformed istek -> -32602 Invalid params33 return invalidParamsError(request);34}Bu iskeletin kritik noktası sıralama: önce _meta varlığına bakılıyor, çünkü zorunlu per-request alanlarını taşımayan bir istek — server/discover dahil — malformed sayılır ve -32602 ile reddedilmek zorundadır. _meta varsa istek modern akışa girer, zorunlu server/discover de bu dalın içinde yanıtlanır; _meta yoksa yalnızca initialize legacy akışına düşer, geri kalan her şey -32602 alır.
Bu dispatcher deseni, aynı sunucu binary'sinin hem 2026-07-28 öncesi hem sonrası istemcilerle konuşabilmesini sağlıyor — istemci filonun tamamı per-request _meta gönderir hale geldiğinde dispatchLegacy dalını ve initialize handler'ını güvenle kaldırabilirsin.
Göç sonrası doğrulama kontrol listesi
Göçü tamamladıktan sonra aşağıdaki maddeleri tek tek doğrula — her biri spesifikasyonun somut bir kırılma noktasına karşılık geliyor:
Kontrol | Neyi doğrular | Nerede bakılır |
|---|---|---|
server/discover yanıt veriyor mu | Zorunlu RPC implementasyonu | Sunucu loglarında istek/yanıt |
Desteklenmeyen sürüm isteğinde doğru hata | UnsupportedProtocolVersionError + sürüm listesi | Manuel eski-sürüm isteği ile test |
Mcp-Method/Mcp-Name header'ları | Gateway route/rate-limit uyumu | Reverse proxy access log |
MRTR akışı | input_required → inputResponses döngüsü | Onay veya eksik parametre isteyen tool çağrısı |
Liste yanıtlarında ttlMs/cacheScope | Cache'lenebilir liste sonuçları | tools/list, resources/templates/list yanıtı |
SDK sürümü | 2026-07-28 desteği | package.json / go.mod / SDK changelog |
Yeni hata kodları | -32020, -32021, -32022 client'ta tanınıyor mu | İstemci hata-işleme testleri |
tools/list, prompts/list, resources/list, resources/read ve resources/templates/list yanıtlarının artık ttlMs ve cacheScope alanlarını taşıdığını unutma (SEP-2549) — bu alanları okuyup client tarafında cache'lemezsen, spec'in getirdiği performans kazanımını kaçırırsın. Ayrıca yeni rezerve hata kodlarını (-32020 HeaderMismatch, -32021 MissingRequiredClientCapability, -32022 UnsupportedProtocolVersion) istemci tarafında ayırt edilebilir şekilde işlediğinden emin ol.
ALTIN İPUCU
Bu yazının en değerli bilgisi
Bu ipucu, yazının en önemli çıkarımını içeriyor.
Easter Egg
Gizli bir bilgi buldun!
Bu bölümde gizli bir bilgi var. Keşfetmek ister misin?
Okuyucu Ödülü
Bu göçte atlanan bir adım üretim yükü altında ortaya çıkabilir, o yüzden aşağıdaki listeyi göç öncesi bir kere, göç sonrası bir kere daha kontrol et. Liste, bu rehberdeki tüm zorunlu ve opsiyonel maddeleri tek bir sırayla topluyor.
SSS
MCP 2026-07-28 spesifikasyonunda tam olarak ne değişti?
28 Temmuz 2026'da yayınlanan spesifikasyon, MCP'yi çift-yönlü stateful bir protokolden request/response tabanlı stateless bir protokole çevirdi: Mcp-Session-Id header'ı ve initialize/initialized el sıkışması kaldırıldı, her istek artık _meta alanında kendi protokol sürümünü ve capability'lerini taşıyor. Ayrıca sunucu-başlatımlı elicitation/sampling/roots çağrılarının yerini Multi Round-Trip Requests (MRTR) aldı ve resmi bir Extensions çerçevesi eklendi.
Mcp-Session-Id header'ı neden kaldırıldı, yerine ne geldi?
Amaç, herhangi bir MCP isteğinin herhangi bir sunucu örneğine düşebilmesini sağlayıp sticky routing veya paylaşımlı oturum deposu ihtiyacını ortadan kaldırmaktı — böylece sunucular düz round-robin load balancer arkasında ölçeklenebiliyor. Çapraz-çağrı durumu gerekiyorsa sunucular artık açık bir handle üretip modele parametre olarak geri gönderiyor.
Mevcut MCP sunucumu stateless spec'e nasıl taşırım?
Üç adım izle: server/discover RPC'sini zorunlu olarak implemente et; oturum durumu tutuyorsan bunu bir handle'a çevirip tool parametresi yap; initialize akışını hemen silme, kendi istemci filonun geçiş takvimi boyunca eski istemcilerle paralel çalıştır (spesifikasyon bu akışı kaldırdığı için sana ayrı bir pencere tanımıyor). stdio'da server/discover prob'u, HTTP'de modern istek + 400 gövde incelemesiyle era tespiti yaparak geçişi kademeli hale getirebilirsin.
server/discover zorunlu mu, initialize handshake'i silmeli miyim?
server/discover'ı implemente etmek sunucular için zorunludur; istemcinin onu her istekten önce çağırması ise opsiyoneldir, ayrıca stdio'da geriye-uyum probu olarak da kullanılabilir. initialize handshake'i spesifikasyondan tamamen kaldırıldığı için yeni implementasyonlarda kullanma, ama Roots/Sampling/Logging gibi deprecated özellikler en az 12 ay çalışmaya devam edeceği için mevcut sunucunu aniden kırmak zorunda değilsin.
DCR'dan CIMD'ye geçişi ne zaman yapmalıyım?
Hemen zorunlu değil — DCR geriye dönük uyumluluk için çalışmaya devam ediyor, spesifikasyon yalnızca CIMD'yi standart olarak öne çıkarıyor. Yeni entegrasyonları CIMD ile kurup mevcut DCR akışlarını kendi takvimine göre kapatabilirsin.
Legacy HTTP+SSE sunucumu ne zamana kadar çalıştırabilirim?
Blog duyurusu bu transport için yıl uzunluğunda bir offramp'tan söz ediyor, ama normatif kayıt olan deprecated özellikler registry'si en erken kaldırma tarihini SEP-2596'nın Final aşamasına ulaşmasından üç ay sonrası olarak veriyor. Planını registry satırına göre kur ve bu süre içinde yeni özellik geliştirmeyi Streamable HTTP ve stateless modele taşı.
Sonuç
MCP 2026-07-28'in getirdiği stateless model, protokolü sticky-session bağımlılığından kurtarıp gerçek anlamda yatay ölçeklenebilir hale getiriyor — bedeli ise initialize akışını, Mcp-Session-Id'yi ve açık stream'e dayalı sunucu-başlatımlı çağrıları elden çıkarmak. Göçü tek gecede yapmak zorunda değilsin: server/discover'ı zorunlu implementasyon olarak ekleyip çift-mod bir dispatcher'la eski ve yeni istemcileri bir süre birlikte taşıyabilirsin.
MCP'yi ilk kez kuruyorsan temel kavramlara MCP nedir ve nasıl entegre edilir rehberinden, Claude Code özelinde kurulum için Claude Code'da MCP entegrasyonu yazısından başlayabilirsin. Sunucunu birden fazla ajanın paylaştığı bir mimari kuruyorsan Claude Code multi-agent teams ve CrewAI ile multi-agent koordinasyon yazıları tamamlayıcı olacaktır. Ajan mimarinde tool-use döngüsünü stateless modele göre tasarlamak istiyorsan agentic AI tool-use ve planner-loop production rehberi sıradaki iyi bir adım; LangGraph tabanlı bir ajan üzerinde MCP sunucularını orkestre ediyorsan LangGraph ile production ajan mimarisi yazısına da göz at.
Kaynaklar
- MCP 2026-07-28 resmi duyuru — stateless geçişin,
Mcp-Session-Idveinitialize/initializedkaldırılmasının,server/discoverve MRTR'nin birincil kaynağı. - MCP 2026-07-28 Base Protocol genel bakışı —
resultType, per-request_metaalanları tablosu ve yeni hata kodları. - MCP 2026-07-28 MRTR sayfası —
inputRequests/inputResponsesmap şekli,requestStatekuralları ve güvenlik gereksinimleri. - MCP deprecated özellikler registry'si — Roots/Sampling/Logging, DCR ve HTTP+SSE için en erken kaldırma tarihleri.
- MCP 2026-07-28 versioning sayfası —
server/discoverzorunluluğu,UnsupportedProtocolVersionError, era-tespiti ve cache kuralları, extension negotiation. - MCP 2026-07-28 transports sayfası — stdio ve Streamable HTTP transport kuralları, custom transport gereksinimleri.
- MCP 2026-07-28 changelog — SEP numaralarıyla madde madde değişiklik listesi;
server/discoverzorunluluğunun ve oturum/handshake kaldırılmasının birebir ifadeleri burada. - Claude blog: MCP 2026-07-28'i Claude'a getirmek — Anthropic ekosistemi bağlamında stateless geçişin özeti.

