Model Context Protocol'ün 2026-07-28 spec revizyonu, üç köşe taşı özelliği aynı anda deprecated listesine taşıdı: Roots, Sampling ve Logging. Bu yazıda MCP deprecated özellikler geçiş sürecini adım adım ele alıyoruz — neyin neden kaldırıldığını, elinde ne kadar zaman olduğunu ve sunucunu ya da istemcini kırmadan nasıl taşıyacağını. SEP-2577 ile resmileşen bu karar, protokolün ilk kez gerçek bir deprecation politikasını uyguladığı örnek; burada öğrendiğin desen bundan sonraki her deprecation için de geçerli olacak.
💡 Pro Tip: Roots, Sampling ve Logging şu an hâlâ çalışıyor — wire-level'da hiçbir şey kırılmadı. Panik yapıp acele geçiş yapma; asıl öncelik kod tabanında bu üç primitive'i kullanan yerleri envanterleyip migrasyon yolunu netleştirmek.
İçindekiler
- Neler Deprecate Edildi ve Neden
- Deprecation kriterleri nereden geliyor
- Neden hepsi aynı anda
- 12 Aylık Pencere: Takvim ve Risk
- Fiili kaldırma neden değişebilir
- Roots'suz Dosya Kapsamı Vermek
- Sampling'siz Server-Initiated LLM Çağrısı Alternatifleri
- Neden bu değişim iyileştirme sayılıyor
- Logging Yerine Telemetri Deseni
- Eski HTTP+SSE Transport'tan Çıkış
- Envanter: Neyin Etkilendiğini Bulan Betik
- Envanteri önceliklendirme sırası
- SSS
- MCP'de Sampling özelliği neden deprecated oldu?
- Roots yerine ne kullanılmalı?
- MCP deprecation penceresi ne kadar sürüyor?
- Logging kullanan MCP sunucumu nasıl güncellerim?
- HTTP+SSE transport'un deprecation'ı Roots/Sampling/Logging ile aynı takvimde mi?
- Deprecated bir özelliği kullanmaya devam edersem ne olur?
- Yeni bir MCP sunucusu yazıyorum, Roots/Sampling/Logging'i hiç mi kullanmamalıyım?
- Sonuç
- Kaynaklar
Neler Deprecate Edildi ve Neden
2026-07-28 tarihli spec revizyonu, SEP-2577 ile Roots, Sampling ve Logging'i Deprecated durumuna aldı. Resmî duyuru bunu net biçimde koyuyor: "Roots, Sampling, and Logging are deprecated (SEP-2577). They still work, and they'll keep working for at least twelve months. New implementations shouldn't adopt them." Yani mevcut entegrasyonların hiçbiri o gün kırılmadı; asıl mesaj yeni projelerin artık bu üç primitive üzerine inşa edilmemesi.
Aynı revizyon döneminde, ayrı bir karar akışıyla (PR #2858) Dynamic Client Registration (DCR) de Deprecated listesine eklendi. Yani bu geçiş dört başlıklı bir paket: Roots, Sampling, Logging ve DCR — her birinin kendi migrasyon yolu var, ama hepsi aynı resmî deprecation politikasına tabi.
Deprecation kriterleri nereden geliyor
Bir özelliğin Deprecated işaretlenmesi keyfi değil; resmî feature-lifecycle politikası dört kriter sıralıyor: başka bir özellik tarafından ikame edilmiş olmak, yerinde giderilemeyen bir güvenlik/gizlilik/birlikte-çalışabilirlik riski taşımak, "ecosystem telemetry or SDK maintainer consensus indicates negligible adoption relative to its maintenance cost" durumu ve Core Maintainer'ların uygun gördüğü başka gerekçeler. Bu üçlüde kriterlerden en yakını üçüncüsü: SEP-2577'nin Motivation bölümü "Features that see low adoption, overlap with existing alternatives, or impose disproportionate implementation burden relative to their value are candidates for removal" diyor.
Özellik | Durum (2026-07-28 itibarıyla) | Kısa gerekçe |
|---|---|---|
Roots | Deprecated (SEP-2577) | Düşük benimseme, belirsiz semantik, daha açık alternatifler |
Sampling | Deprecated (SEP-2577) | Karmaşık implementasyon, düşük benimseme, doğrudan API yolu |
Logging | Deprecated (SEP-2577) | Örtüşen olgun altyapı (stderr, OTel), karmaşıklığa göre düşük değer |
Dynamic Client Registration | Deprecated (PR #2858) | Client ID Metadata Documents ile değiştirildi |
Neden hepsi aynı anda
Dört özelliğin aynı revizyonda deprecate edilmesi tesadüf değil. SEP-2577, Roots ve Sampling için aynı iki gerekçeyi ortak koyuyor: feature support matrix'in gösterdiği düşük istemci benimsemesi ve protokol dışında daha açık alternatiflerin varlığı — Roots için tool parametresi, resource URI, sunucu konfigürasyonu veya ortam değişkeni; Sampling için doğrudan LLM sağlayıcı API'leri. Sampling'e ek olarak bir de "complex to implement" maddesi geliyor: doğru bir implementasyon insan onayı, model seçim mantığı, güvenlik değerlendirmeleri ve SEP-1577'den beri tool-loop desteği istiyor. Logging ise farklı bir gerekçeyle geldi: protokol içi log RPC'leri, dışarıda zaten olgunlaşmış OpenTelemetry gibi standartlarla örtüşüyordu ve spec bu yüzeyi çekirdekte tutmak yerine mevcut ekosistem standardına yaslanmayı seçti. DCR'ın deprecation'ı ise ayrı bir güvenlik kararı (Client ID Metadata Documents'a geçiş) ile geldi ve teknik olarak diğer üçünden bağımsız, sadece takvimi paylaşıyor.
12 Aylık Pencere: Takvim ve Risk
Burada iki farklı sayı birbirine karıştırılmamalı. Blog yazısı "en az on iki ay" diyor; SEP-2577'nin kendi metni ise mekanizmanın nasıl işlediğini daha ayrıntılı anlatıyor: "They will continue to be fully functional in all specification versions released within one year of that version's release... This provides implementations with an extended migration window before the features are fully removed." Yani bu kayan bir pencere: her yeni spec sürümü, kendi yayın tarihinden itibaren desteği yeniden bir yıl uzatıyor — tek seferlik, sabit bir kesim tarihi değil. Bir şerh düşmek gerek: SEP-2577 bu mekanizmayı "assuming the one-year-per-version support policy proposed in a separate SEP" kaydıyla anlatıyor, yani sürüm başına bir yıllık destek politikası ayrı bir SEP'e bağlı ve kesinleşmiş sayılmıyor.
Resmî deprecated-registry sayfası, Roots/Sampling/Logging/DCR için somut bir alt sınır da veriyor: tablonun "Earliest removal" kolonu bu dört satırda da First revision released on or after 2027-07-28 yazıyor. Bunu "2027 Temmuz'da kesin kalkacak" diye okumak yanlış olur — kayıt sadece bu tarihten sonraki ilk revizyonun kaldırma için _uygun hale geleceğini_ söylüyor; fiili kaldırma kararı yine Core Maintainer'lara ait ve daha geç de gerçekleşebilir.
Aynı 2026-07-28 revizyonunda paralel bir deprecation daha var: eski HTTP+SSE transport. Ama bu farklı bir sayaç kullanıyor — resmî kayıtta Deprecated tarihi 2026-07-28 değil, 2025-03-26; erken kaldırma tetikleyicisi de aynı tablonun kolonunda "Three months after SEP-2596 reaches Final" (SEP-2596 Final'e ulaştıktan üç ay sonra) olarak geçiyor. Blog yazısı bunu "year-long offramp" diye anlatıyor ama registry'nin verdiği tetikleyici üç ay — iki resmî kaynak farklı çerçeveler kullanıyor, bu ikisini aynı sayaç sanma.
Özellik grubu | Deprecated tarihi | En erken kaldırma tetiği | Sayaç türü |
|---|---|---|---|
Roots / Sampling / Logging / DCR | 2026-07-28 | 2027-07-28 sonrası ilk revizyon | Kayan, en az 12 ay |
HTTP+SSE transport | 2025-03-26 | SEP-2596 Final'den 3 ay sonra | Sabit, SEP durumuna bağlı |
Risk şurada: ekipler "12 ay sonra kesin silinir" varsayımıyla göçü aceleye getirebilir. Gerçek durum daha yumuşak — ama bu, geçişi erteleme gerekçesi değil; sadece takvim baskısını doğru büyüklükte tutmak için.
Fiili kaldırma neden değişebilir
Resmî kayıt, "eligible for removal" ile "removed" arasına bilinçli bir boşluk bırakıyor: bir özellik kaldırma için uygun hale geldiğinde bile, gerçek kaldırma "a Core Maintainer decision taken during release preparation" — yani bir sonraki spec revizyonu hazırlanırken alınan ayrı bir karar. Bu, ekosistemdeki gerçek benimseme oranına, açık implementasyon sayısına ve topluluk geri bildirimine bağlı olarak değişebilir. Pratik sonucu şu: "en erken kaldırma tarihi" bir alarm değil, bir alt sınır. Migrasyon planını bu tarihe göre erteleme, ama "tarih geçince otomatik kırılır" diye de acele etme — ikisi de yanlış okuma.
Roots'suz Dosya Kapsamı Vermek
Roots'un resmî migrasyon yolu net: dizin/dosya bağlamını artık protokol seviyesinde ayrı bir "roots" listesi yerine, tool parametreleri, resource URI'leri veya sunucu konfigürasyonu üzerinden taşımalısın. Bu, stateless çekirdeğin genel prensibiyle de örtüşüyor — sunucu durumunu transport'ta tutmak yerine, modele görünür açık bir handle olarak tool argümanında taşımak.
ts
1// ÖNCE — Roots ile örtük dizin bağlamı (roots/list'i SUNUCU ister)2type ListRootsResult = { roots: Array<{ uri: string; name?: string }> };3 4// Sunucu, roots/list isteğini InputRequiredResult içinde istemciye gönderir:5const inputRequired = {6 resultType: "input_required" as const,7 inputRequests: { workspace: { method: "roots/list" } },8};9 10// İstemci ListRootsResult'ı inputResponses altında geri verir:11function pickScope(responses: Record<string, ListRootsResult>): string {12 return responses.workspace.roots[0].uri; // bilgilendirici; sunucuyu bağlamıyor13}14 15// SONRA — tool parametresiyle açık kapsam16type ToolCall = { name: string; arguments: Record<string, string> };17const explicitCall: ToolCall = {18 name: "search_files",19 arguments: {20 workspacePath: "/Users/dev/projects/portfolio",21 pattern: "*.ts",22 },23};24 25console.log(26 inputRequired.resultType,27 pickScope,28 explicitCall.arguments.workspacePath,29);Kapsamı açıkça tool argümanına yazmak, modelin de sunucunun da hangi dizinle çalıştığını tartışmasız biçimde bilmesini sağlıyor — Roots'un "bilgilendirici ama bağlayıcı olmayan" belirsizliğinin yerini net bir sözleşme alıyor.
Sampling'siz Server-Initiated LLM Çağrısı Alternatifleri
Sampling'in resmî migrasyon önerisi kısa: LLM sağlayıcı API'lerine doğrudan entegre ol. Ama teknik arka planı anlamak geçişi kolaylaştırıyor. Eskiden sunucunun modele "bana bir tamamlama üret" diye açık bir stream üzerinden çağrı yapması gerekiyordu (sampling/createMessage, roots/list, elicitation/create). Bu server-initiated desen artık MRTR (SEP-2322) ile değiştirildi: sunucu doğrudan stream açmak yerine resultType: "input_required" döndürüyor, istemci de aynı çağrıyı gereken cevaplarla birlikte inputResponses alanında tekrarlıyor.
json
1// Sunucunun yanıtı — açık stream yerine "input gerekiyor" sinyali.2// inputRequests bir DİZİ değil, sunucunun atadığı anahtarlarla bir MAP.3{4 "resultType": "input_required",5 "inputRequests": {6 "capital_of_france": {7 "method": "sampling/createMessage",8 "params": {9 "messages": [10 { "role": "user", "content": { "type": "text", "text": "What is the capital of France?" } }11 ],12 "systemPrompt": "You are a helpful assistant.",13 "maxTokens": 10014 }15 }16 },17 "requestState": "AEAD-protected blob"18}19 20// İstemcinin tekrar çağrısı — CreateMessageResult ve requestState aynen geri21// not: tekrar çağrının JSON-RPC id'si ilk istektekinden FARKLI olmalı22{23 "jsonrpc": "2.0",24 "id": 2,25 "method": "tools/call",26 "params": {27 "name": "summarize_repo",28 "inputResponses": {29 "capital_of_france": {30 "role": "assistant",31 "content": { "type": "text", "text": "The capital of France is Paris." },32 "model": "claude-3-sonnet-20240307",33 "stopReason": "endTurn"34 }35 },36 "requestState": "AEAD-protected blob"37 }38}Pratikte bu, sunucunun artık kendi tuttuğu bir LLM istemcisiyle (OpenAI, Anthropic veya başka bir sağlayıcı SDK'sı) doğrudan konuşması anlamına geliyor — model seçimi, parametreler ve streaming tamamen senin kontrolünde, protokol içi bir aracıya bağımlı değilsin.
Neden bu değişim iyileştirme sayılıyor
Eski server-initiated Sampling deseninin en büyük pratik sorunu, sunucunun cevabı bekleyebilmek için bağlantıyı açık tutması gerekmesiydi — bu da yük dengeleyici, proxy ve serverless ortamlarda ciddi bir kısıt getiriyordu. MRTR'nin input_required / inputResponses döngüsü, her adımı sıradan bir istek-cevap çiftine indirgiyor; sunucu stream tutmak zorunda kalmadan, istemci de bağlantıyı serbestçe kapatıp yeniden açarak aynı işi tamamlayabiliyor. Bu, Sampling'in kaybı değil, aynı işlevin stateless dünyaya taşınmış hali.
Logging Yerine Telemetri Deseni
Logging'in resmî migrasyon yolu iki parçalı: stdio transport kullanan sunucular için stderr'e yazmak, daha geniş gözlemlenebilirlik ihtiyacı için OpenTelemetry'e geçmek. Spec ayrıca logging/setLevel RPC'sini tamamen kaldırdı; log seviyesi artık her istekte _meta alanı içindeki io.modelcontextprotocol/logLevel anahtarıyla ayarlanıyor.
ts
1// Her istekte per-request log seviyesi (logging/setLevel yerine)2declare const client: { request(req: unknown): Promise<unknown> };3 4async function callWithLogLevel() {5 await client.request({6 method: "tools/call",7 params: {8 name: "run_migration",9 _meta: {10 "io.modelcontextprotocol/logLevel": "debug",11 traceparent: "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",12 },13 },14 });15}Aynı revizyonda OpenTelemetry trace context taşıma kuralları da (traceparent, tracestate, baggage — SEP-414) _meta içinde belgelendi. Bu, Logging'in bıraktığı boşluğu dolduran telemetri altyapısının parçası: artık tekil log satırları yerine, dağıtık iz (trace) bağlamını çağrılar arasında taşıyabiliyorsun.
Eski HTTP+SSE Transport'tan Çıkış
Aynı 2026-07-28 döneminde, çekirdek primitive'lerden bağımsız bir başka deprecation daha yürürlükte: 2025-03-26'dan beri deprecated olan eski HTTP+SSE transport, bu revizyonda feature-lifecycle politikası altında resmen Deprecated olarak yeniden sınıflandırıldı ve önerilen hedef Streamable HTTP. Bu geçişin kendi takvimi ve teknik detayları var — konuyu burada tekrar etmek yerine, stateless geçiş ve handshake tarafını derinlemesine işleyen MCP 2026-07-28: Stateless Geçiş ve Sunucunu Kırmadan Taşıma yazısına bakabilirsin.
Envanter: Neyin Etkilendiğini Bulan Betik
Geçişe başlamadan önce kod tabanında bu dört başlığın nerede kullanıldığını bulmak gerekiyor. Aşağıdaki basit grep taraması, en yaygın çağrı imzalarını ve extension kullanım noktalarını yakalıyor:
bash
1#!/usr/bin/env bash2# MCP deprecated primitive envanteri3echo "== Roots =="4grep -rn "roots/list\|roots/list_changed" --include="*.ts" --include="*.py" .5 6echo "== Sampling =="7grep -rn "sampling/createMessage\|elicitation/create" --include="*.ts" --include="*.py" .8 9echo "== Logging (eski) =="10grep -rn "logging/setLevel" --include="*.ts" --include="*.py" .11 12echo "== Dynamic Client Registration =="13grep -rn "register_client\|dynamic_client_registration" --include="*.ts" --include="*.py" .14 15echo "== Tasks extension kullanımı =="16grep -rn "io.modelcontextprotocol/tasks" --include="*.ts" --include="*.py" .Son satır bilinçli eklendi: aynı 2026-07-28 revizyonunda deneysel Tasks özelliği de çekirdekten çıkarılıp io.modelcontextprotocol/tasks adlı resmî bir extension'a taşındı. Extension kullanımı, changelog'un deyişiyle ClientCapabilities ve ServerCapabilities tiplerine eklenen extensions alanıyla beyan ediliyor; istemci tarafında bu yetenek bloğu her istekte _meta.io.modelcontextprotocol/clientCapabilities içinde, sunucu tarafında ise server/discover yanıtında taşınıyor — envanter betiğin bu alanı da taramalı, çünkü Tasks artık opt-in.
Envanteri önceliklendirme sırası
Betiğin çıktısı genelde dört ayrı liste verir; hepsini aynı anda göçe almaya çalışma. Önce Logging'i taşı — bu en düşük riskli değişiklik, çünkü stderr ve OpenTelemetry'ye geçiş uygulama mantığını değiştirmiyor, sadece çıktı hedefini değiştiriyor. Ardından Roots'u ele al — tool parametrelerine taşımak genelde tek bir imza değişikliği. Sampling en çok efor isteyen adım, çünkü LLM sağlayıcı entegrasyonunu sıfırdan kurmak gerekebilir; bu yüzden onu üçüncü sıraya bırak. DCR'ı sona bırakabilirsin, çünkü resmî kayıt onu Client ID Metadata Documents'a yönlendirirken bir de şu notu düşüyor: "It remains available for backwards compatibility with authorization servers that do not support Client ID Metadata Documents." Yani yetkilendirme sunucun CIMD'yi desteklemiyorsa mevcut akış çalışmaya devam ediyor.
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ü
Geçiş planını başlatmadan önce ekibinle gözden geçirebileceğin, resmî kaynaklara dayanan kısa bir kontrol listesi hazırladık. Her madde, yazıda geçen bir migrasyon yoluna karşılık geliyor.
SSS
MCP'de Sampling özelliği neden deprecated oldu?
SEP-2577 üç gerekçe sıralıyor: implementasyonu karmaşık (insan onayı, model seçim mantığı, güvenlik değerlendirmeleri ve SEP-1577'den beri tool-loop desteği gerekiyor), feature support matrix'e göre istemci benimsemesi düşük ve protokol dışında doğrudan alternatifi var. Resmî migrasyon önerisi, sunucuların LLM sağlayıcı API'lerine doğrudan bağlanması; bu sayede model seçimi, parametreler ve streaming tamamen sunucunun kontrolünde kalıyor.
Roots yerine ne kullanılmalı?
Dizin veya dosya bağlamını artık protokol seviyesinde ayrı bir Roots listesi yerine tool parametreleri, resource URI'leri veya sunucu konfigürasyonu üzerinden açıkça taşımalısın. Bu, kapsamı belirsiz bırakmak yerine modele ve sunucuya net bir sözleşme sunuyor.
MCP deprecation penceresi ne kadar sürüyor?
Roots, Sampling, Logging ve Dynamic Client Registration için pencere kayan bir yapı: her yeni spec sürümü kendi yayın tarihinden itibaren desteği yeniden en az bir yıl uzatıyor. Resmî kayıt, bu dört özellik için en erken kaldırmanın 2027-07-28 veya sonrasında yayınlanan ilk revizyonda mümkün olabileceğini söylüyor — ama bu kesin bir kaldırma tarihi değil, sadece uygunluk eşiği.
Logging kullanan MCP sunucumu nasıl güncellerim?
logging/setLevel bu revizyonda kaldırıldı: changelog'un Major changes listesi "Remove ping, logging/setLevel, and notifications/roots/list_changed" diyor. Seviye artık _meta içindeki io.modelcontextprotocol/logLevel ile istek bazında ayarlanıyor, notifications/message ise yalnız bu alanı taşıyan isteklerde yayılıyor. Uzun vadede resmî öneri stdio için stderr, daha geniş gözlemlenebilirlik için OpenTelemetry'e geçmek.
HTTP+SSE transport'un deprecation'ı Roots/Sampling/Logging ile aynı takvimde mi?
Hayır. HTTP+SSE'nin resmî kayıttaki Deprecated tarihi 2025-03-26 ve en erken kaldırma tetikleyicisi SEP-2596'nın Final durumuna ulaşmasından üç ay sonrası — Roots/Sampling/Logging/DCR'ın 2026-07-28'den başlayan en-az-12-aylık kayan penceresinden tamamen ayrı bir sayaç.
Deprecated bir özelliği kullanmaya devam edersem ne olur?
SEP-2577 açıkça "they still work" diyor — deprecation anında hiçbir çağrı kırılmıyor. Ama yeni implementasyonların bu primitive'leri benimsememesi öneriliyor ve nihai kaldırma kararı Core Maintainer'lara ait; bu yüzden envanter çıkarıp migrasyon yolunu şimdiden netleştirmek, ileride acele bir göçten daha güvenli.
Yeni bir MCP sunucusu yazıyorum, Roots/Sampling/Logging'i hiç mi kullanmamalıyım?
Resmî duyuru bunu açıkça öneriyor: "New implementations shouldn't adopt them." Yani sıfırdan bir sunucu ya da istemci yazıyorsan, baştan itibaren tool parametreleriyle kapsam taşımayı, LLM sağlayıcı API'lerine doğrudan entegrasyonu ve OpenTelemetry tabanlı gözlemlenebilirliği tercih etmek, ileride migrasyon borcu biriktirmemenin en kestirme yolu.
Sonuç
Roots, Sampling, Logging ve DCR'ın deprecation'ı, MCP'nin ilk kez resmî bir deprecation politikasını uyguladığı örnek — ve bu iyi haber, çünkü artık takvim ve migrasyon yolu belirsiz değil, kayıtlı ve öngörülebilir. Kod tabanında bu dört başlığı taramak için MCP (Model Context Protocol): AI Entegrasyon Standardı yazısındaki temel kavramlara, güvenlik tarafı için AI Kodlama Ajanına Yetki Vermek: Prompt Injection Riski yazısına, agentic akışlarda Sampling'in yerini alan tool-use desenleri için Agentic AI: Tool Use, Planner Loops ve Production Agent Mimarisi yazısına bakabilirsin. Claude Code'un MCP entegrasyonunu genel hatlarıyla görmek istersen Claude Code MCP: Model Context Protocol ile AI Plugin Ekosistemi iyi bir başlangıç; hangi aracı ne zaman seçeceğini netleştirmek içinse Claude Code'da Skill, Subagent, Hook, MCP: Hangisi Ne Zaman yazısı yardımcı olur.
Son adım her zaman aynı: önce envanter çıkar, sonra migrasyon yolunu resmî kaynaktan doğrula, sonra göç et — panikle değil, takvime güvenerek.
Kaynaklar
- MCP Roadmap Blog — 2026-07-28 duyurusu — Roots/Sampling/Logging deprecation'ının resmî duyurusu ve "en az on iki ay" ifadesinin kaynağı
- MCP Specification Changelog 2026-07-28 —
logging/setLevelkaldırılması,_metaüzerinden log seviyesi ve OTel trace context değişikliklerinin teknik dökümü - MCP Deprecated Features Registry — her özelliğin migrasyon yolu, deprecated tarihi ve en erken kaldırma tetikleyicisi
- MCP Feature Lifecycle Policy — deprecation kriterleri ve pencere hesaplama kuralları
- SEP-2577: Deprecate Roots, Sampling, and Logging — kayan pencere mekanizmasının birebir metni, Final statüsü
- MCP Tasks Extension Overview — Tasks'ın çekirdekten extension'a taşınması ve capability beyan deseni

