Bir MCP sunucusunun kullanıcılar adına API'nizi nasıl çağırdığı: üretimde token stratejisi
MCP sunucuları için dışa yönelik token stratejisini açıklar: neden token aktarımı ve M2M başarısız olur ve token değişiminin izinleri kullanıcılarla nasıl hizalı tuttuğunu anlatır.
Bir MCP sunucusunun kullanıcılar adına API'nizi nasıl çağırdığı: üretimde token stratejisi#
Önceki makalemizde, Logto uzaktan MCP sunucusunu oluşturma deneyimimizi genel hatlarıyla paylaşmıştık. Bu makalede mimari tasarım ve OAuth akışı ayrıntılı olarak ele alınıyor.
MCP sunucusu sınır olarak alındığında, bir uzak MCP sunucusu için kimlik doğrulama iki ayaktan oluşur: gelen (inbound) ve giden (outbound).
Gelen: MCP istemcisi (VS Code, Cursor gibi) OAuth ile oturum açar, bir erişim token'ı alır ve MCP sunucunuza erişmek için onu kullanır
Giden: Araç çağrılarını işlerken, MCP sunucusu kullanıcının adına kendi iş API’nizi çağırır
Gelen ayak MCP spesifikasyonunda iyi tanımlanmıştır ve toplulukta pek çok tartışma ve uygulama örnekleri vardır. Daha önce bir uygulama rehberi de yazdık. Giden ayak ise çok daha az ilgi görüyor: MCP sunucusunun elinde sadece kendisine erişim için bir token var. İş API’nizi kullanıcı adına nasıl çağırabilir?
Logto MCP sunucusunu oluştururken sürekli olarak mücadele ettiğimiz soru buydu. Logto Cloud tipik bir B2B çok kiracılı üründür: bir kullanıcı birden fazla kiracıya ait olabilir ve izinler, kullanıcının her kiracıdaki rolünden gelir. Yapay zeka sadece kullanıcı gibi davranmamalı, aynı zamanda doğru kiracıya da ulaşmalıdır.
Bu makale, gerçek karar verme sürecimizi takip ediyor:
MCP sunucusunun neden bağımsız olarak, ayrı bir korunan kaynak olarak konuşlandırılması gerektiği
Reddettiğimiz iki giden çözüm (token aktarımı ve M2M token) ve bunların problemleri
Nihai tasarım: token değişimi ve konu token'ı (subject token), ayrıca organizasyon token'larının çok kiracılı sistemlerde nasıl çalışmasını içerir
Benzer bir şey inşa ederken göz önünde bulundurmanız gereken birkaç ilke
OAuth perspektifinden bakıldığında, bir uzak MCP sunucusu aynı anda iki rol oynar:
MCP istemcisine göre bir kaynak sunucudur: istemci ona erişmek için bir token getirmek zorundadır
İş API’sine göre ise bir istemcidir: başkasına erişmek için bir token götürür
Yani MCP sunucusu iki tarafta farklı rol oynar ve her biri farklı bir token kullanır. MCP istemcisinin OAuth ile aldığı token'ın hedef kitlesi (audience) MCP sunucusudur; bu yüzden iş API’si, hedef kitleyi doğrularken onu reddedecektir.
Yani giden ayak, esasen bir yetkilendirme devri sorunudur: MCP sunucusu, kullanıcının kimliğini veya kimlik bilgilerini saklamadan, kullanıcının izinleriyle aşağı akış API'larını kullanıcı gibi nasıl çağırır?
Mimari kararı: MCP sunucusu ayrı bir hizmet olarak#
MCP uç noktasını iş API hizmetinin içine dahil etmek, aynı süreçte ve aynı kimlik doğrulama yığınıyla paylaşmak en doğrudan seçenek gibi görünebilir. Bunu tarttıktan sonra, biz bağımsız konuşlandırmayı seçtik:
Risk izolasyonu: Kararı verdiğimizde, resmi MCP SDK’sı henüz üretime hazır değildi ve protokol kendisi hızlıca evrimleşiyordu (iletişim şeklinin SSE’den Streamable HTTP’ye geçmesi buna bir örnek). Logto bir IAM hizmeti ve oturum açma yolunun kullanılabilirliği en önemli şeydir. Bağımsız konuşlandırmada MCP sunucusu bozulursa, sadece yapay zeka giriş noktası etkilenir. Ana hizmet etkilenmez.
Bağımsız iterasyon: MCP ekosistemi haftalık değişiyor ve istemci uyumluluk sorunları herhangi bir anda sıcak yamalar gerektirebilir; ana hizmet ise regresyon testleriyle sıkı bir sürüm takvimine sahip. Ayrı konuşlandırmalar, ikisinin birbirini yavaşlatmasını engeller.
Çalışma zamanı özgürlüğü: Bağımsız hizmet, kendisine en uygun çalışma zamanını seçebilir. Logto MCP sunucusu Cloudflare Workers üzerinde çalışır: durumsuz, istek başına ölçeklenir ve neredeyse sıfır operasyon gerektirir. Gömülü seçenekte bu özgürlüğünüz olmaz.
MCP sunucusu kendi alan adında, mcp.logto.io üzerinde konuşlandırılır, ana hizmet ile özel bir bağlantısı yoktur. İleride açık kaynak yapmak istersek, önünde engel yoktur.
Gömülü seçenek de token sorununu çözemez: MCP uç noktası ile iş API’si aynı kaynak tanımlayıcısını paylaşır, yani MCP istemcisinin aldığı token tüm API izinlerini içerir. "Bu çağrı hangi izinlerle çalışıyor?" sorusu, çapraz hizmet token değişiminden işlem için izin aktarıma gider ve sorun ortadan kalkmaz. Bağımsız konuşlandırma, izin sınırını açıkça tasarlamaya zorlar. Bu makalenin gerisi de bununla ilgilidir.
MCP sunucusunun kendine ait bir kaynak tanımlayıcısı olmalı#
Dışa doğru olan tartışma daha temel bir soruyla başlar: MCP istemcisinin aldığı token'ın hedef kitlesi ne olmalı?
İş API’sinin kaynak tanımlayıcısını yeniden kullanmak en doğrudan seçenek: Logto’nun Yönetim API’si zaten standart bir OAuth korumalı kaynaktır, bu nedenle MCP istemcisi token'ı doğrudan isteyebilir ve MCP sunucusu onu aynen iletebilir. Pek çok ilk MCP sunucu uygulaması da tam olarak bunu yaptı.
Bunun bedeli: Eğer MCP token’ın hedef kitlesi iş API’si olursa, artık izin sınırı yok olur.
Özenle tasarlanmış MCP araçlarınız süs gibi kalır: token'ın kendisi API'nin tamamını, araçlarınıza uğramadan çağırabilir
Sızan bir token’ın etkisi, "sadece MCP sunucusunun açtığı birkaç işlem"den "tüm Yönetim API’sine" çıkar
MCP senaryoları için bağımsız denetim, kota sınırlandırma, izin kapsamlandırma için bir temel kalmaz
Bu yüzden ilk kararımız: MCP sunucusu ayrı bir korunan kaynaktır, kendine ait bir kaynak tanımlayıcısı (https://mcp.logto.io) ve kapsamına sahiptir.
Bu karar izin sınırını temiz kılar ve hemen dışa yönelik soruyu somutlaştırır: Token sadece MCP sunucusuna erişebilir; peki MCP sunucusu API’yi çağırırken ne kullanacak?
Logto Console bir SPA’dır. Yönetim API’sini çağırması basittir: kullanıcı OAuth ile tarayıcıda oturum açar, hedef kitlesi Yönetim API’si olan bir token alır ve frontend doğrudan API’yi çağırır.
Peki MCP sunucusu, başka türden bir Console gibi çalışabilir mi? MCP istemcisine iş API’sinin token’ını oturum açınca istemesini sağlayıp, MCP sunucusunun onu hiç dönüştürmeden iletmesine izin verelim:
Bu yaklaşımın cazibesi sade olmasıdır: MCP sunucusu sadece token'ları ileri iletir. Ama açık sorunları vardır:
Birincisi, yukarıdaki izin sınırı kararıyla doğrudan çelişir. Token aktarımı, MCP istemcisinin iş API’sinin token’ına sahip olmasını gerektirir ki, az önce reddettiğimiz şey buydu.
İkincisi, MCP sunucusu artık gerçek bir korunan kaynak olmaz. Aldığı token'ların hedef kitlesi kendisi değildir, bu yüzden hedef kitle doğrulaması anlamını yitirir ve "sadece imzayı ve vericiyi kontrol etme"ye indirgenir. Bu, MCP spesifikasyonunda tanımlanan yetkilendirmeyle uyumsuzdur (MCP sunucusu kaynak sunucu gibi davranmalı ve kendisini RFC 9728 Protected Resource Metadata ile beyan etmelidir). Esasen, bir backend servis, tarayıcıda SPA gibi gizlenmiş olur.
Üçüncüsü, MCP istemcileri işbirliği yapmaz. Şarta uygun bir MCP istemcisi token'ları Protected Resource Metadata'ya göre ister ve hedef kitlesi MCP sunucusu olur. İş API’sinin token’ını istemesini sağlayacak standart bir yol yoktur, bu yüzden bu yol istemci tarafında çalışmaz.
Kullanıcının token’ı işe yaramıyorsa, MCP sunucusunun kendi kimliği peki?
MCP sunucusuna bir M2M (makineden makineye) uygulama tanıyalım, istemci kimlik bilgileriyle bir token alsın ve iş API’sini bununla çağırsın. Bu, dahili servisler arası standart uygulamadır.
Artık gelen kimlik doğrulaması da gayet iyi çalışır: MCP istemcisinin token’ı hedef kitle olarak MCP sunucusunu taşır, MCP sunucusu onu doğrular, sonra kendi M2M token’ı ile işlemi yapar.
Yetki aşımı: M2M token’ı "MCP sunucusu ne yapabilir"i temsil eder, "bu kullanıcı ne yapabilir"'i değil. Sadece okuma yetkisi olan bir kullanıcı, MCP ile uygulama silebilir çünkü M2M token’ının yetkisi vardır
Kimlik kaybı: Aşağı akıştaki API çağrıyı yapanı hep M2M uygulaması olarak görür, denetim logları belli bir kullanıcıya geri izlenemez
Karmaşık vekil (confused deputy): MCP sunucusu yüksek ayrıcalıklı bir proxy olur ve onu arayacak birini ikna eden herkes, onun izinlerinden yararlanabilir
M2M kullanıcısız durumlara uygundur; zamanlanmış işler ve sistemden sisteme eşitleme gibi. Bir MCP sunucusu farklıdır: her çağrı belli bir kullanıcı tarafından başlatılır, bu yüzden kullanıcı kimliği ve izinleriyle yürütülmelidir.
Nihai tasarım: token değişimi + konu token’ı (subject token)#
İki yaklaşımın derslerini birleştirince doğru tasarımın gerekleri ulaşılır:
MCP sunucusu aşağı akış API’larını çağırırken kullanıcı gibi davranmalı ve kullanıcının sınırlarıyla hareket etmeli (yaklaşım 2’nin dersi)
Bu doğrudan standart bir mekanizmaya işaret eder: token değişimi (RFC 8693). MCP sunucusu kullanıcıyı temsil eden bir kimlik bilgisini alır ve kimlik doğrulama sunucusunda onunla, aşağı akışta çalışacak bir token ile değiştirir. Kullanıcı kimliği ve izinleri değişim sırasında korunur.
Logto’da bu "kullanıcıyı temsil eden kimlik bilgisi", kullanıcı taklidi özelliğiyle gelir: konu token’ı (subject token). Sunucu, belli bir kullanıcı için, "bir sonraki token değişimi bu kullanıcı adına olacak" anlamına gelen kısa ömürlü bir kimlik bilgisi ister. Kullanıcı ek bir şey oluşturmaz ya da yapılandırmaz, tüm akış otomatiktir. Konu token’ı kısa ömürlü ve tek kullanımlıktır, kullanıldıktan sonra geçersiz olur.
Mimaride dört rol vardır. MCP sunucusu bağımsız olarak mcp.logto.io'da konuşlandırılır:
Bir araç çağrısının ardındaki tam token akışı:
Adım adım:
① Gelen doğrulama. MCP istemcisi, araç ile birlikte kullanıcı token’ı gönderir. Token'ın hedef kitlesi MCP sunucusunun kaynak tanımlayıcısı ve kapsamı mcp:all'dır. MCP sunucusu imza, verici, hedef kitle ve kapsamı doğrular ve kullanıcı kimliğini alır. Gelen burda biter. Bu token asla aşağı akışa gitmez.
② Servis kimliği. MCP sunucusu kendi M2M kimlik bilgileriyle, özel bir kapsamla bir erişim token’ı alır: access:mcp:api. Bu kapsamın tam bir amacı vardır: bir sonraki adımda ayrılmış bir uç noktayı çağırmak.
③ Konu token’ının istenmesi, tüm zincirin kilit adımıdır. MCP sunucusu POST /api/mcp/subject-tokens’ı çağırır; Cloud, MCP için özel olarak açtığı uç nokta, aynı anda iki kimlik bilgisi sunulur:
Authorization başlığı: M2M token’ı, "Ben resmi MCP sunucusuyum" kanıtı
x-mcp-user-token başlığı: Kullanıcı token’ı, "Bu kullanıcı bana yetki verdi ve yetki halen geçerli" kanıtı
Cloud, kullanıcı token’ını tam olarak doğrular: imza, verici, son kullanma, hedef kitle mutlaka MCP sunucusunun kaynak tanımlayıcısı olacak ve kapsamda mcp:all bulunmalı. Doğrulama sonrası userId doğrudan token’ın sub claim’inden gelir. Uç noktada ayrıca kullanıcı belirtme parametresi yoktur.
Bu tasarım M2M kimlik bilgisinin kötüye kullanılmasını önler. Uç nokta rastgele bir userId alsaydı, M2M kimliğe sahip herkes istediği kullanıcı gibi işlem yapabilirdi. Bu şekilde, MCP sunucusu ancak kullanıcının hali hazırda geçerli yetkisini gösteren bir token olduğunda onun adına kimlik bilgisi talep edebilir.
Verilen konu token’ı kısa ömürlü ve tek kullanımlıktır. Uygulama asla onu önbelleğe almaz ve her kullanım için yenisini ister.
④ Çalışma token’larına değişim. Konu token’ı ile, standart bir token değişimiyle iki tür token alınır:
Cloud API token’ı: Kullanıcı olarak yapılan üst düzey işlemler için (ör: kiracıları listele, kiracı oluştur)
Organizasyon token’ı: Hedef kiracıya özgü (Logto Cloud’daki her kiracı bir organizasyona denk gelir). Token kullanıcı olarak verilir ve izinleri, o kullanıcıya ait kiracıdaki rol ile aynıdır
⑤ Dışa çağrı. İş API’sini değişmiş token ile çağırın ve sonucu MCP istemcisine döndürün.
Çok kiracılı bağlam, değişim adımında çözülür: kiracı değişim katmanında yer alır, bağlantı katmanında değil. list_tenants, Cloud API token’ı ile seçenekleri listeler; kullanıcı konuşmada birini seçer; MCP sunucusu da seçilen kiracı için bir organizasyon token’ı ile değişim yapar. Tek bir uç nokta tüm kiracıları karşılar; kiracılar için ayrı ayrı konuşlandırmaya gerek yoktur; konuşma ortasında oluşturulan kiracı hemen görünür.
İlk yaklaşımlardaki başarısızlık noktalarıyla yeniden kıyaslarsak:
Kullanıcı token’ının etkisi sınırlanır (yaklaşım 1’in dersi): hedef kitlesi sadece MCP sunucusudur. Sızsa bile sadece o kontrollü araçlar çağrılır
M2M token’ı kötüye kullanılamaz (yaklaşım 2’nin dersi): artık iş API’sini doğrudan çağırmaz, sadece servis kimliği kanıtıdır. Konu token’ı almak için kullanıcıya ait geçerli token da gösterilmelidir, böylece MCP sunucusu yetki verdiği kullanıcılar için geçici kimlik bilgisi talep edebilir. Karmaşık vekil sorunu ortadan kalkar
Kullanıcı kimlik bilgisi saklanmaz: konu token’ları anında alınır, kullanıldıktan sonra atılır. MCP sunucusu sadece kendi M2M kimlik bilgilerini tutar
İptal doğrudan bağlantılı: Kullanıcı MCP yetkilendirmesini geri çekince kullanıcı token’ı geçersizleşir, x-mcp-user-token kontrolü başarısız olur, dışa zincir orada biter
İzinler kullanıcıya göre hizalı: değişen token’lar kullanıcı olarak verilir. Sadece okuma yetkisi olan kullanıcı, MCP’de de sadece okuma yetkisiyle kalır; ayrıcalık yükseltme kimlik doğrulama sunucusu katmanında başarısız olur. Denetim kayıtlarında da gerçek kullanıcı görünür
Geriye bakınca, nihai tasarımda M2M kimliğinin görevi yerine oturur: kim olduğumu kanıtlarım, ama "kullanıcı gibi hareket etme yetisi" ancak kullanıcının geçerli yetkisiyle anlık olarak değişimle elde edilir.
Tüm zincire bakınca, uzak bir MCP sunucusu için token stratejisi şu noktalara dayanır:
Gelen ve giden iki farklı kimlik doğrulama ayağıdır; MCP token’ının hedef kitlesi kesinlikle MCP sunucusu olmalıdır
Giden, token değişimi ile çözülür: kimlik doğrulama sunucunuz gelen token’ı doğrudan değişebiliyorsa, standart token değişim mekanizması yeterlidir; yoksa (örneğin Logto'nunkinde değişim, konu token’ı girdisiyle başlıyor) sunucu tarafında taklit tarzı bir özellikle değişimi başlatın
Çok kiracılılık mekanizmayı değiştirmez. Organizasyon bağlamı değişim sırasında bir parametredir; tek kiracılı ürünler adımı atlar
Yapay zeka kullanıcı adına hareket eder; dolayısıyla aşağı akıştaki token izinleri mutlaka kullanıcı yetkileriyle sınırlanmalıdır
Basit test: MCP istemcisinin taşıdığı token sızsa, bir saldırganın yapabileceği tek şey, MCP sunucusundaki kontrollü araçları, yine kullanıcının izinleriyle çağırmak olmalıdır. Doğrudan tüm API’ye ulaşabiliyorsa izin sınırı bozulmuş demektir.
MCP ekosistemi hâlâ hızla gelişiyor. Gelen kimlik doğrulama standartta iyi tanımlanmış; ama "MCP sunucusu aşağı akışı nasıl çağıracak" hâlâ her ekibin çözümüne kalmış. Umarız bizim uygulamamız size faydalı bir referans sağlar.