Ülkesizler Protokolü Üzerindeki MCP Uygulamaları
Type: Build
Languages: Python
Prerequisites: Phase 13 · 07 (MCP server), Phase 13 · 10 (resources)
Time: ~75 minutes
Öğrenme Hedefleri
- MCP Uygulamalarını üzerinden reklamlandırın
server/discoverve talep üzerine uzatma yetenekleri. - Bir
ui://Bir araç çağrılmadan önce bir araç üzerinde kaynak kullanmak. - 2026-07-28'deki devletsiz tel üzerinde tüm araç ve kaynak sonuçlarını geri gönderin.
- Uygulamaları Ayrılayın
ui/initializeKaldırılmış MCP çekirdeği el sıkışmasından gelen köprü mesajı. - Kaynak doğrulama, kum kutu, CSP ve en az ayrıcalıklı izinler uygulayın.
Sorun
Metin sonucu bir zaman çizgisini tanımlayabilir. Kullanıcıya filtreleyebilir, kontrol edebilir veya hareket edebilecek bir zaman çizgisini veremez.
MCP Apps, sunum sorunuyu seçmeli bir uzantı ile çözüyor.ui://Kullanıcı, araç çalıştırılmadan önce bu kaynağı alabilir ve gözden geçirebilir, sandboxed iframe'de görüntüleyebilir ve tüm uygulama eylemlerini JSON-RPC köprü üzerinden aracılık edebilir.
2026-07-28'de temel protokol değiştirildi.
- Yüklü bir çekirdek yok .
initializetalebiniz veyanotifications/initializedbildirim. - - Hayır .
Mcp-Session-IdBaşlık. - Her talepte protokol versiyonu ve istemci özellikleri bulunmaktadır.
params._meta- Evet . - Bir sunucu uygulaması
server/discoverBöylece müşteriler versiyonları, temel özellikleri ve uzantıları kontrol edebilirler. - Her başarılı sonuç bir
resultTypeayrımcılık. - Akışlanabilir HTTP, istek başına bir POST kullanır. Modern GET ve DELETE giriş noktaları 405'i gönderir.
Apps köprüde hala adı verilen bir yöntem var ui/initializeİframe mesaj sonrası diyaloguna aittir.
Anlaşım
İki protokol, bir özellik
Katmanları açık tut:
- MCP çekirdeği taşıyor
server/discover- Evet .tools/list- Evet .tools/call- Evet .resources/listveresources/read- Evet . - MCP Apps uzantısı kullanıcı aracını açıklar ve iframe-host köprüsünü tanımlar.
- Tarayıcı sandbox kuralları kullanıcı aracının ulaşabildiğini sınırlıyor.
Uzatma tanımlayıcısı io.modelcontextprotocol/uiHer bir istek için bir istemci, özellikler nesnesinin içinde uzantı desteği gönderir:
json{
"jsonrpc": "2.0",
"id": 1,
"method": "server/discover",
"params": {
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/ui": {}
}
},
"io.modelcontextprotocol/clientInfo": {
"name": "timeline-host",
"version": "1.0.0"
}
}
}
}clientInfoBu, kendiliğinden bildirilen veriler, yetki kimliği değil.
Yükleme öncesi keşfet
Sunucunun keşif sonucu uzantıyı reklam eder:
json{
"resultType": "complete",
"supportedVersions": ["2026-07-28"],
"capabilities": {
"tools": {},
"resources": {},
"extensions": {
"io.modelcontextprotocol/ui": {}
}
},
"ttlMs": 300000,
"cacheScope": "public",
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "timeline-app-server",
"version": "2.0.0"
}
}
}Sunucu keşif desteklemesi gerekir. Bir istemci her eylemden önce keşif çağrısı yapmak zorunda değildir çünkü her eylem kendi yeteneklerini taşır.
Araç tanımlamasında kullanıcı arayüzünü bildir
Modern Apps sözleşmesi bir UI 'yi araçla bağlar tools/list- ...
json{
"name": "notes_timeline",
"description": "Render a timeline of notes.",
"inputSchema": {
"type": "object",
"properties": {}
},
"_meta": {
"ui": {
"resourceUri": "ui://notes/timeline.html"
}
}
}Bu kasıtlı olarak çağrı öncesi metadata. Host, bir sonuç görüntülemesini istemekten önce HTML'i önceden yükleyebilir, önbelleğe kaydediyor ve güvenlik değerlendirmesini yapabilir. Eski düz metadata anahtarları uyumluluk kodu tarafından kabul edilebilir, ancak yeni sunucular yuvalanmış olan metadataları yayımlamalıdır._meta.ui.resourceUri- Şekil.
tools/list- Deterministik sıralama dahil,ttlMsvecacheScopeKullan .privateGörünen araçlar kullanıcı veya token'a göre değişirken.
Verileri geri gönderin, sonra konuksever görünümü bağlasın
Araç çağrısı sıradan içeriği ve yapılandırılmış verileri gönderir:
json{
"resultType": "complete",
"content": [
{"type": "text", "text": "Timeline ready."}
],
"structuredContent": {
"notes": [
{"id": "note-1", "title": "Discover", "created": "2026-07-28"}
]
},
"isError": false
}Ev sahibi, araçtan hangisinin görüntüsünü bildiğinden, URI'yi tekrarlamak için yeni bir içerik blokunun icat edilmesini önleyin.
Uygulama kaynak olarak kullan
Sunucu reklamlar yapıyor resourcesBu yüzden zorunlu olanları da uyguluyor.resources/listDeterministik listesi girişinde kanonik URI, sabit bir isim, açıklama ve MIME tipi bulunur.resultType, sunucu kimliği metadataları, ttlMsvecacheScope, tıpkı belirleyici araç listesi gibi.
Ev sahibi gönderir .resources/read. Streamable HTTP'de, talebin:
textPOST /mcp
MCP-Protocol-Version: 2026-07-28
Mcp-Method: resources/read
Mcp-Name: ui://notes/timeline.htmlBaşlık değerleri ve JSON-RPC vücudu eşleşmelidir.-32020- Evet .
Sonuç HTML kaynağı ve önbelleği ipuçları içerir:
json{
"resultType": "complete",
"contents": [
{
"uri": "ui: TOK0
"mimeType": "text/html;profile=mcp-app",
"text": "<!doctype html>...",
"_meta": {
"ui": {
"csp": {
"connectDomains": [],
"resourceDomains": [],
"frameDomains": [],
"baseUriDomains": []
},
"permissions": {}
}
}
}
],
"ttlMs": 60000,
"cacheScope": "public"
}Kullanılabilir içeriğe göre UI kaynaklarını önbelleğe koy
Bir uygulama kaynağı sıradan bir proza ile değiştirilmez. Kaş girişinin köprü kodu, araç verilerini göstermek ve host aracılığıyla eylemleri talep edebilmesi için kullanılabilir.ui://URI, kabul edilen sunucu kimliği ve sürümü, kaynak içeriği sindirme ve yetki bağlamıcacheScopeÖzel bir uygulama kaynağını asla başlıklar arasında yeniden kullanmayın çünkü HTML veya politika metadataları URI aynı olduğunda bile farklı olabilir.
Girişi geçersiz kılmak için ttlMsSonun geldiğinde, aletin kullanımı biter._meta.ui.resourceUriBağlayıcı değişiklikler, sunucu sürümü veya kabul edilen açıklayıcı pin değişiklikleri veya kabul edilen bir kaynak değiştirme aboneliği URI isimlerini değiştirir. Yeniden yüklenmeden önce CSP ve izin incelemesini yeniden uygulayın ve tekrar uygulayın. Eski bir iframe, yeni bir kaynak sürümü henüz yüklenmediği için daha geniş izinleri tutmamalıdır.
Özellik politikası öncesi kablo belirsizliklerini reddet
Validasyon, kasıtlı bir sıraya sahiptir. Önce JSON-RPC şeklini doğrulayın ve bir string protokol metadata ve nesne istemcisi yetenekleri haritasını gerektirin. Daha sonra yönlendirme başlıklarını vücut ile karşılaştırın. Sadece o zaman eşleşen protokol sürümünün desteklendiğine karar verin. Bu sırayla bir vekil ve sunucu farklı istekleri yorumlamayı engeller.
| Condition | HTTP | JSON-RPC error |
|---|---|---|
| Header and body version, method, or name disagree | 400 | -32020 |
| Header and body agree on an unsupported version | 400 | -32022, with data exactly {"supported":["2026-07-28"],"requested":"<actual>"} |
resources/read lacks the Apps extension capability | 400 | -32021, with data.requiredCapabilities.extensions.io.modelcontextprotocol/ui |
| Method is unknown | 404 | -32601 |
JSON-RPC bildirimi bulunmuyor idHTTP'nin kabul edilen bir bildirimi boş bir vücutla 202'yi gönderir. Bir hata HTTP durumunu değiştirebilir, ancak yine de bir bildirim için JSON-RPC hata vücudu oluşturulamıyor.
Kum kutusu bir sınır, güven kararı değil.
Bir host iframe'i kontrol eder. Uygulama doğrudan host çerezlerini, yerel depolama veya sayfa DOM'i okuyamıyor. Tüm ayrıcalıklı iş köprüden geçmelidir.
Bu öntanımlı seçenekleri kullan:
- Tüm CSP alan listelerini boş bırakın, sonra sadece uygulamanın ihtiyaç duyduğu kökenleri ekleyin. Kullan
connectDomainsGetch, XHR ve WebSocket için kullanınresourceDomainssenaryolar, stiller, resimler ve şriftler için. - Kullanılabilir olduğunda kod ve verileri birleştir.
- Görünen bir özelliğin bunu istemediği sürece kamera, mikrofon veya konum izinini istemeyin.
- Çubuk
postMessageTam eşcinsel kökenle ve diğer kökenlerden olan olayları reddetmek. - Araç argümanlarını, araç sonuçlarını, kaynak metnini ve köprü mesajlarını güvenilmeyen giriş olarak değerlendirin.
- Kullanıcı onayını ev sahibi içinde tutun. iframe kendi sonuç eylemini onaylayamaz.
Bir sabit kopyalama .sandboxEv sahibi, uygulamanın köken modeline ve kendi izole tasarımına göre bayraklar seçmelidir.
İzin verilen bir alan hala bir çıkış yolu.connectDomains: ["https://api.example.com"]Yani uygulamada çalıştırılan herhangi bir senaryo izin verilen verileri gönderebilir. Doğrudan eşleşme, destinasyon karışıklığını önler, ancak yararlı yükün uygun olup olmadığını belirlemez. Bağlantı erişimini varsayılan olarak boş tutun, iframe'ye taşıyıcı tokenlerinin yerleştirilmesini önleyin, pratik olduğunda host üzerinden proxy dar işlemleri, cevap ve talep boyutlarını sınırlayın ve her çıkış talebi hangi kullanıcı eyleminin neden olduğu denetlensin. Tedavi et .resourceDomainsayrı olarak connectDomains; Bir yazı tipi veya senaryo yükleme izninin keyfiyetli veri yüklemeyi sağlaması gerekmez.
Apps köprüsü kendi yaşam döngüsüne sahiptir .
Apps köprü JSON-RPC dili üzerinde postMessage- Değişimi yapabilir .ui/initializeve ui/*bildirimleri ve proxy gibi çekirdek görünümlü yöntemleri kullanabilir.tools/call- Evet .
Görüş gönderir ui/initialize- Evet .appInfove bir appCapabilitieshost özelliğini ve host bağlamını gönderir. Sadece bu cevabın ardından View gönderir ui/notifications/initializedEv sahibi, görüntülemeye mesaj göndermeden önce bu uygulama bildirimini beklemeli.
Bu yerel el sıkışması bir iframe ile bir host çerçeve arasında bir köprü oluşturur. MCP protokol versiyonunu müzakere etmez, sunucu durumunu oluşturmaz veya bir nakliye oturumunu oluşturmaz. Tam ön öncüye dikkat edin: çekirdek notifications/initializedApps ui/notifications/initializedKöprüli bir araç çağrısı tarafından oluşturulan bir temel talep, yeni bir JSON-RPC kimliği ve tam talep metadataları ile yeni bir bağımsız bir istektir.
Ev sahibi bağlamı, eylemler ve iptal
Host, köprü başlangıcından sonra yetki sahibi olmaya devam eder. Bir View, bir araç eylemini, gezintiyi, klipboyu kullanımı veya başka ayrıcalıklı bir etkiyi yalnızca host'ın reklamladığı bir yetenekle talep edebilir. Host, yazdırılmış talebi, mevcut kullanıcıyı, hedefi ve argümanları onaylar, onay politikasını uygulaır ve reddedebilir. Bir düğme tıklaması ve geçerli köprü mesajı açık niyet; hiçbirisi yetki vermez.
Bir kerelik render girişleri yerine konuyu, boyutunu ve erişilebilirliği sunucu bağlamını değiştirmek olarak değerlendirin:
- Host tarafından sağlanan renk ve tipografi belirtilerini uygulayın, sonra tema veya kontrast tercihleri değişince tepki gösterin.
- Görüntü istedikleri boyutları bildirsin, ancak host kapalı ve iframe boyutunu uygulayın, böylece içerik düzeninden kaçamaz veya yanıltıcı üstlükler oluşturabilir.
- Klavye düzenini, görünür odaklanmayı, erişilebilir isimleri, ekran okuyucu statüsünü, yeterli kontrastı, zoom ve iframe içinde az hareket davranışını korumak.
- Host kontrolleri ve View kontrolleri arasında odak aktarımını yeniden test edin boyut değiştirdikten ve yeniden gösterdikten sonra.
Uygulama açıkken yetenekler iptal edilebilir çünkü kullanıcı hesabı değiştirir, politika değişiklikleri, bir sunucu karantinaya alınır veya sunucu rızkı daraltır.ui/initialize. İptal olunca, bekleyen ayrıcalıklı çağrıları reddetmek, politikaya uygun olmayan ağ faaliyetini durdurmak, hassas gösterilen durumları temizlemek ve kullanıcı arayüzü kaynağı artık kabul edilmediğinde metine yeniden yüklemek veya geri dönmek. Bir Görüntü, reddedilmeyi normal bir sonuç olarak ele almalıyız, sunucu teslim olana kadar tekrar denememeliyiz.
- Bu sözleşmenin bir parçası.
Uygulamaları bilen bir sunucu hala UI uzantısını reklamlamayan sunucuları hizmet verebilir:
- Aynı aletleri olmadan geri gönderin
_meta.uiİçeridetools/list- Evet . - Kullanılabilir bir metin sonucu kaydet .
tools/call- Evet . - İtiraz
resources/readKayıp kapasite hatası olan kullanıcı aracına göre. - Araçın tamamlanıp bitmediğine karar verirken asla bir iframe var olduğunu düşünmeyin.
Yapın
code/main.pySDK olmadan küçük bir süreç protokol modeli oluşturur. Geçerli talep zarfını ve Akışlanabilir HTTP yönlendirme değerlerini doğruluyor, uygulamaları server/discover, araçları ve kaynakları listeler, araçları yürütür ve kendiliğinden bir HTML kaynağı hizmet verir.
Modelle zaten analiz edilmiş vücutlar ve yönlendirme başlıkları bulunmaktadır.Content-Typeveya Accept. Tüm Akışlanabilir HTTP adaptörü için Ders 09 kullanın .Content-Type: application/jsonve bir Accepther ikisini içeren değer application/jsonve text/event-stream- Evet .
Çek şunu:
bashcd phases/13-tools-and-protocols/14-mcp-apps
python3 code/main.py
python3 -m unittest discover code/tests -vÇıktıran dört şeyi kontrol edin:
- Her arama bağımsızdır.
- Her isteğin var .
_metayetenekleri. resources/listherhangi bir kaynak okumanın öncesinde sabit bir tanımlayıcı gönderir.- Her sonuçta
resultTypeve sunucu kimliği metadataları. - Ana seans kimliği görünmüyor.
Kullan
Başlayın .server/discover- İtiraf et .io.modelcontextprotocol/uiSunucu uzantısı haritasında görünmektedir.tools/listBirinci cevap kaynağı açıklar. İkinci bir kullanılabilir tek metin araç olarak kalır.
Oku ui://notes/timeline.htmlHTML ' i arayın .hostOriginve event.originBu iki çizgi köprüde bir wildcard hedefi olmadığını gösteren en az görünür bir kanıt.
Gönder
Bu ders gemileri outputs/skill-mcp-apps-spec.md. Framework kodu yazmadan önce bir uygulama sözleşmesini incelemek için kullanın. Yazarı mevcut çekirdek zarfı, uzantı müzakere, geri dönüş, UI kaynağı, önbelleği politikası, CSP, izinler, köprü yöntemleri ve onay sınırı belirtmesini zorlar.
Egzersizler
- Müşteri yeteneğini boş bir uzantı haritasına değiştir.
tools/listAraç tutar ama kullanıcı aracını bağlayamaz. - Gönder .
Mcp-Name: ui://notes/other.htmlZaman çizgisini okuyacak bir vücutla.-32020- Evet . - Kaynakı olarak değiştirin
cacheScope: private- Kullanıcıya özgü, bunu haklı çıkaran durumunu açıklayın. - Senaryoyu
https://static.example.com/app.jsBu kökeniresourceDomainsve yeni tedarik zinciri riskini açıklar. - Bir ekle
notes_openKullanıcı onayını host'ta tutun.
Anahtar Terimler
| Term | Meaning |
|---|---|
| MCP Apps | Optional extension for interactive HTML rendered by an MCP host |
io.modelcontextprotocol/ui | Extension identifier advertised by both peers |
ui:// | Resource scheme for an App's UI template |
text/html;profile=mcp-app | MIME type for MCP App HTML |
server/discover | Current RPC for protocol and capability discovery |
resources/list | Mandatory resource listing method when the server advertises resources |
resultType | Required discriminator for modern successful results |
ui/initialize | First Apps bridge request, separate from removed core initialization |
ui/notifications/initialized | Apps View readiness notification sent after the host responds |
| CSP | Browser policy that restricts scripts, styles, images, and network origins |
| Text fallback | Tool behavior retained for a host without Apps support |
Daha Fazla Okumak
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.