Phase 13: Tools & Protocols

बिना नागरिकता प्रोटोकॉल पर एमसीपी एप्लिकेशन

एक इंटरैक्टिव परिणाम अभी भी एक एमसीपी उपकरण और संसाधन विनिमय है। 2026-07-28 कोर उस विनिमय को आत्मनिर्भर बनाता है, जबकि ऐप्स एक्सटेंशन सैंडबॉक्स ब्राउज़र सतह जोड़ता है।

Type: Build

Languages: Python

Prerequisites: Phase 13 · 07 (MCP server), Phase 13 · 10 (resources)

Time: ~75 minutes

सीखने के लक्ष्य

  • के माध्यम से MCP Apps का विज्ञापन करेंserver/discoverऔर अनुरोध पर विस्तार क्षमताएं।
  • एक घोषित करें ui://उपकरण को बुलाए जाने से पहले किसी उपकरण पर संसाधन।
  • 2026-07-28 के बिना राज्य के तार पर पूर्ण उपकरण और संसाधन परिणाम लौटाएं।
  • एप्लिकेशन को अलग करें ui/initializeहटाए गए एमसीपी कोर से ब्रिज संदेश।
  • मूल सत्यापन, सैंडबॉक्सिंग, सीएसपी और न्यूनतम विशेषाधिकार अनुमतियों का उपयोग करें।

समस्या

एक पाठ परिणाम एक समयरेखा का वर्णन कर सकता है। यह उपयोगकर्ता को एक समयरेखा नहीं दे सकता है जिसे वे फ़िल्टर, निरीक्षण या कार्रवाई कर सकते हैं।

MCP Apps एक वैकल्पिक विस्तार के साथ प्रस्तुति समस्या को हल करता है। एक उपकरण परिभाषा एक ui://संसाधन. होस्ट उपकरण चलाने से पहले उस संसाधन को प्राप्त और समीक्षा कर सकता है, इसे सैंडबॉक्स में प्रस्तुत कर सकता है, और JSON-RPC पुल के माध्यम से सभी ऐप कार्यों का मध्यस्थता कर सकता है।

2026-07-28 में मूल प्रोटोकॉल बदल गया। पुराने कनेक्शन जीवन चक्र में ऐप को नहीं लपेटेंः

  • कोई कोर नहीं है initializeअनुरोध या notifications/initializedअधिसूचना।
  • कोई नहीं हैMcp-Session-Idहेडर.
  • प्रत्येक अनुरोध प्रोटोकॉल संस्करण और ग्राहक क्षमताओं को params._meta. .
  • सर्वर कार्यान्वयन server/discoverतो ग्राहकों को संस्करणों, कोर क्षमताओं, और एक्सटेंशन का निरीक्षण कर सकते हैं।
  • प्रत्येक सफल परिणाम का एक परिणाम होता हैresultTypeभेदभाव करने वाला।
  • स्ट्रीम करने योग्य HTTP प्रत्येक अनुरोध पर एक POST का उपयोग करता है। आधुनिक GET और DELETE प्रवेश बिंदु 405 लौटते हैं।

एप्लिकेशन ब्रिज में अभी भी एक विधि है जिसका नाम है ui/initializeयह iframe पोस्ट मैसेज बोली का है. यह एक कोर MCP सत्र को पुनः नहीं बनाता है.

अवधारणा

दो प्रोटोकॉल, एक सुविधा

परतों को स्पष्ट रखेंः

  1. एमसीपी कोर में server/discover,tools/list,tools/call,resources/listऔर resources/read. .
  2. MCP Apps एक्सटेंशन UI को घोषित करता है और iframe-to-host bridge को परिभाषित करता है।
  3. ब्राउज़र सैंडबॉक्स नियम सीमाएँ जो UI तक पहुँच सकते हैं.

विस्तार पहचानकर्ता io.modelcontextprotocol/ui. दोनों समकक्षों में शामिल हो जाते हैं. एक क्लाइंट प्रत्येक अनुरोध पर क्षमताओं ऑब्जेक्ट के भीतर विस्तार समर्थन भेजता हैः

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"
      }
    }
  }
}

clientInfoयह स्व-रिपोर्ट किए गए डेटा हैं, प्राधिकरण की पहचान नहीं है।

प्रतिपादन से पहले खोजें

सर्वर का खोज परिणाम विस्तार का विज्ञापन करता हैः

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"
    }
  }
}

सर्वर को डिस्कवरी का समर्थन करना चाहिए। क्लाइंट को प्रत्येक क्रिया से पहले डिस्कवरी को कॉल करने के लिए मजबूर नहीं किया जाता है क्योंकि प्रत्येक क्रिया में अपनी क्षमताएं होती हैं।

उपकरण परिभाषा पर UI को घोषित करें

आधुनिक अनुप्रयोग अनुबंध उपकरण के लिए एक UI बंधन में tools/list:

json{
  "name": "notes_timeline",
  "description": "Render a timeline of notes.",
  "inputSchema": {
    "type": "object",
    "properties": {}
  },
  "_meta": {
    "ui": {
      "resourceUri": "ui://notes/timeline.html"
    }
  }
}

यह जानबूझकर पूर्व-कॉल मेटाडेटा है। होस्ट HTML को प्रीलोड, कैश और सुरक्षा-समीक्षा कर सकता है इससे पहले कि कोई परिणाम इसे प्रदर्शित करने के लिए कहे। पुराने फ्लैट मेटाडेटा कुंजी संगतता कोड द्वारा स्वीकार की जा सकती है, लेकिन नए सर्वर को निस्ट किए गए को उत्सर्जित करना चाहिए _meta.ui.resourceUriफॉर्म।

tools/listवर्तमान कोर में कैश करने योग्य है। निर्धारक क्रम शामिल है,ttlMsऔर cacheScopeउपयोग करेंprivateजब दृश्यमान उपकरण उपयोगकर्ता या टोकन के अनुसार भिन्न होते हैं।

डेटा वापस, तो मेजबान दृश्य को बांधने दें

उपकरण कॉल सामान्य सामग्री और संरचित डेटा लौटाता हैः

json{
  "resultType": "complete",
  "content": [
    {"type": "text", "text": "Timeline ready."}
  ],
  "structuredContent": {
    "notes": [
      {"id": "note-1", "title": "Discover", "created": "2026-07-28"}
    ]
  },
  "isError": false
}

होस्ट पहले से ही जानता है कि उपकरण का कौन सा दृश्य है। यूआरआई को दोहराने के लिए एक नया सामग्री ब्लॉक का आविष्कार करने से बचें।

ऐप को संसाधन के रूप में सेवा करें

सर्वर विज्ञापन देता है resourcesयह भी अनिवार्य हैresources/listऑपरेशन. इसकी निर्धारात्मक सूची प्रविष्टि में कैनोनिक यूआरआई, एक स्थिर नाम, विवरण और एमआईएमई प्रकार शामिल है। सूची परिणाम में शामिल हैं resultType, सर्वर पहचान मेटाडेटा, ttlMsऔर cacheScope, ठीक वैसा ही निर्धारक उपकरण सूची की तरह.

मेजबान भेजता है resources/read. स्ट्रीम करने योग्य HTTP पर, अनुरोध में हैः

textPOST /mcp
MCP-Protocol-Version: 2026-07-28
Mcp-Method: resources/read
Mcp-Name: ui://notes/timeline.html

हेडर मान और JSON-RPC शरीर मेल खाना चाहिए. एक असंगत प्रोटोकॉल त्रुटि है -32020. .

परिणाम में HTML संसाधन और कैश सुझाव शामिल हैंः

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"
}

निष्पादित सामग्री के रूप में UI संसाधनों को कैश करें

एक ऐप संसाधन सामान्य प्रोसा के साथ आदान-प्रदान योग्य नहीं है। इसका कैश प्रविष्टि ब्रिज कोड निष्पादित कर सकती है, टूल डेटा प्रस्तुत कर सकती है, और होस्ट-मध्यस्थ कार्यों का अनुरोध कर सकती है। इसे कैनोनिकल द्वारा कुंजीकृत करें ui://यूआरआई, स्वीकार किए गए सर्वर पहचान और संस्करण, संसाधन सामग्री डाइजेस्ट, और प्राधिकरण संदर्भ जब cacheScopeकभी भी प्राइवेट ऐप संसाधन का उपयोग प्रिंसिपल के बीच न करें क्योंकि एचटीएमएल या इसकी नीति मेटाडेटा भिन्न हो सकते हैं भले ही यूआरआई समान हो।

प्रविष्टि को अमान्य करें जब यह ttlMsसमाप्त हो जाता है, उपकरण के _meta.ui.resourceUriबाध्यकारी परिवर्तन, सर्वर संस्करण या स्वीकार किए गए वर्णक पिन परिवर्तन, या एक मान्यता प्राप्त संसाधन-बदला सदस्यता URI नामों. पुनः स्थापना से पहले CSP और अनुमति समीक्षा को फिर से लागू करें। एक पुराने iframe को केवल इसलिए व्यापक अनुमतियां नहीं रखनी चाहिए क्योंकि एक नया संसाधन संस्करण अभी तक लोड नहीं हुआ है।

फीचर नीति से पहले तार अस्पष्टता को अस्वीकार करें

सत्यापन में एक जानबूझकर आदेश होता है। पहले JSON-RPC आकार को मान्य करें और स्ट्रिंग प्रोटोकॉल मेटाडेटा और ऑब्जेक्ट क्लाइंट क्षमता मानचित्र की आवश्यकता होती है। इसके बाद रूटिंग हेडर को शरीर के साथ तुलना करें। केवल तब तय करें कि क्या मैच प्रोटोकॉल संस्करण समर्थित है। यह आदेश प्रॉक्सी और सर्वर को विभिन्न अनुरोधों की व्याख्या करने से रोकता है।

ConditionHTTPJSON-RPC error
Header and body version, method, or name disagree400-32020
Header and body agree on an unsupported version400-32022, with data exactly {"supported":["2026-07-28"],"requested":"<actual>"}
resources/read lacks the Apps extension capability400-32021, with data.requiredCapabilities.extensions.io.modelcontextprotocol/ui
Method is unknown404-32601

JSON-RPC सूचना में कोई idएक स्वीकार किए गए HTTP अधिसूचना 202 को एक खाली शरीर के साथ लौटाता है। एक त्रुटि HTTP स्थिति बदल सकती है, लेकिन यह अभी भी एक अधिसूचना के लिए एक JSON-RPC त्रुटि शरीर नहीं बना सकता है।

रेत बॉक्स एक सीमा है, एक विश्वास निर्णय नहीं

एक होस्ट iframe को नियंत्रित करता है. ऐप सीधे होस्ट कुकीज़, स्थानीय भंडारण, या पृष्ठ DOM को नहीं पढ़ सकता है. सभी विशेषाधिकार प्राप्त काम को पुल पार करना होगा।

इन डिफ़ॉल्ट का उपयोग करेंः

  • सभी सीएसपी डोमेन सूचियों को खाली छोड़ दें, फिर केवल मूल जोड़ें ऐप की जरूरत है। उपयोग connectDomainsलाना, XHR, और WebSocket के लिए; उपयोग resourceDomainsस्क्रिप्ट, शैलियों, छवियों और फ़ॉन्ट के लिए।
  • कोड और डेटा बंडल करें जब संभव हो।
  • जब तक किसी दृश्य सुविधा की आवश्यकता नहीं होती, तब तक कोई कैमरा, माइक्रोफोन या स्थान अनुमतियां नहीं मांगें।
  • पिन postMessageसटीक समकक्ष मूल के लिए और अन्य सभी मूल से घटनाओं को अस्वीकार।
  • उपकरण तर्कों, उपकरण परिणामों, संसाधन पाठ और पुल संदेशों को अविश्वसनीय इनपुट के रूप में व्यवहार करें।
  • उपयोगकर्ता की सहमति मेजबान में रखें. iframe अपनी परिणामी कार्रवाई को स्वीकृति नहीं दे सकता है।

एक निश्चित नकल न करें sandboxप्रत्येक मेजबान में एक ट्यूटोरियल से विशेषता। मेजबान को ऐप के मूल मॉडल और इसके अपने अलग-अलग डिजाइन के आधार पर ध्वज चुनना होगा।

एक अनुमत डोमेन अभी भी एक निष्फलता पथ है।connectDomains: ["https://api.example.com"]इसका मतलब है कि एप्लिकेशन के अंदर निष्पादित होने वाला कोई भी स्क्रिप्ट वहां अनुमति प्राप्त डेटा भेज सकता है। मूल के सटीक मिलान से गंतव्य भ्रम से बचा जाता है, लेकिन यह तय नहीं करता है कि उपभोग्य भार उपयुक्त है या नहीं। डिफ़ॉल्ट रूप से कनेक्ट एक्सेस खाली रखें, iframe में धारक टोकन लगाने से बचें, जब व्यावहारिक हो, तो होस्ट के माध्यम से प्रॉक्सी संकीर्ण संचालन, प्रतिक्रिया और अनुरोध आकार को सीमित करें, और ऑडिट करें कि प्रत्येक आउटबाउंड अनुरोध के कारण उपयोगकर्ता की कार्रवाई क्या थी। उपचारresourceDomainsअलग से connectDomains; फ़ॉन्ट या स्क्रिप्ट को लोड करने की अनुमति किसी भी तरह के डेटा अपलोड को अनुमति नहीं देनी चाहिए।

एप्लिकेशन ब्रिज की अपनी जीवन चक्र है

अनुप्रयोगों पुल एक JSON-RPC बोली है postMessage. यह आदान-प्रदान कर सकते हैं .ui/initializeऔर ui/*सूचनाओं और कर सकते हैं प्रॉक्सी कोर-देखने के तरीकों जैसे tools/call. .

दृश्य भेजता है ui/initializeके साथappInfoऔर एक appCapabilitiesवस्तु. मेजबान अपनी क्षमताओं और मेजबान संदर्भ लौटाता है. केवल उस प्रतिक्रिया के बाद दृश्य भेजता है ui/notifications/initialized. मेजबान को दृश्य पर संदेश भेजने से पहले इस एप्लिकेशन सूचना का इंतजार करना होगा.

यह स्थानीय हैंडशैक एक iframe और एक होस्ट फ्रेम के बीच एक पुल बनाता है। यह MCP प्रोटोकॉल संस्करण पर बातचीत नहीं करता है, सर्वर राज्य बनाता है, या परिवहन सत्र का निर्माण नहीं करता है। सटीक पूर्वावलोकन देखेंः कोर notifications/initializedहटा दिया गया था, जबकि Apps ui/notifications/initializedएक पूल उपकरण कॉल द्वारा उत्पन्न एक कोर अनुरोध एक नया स्वयं-निहित अनुरोध है जिसमें एक नया JSON-RPC आईडी और पूर्ण अनुरोध मेटाडेटा है।

मेजबान संदर्भ, क्रियाएँ और निरसन

मेजबान पुल आरंभिकरण के बाद प्राधिकरण बना रहता है। एक दृश्य केवल मेजबान द्वारा विज्ञापित क्षमता के माध्यम से एक उपकरण कार्रवाई, नेविगेशन, क्लिपबोर्ड उपयोग या अन्य विशेषाधिकार प्रभाव का अनुरोध कर सकता है। मेजबान टाइप किए गए अनुरोध, वर्तमान उपयोगकर्ता, लक्ष्य और तर्कों को मान्य करता है, अनुमोदन नीति लागू करता है, और इसे अस्वीकार कर सकता है। एक बटन क्लिक और एक मान्य पुल संदेश व्यक्त इरादा; कोई भी प्राधिकरण प्रदान नहीं करता है।

एक बार में प्रस्तुत इनपुट के बजाय विषय, आकार और पहुंच को होस्ट संदर्भ में परिवर्तन के रूप में देखेंः

  • होस्ट द्वारा प्रदान किए गए रंग और टाइपोग्राफी टोकन लागू करें, फिर विषय या विपरीत प्राथमिकता में परिवर्तन होने पर प्रतिक्रिया करें।
  • दृश्य को वांछित आयामों की रिपोर्ट करने दें, लेकिन होस्ट कैप और iframe आकार लागू करने दें ताकि सामग्री अपने लेआउट से बच न सके या भ्रामक ओवरले न बनाए।
  • आईफ़्रेम के अंदर कीबोर्ड क्रम, दृश्य फोकस, सुलभ नाम, स्क्रीन रीडर स्थिति, पर्याप्त कंट्रास्ट, ज़ूम और कम गति वाला व्यवहार बनाए रखें।
  • आकार बदलने और पुनः प्रस्तुत करने के बाद होस्ट नियंत्रण और दृश्य नियंत्रण के बीच फोकस स्थानांतरण का पुनः परीक्षण करें।

ऐप के खुले होने पर क्षमताओं को रद्द किया जा सकता है क्योंकि उपयोगकर्ता खाता बदलता है, नीति बदलता है, सर्वर को संगरोध में रखा जाता है, या होस्ट सहमति को संकुचित करता है। कार्रवाई के समय क्षमता और प्राधिकरण की जांच करें, न कि केवल दौरान।ui/initialize. निरस्त होने पर, प्रत्याशित विशेषाधिकार प्राप्त कॉल को अस्वीकार करना, नेटवर्क गतिविधि को रोकना जो अब नीति से मेल नहीं खाती है, संवेदनशील रेंडर की गई स्थिति को साफ करना, और जब UI संसाधन स्वयं को अब स्वीकार नहीं किया जाता है तो पाठ को फिर से स्थापित करना या वापस आना। एक दृश्य को अस्वीकृति को सामान्य परिणाम के रूप में संभालना चाहिए, जब तक होस्ट नहीं देता तब तक पुनः प्रयास नहीं करना चाहिए।

रिटर्न अनुबंध का हिस्सा है

एक Apps-aware सर्वर अभी भी होस्ट की सेवा कर सकता है जो UI एक्सटेंशन का विज्ञापन नहीं करते हैंः

  • बिना के समान उपकरण लौटाएँ_meta.uiमें tools/list. .
  • के लिए उपयोगी पाठ परिणाम रखेंtools/call. .
  • मना कर दोresources/readएक अनुपस्थित क्षमता त्रुटि के साथ UI के लिए।
  • यह कभी भी न मानें कि उपकरण पूरा हो गया है या नहीं, यह तय करते समय एक iframe मौजूद है।

इसे बनाओ

code/main.pyयह एक SDK के बिना एक छोटे से प्रक्रिया में प्रोटोकॉल मॉडल बनाता है। यह वर्तमान अनुरोध कूपन और Streamable HTTP रूटिंग मानों को मान्य करता है, विज्ञापन अनुप्रयोगों के माध्यम से server/discover, उपकरण और संसाधनों की सूची देता है, उपकरण निष्पादित करता है, और एक स्वतंत्र HTML संसाधन की सेवा करता है।

मॉडल पहले से ही विश्लेषणित निकायों और रूटिंग हेडर प्राप्त करता है। यह एक पूर्ण HTTP एडाप्टर नहीं है और विश्लेषण नहीं करता है Content-Typeया Accept. पाठ 09 का उपयोग पूर्ण Streamable HTTP एडाप्टर के लिए जो आवश्यकता होती है के लिए Content-Type: application/jsonऔर एक Acceptदोनों को युक्त मूल्य application/jsonऔर text/event-stream. .

इसे चलाओः

bashcd phases/13-tools-and-protocols/14-mcp-apps
python3 code/main.py
python3 -m unittest discover code/tests -v

आउटपुट में चार चीजों की जांच करेंः

  1. हर कॉल स्वतंत्र है।
  2. हर अनुरोध है_metaक्षमताओं।
  3. resources/listकिसी भी संसाधन को पढ़ने से पहले एक स्थिर वर्णक लौटाता है।
  4. हर परिणाम मेंresultTypeऔर सर्वर पहचान मेटाडेटा।
  5. कोई कोर सत्र पहचानकर्ता दिखाई नहीं देता है।

इसका प्रयोग करें

से शुरू करेंserver/discoverपुष्टि करेंio.modelcontextprotocol/uiसर्वर विस्तार मानचित्र में दिखाई देता है. फिर कॉल tools/listएक बार एप्लिकेशन क्षमता के साथ और एक बार इसके बिना। पहला जवाब संसाधन घोषित करता है। दूसरा केवल पाठ के लिए उपयोग करने योग्य उपकरण बना रहता है।

पढ़िए ui://notes/timeline.html. HTML खोजेंhostOriginऔर event.originवे दो पंक्तियाँ न्यूनतम दृश्यमान प्रमाण हैं कि पुल एक वाइल्डकार्ड लक्ष्य का उपयोग नहीं करता है।

इसे भेजें

यह सबक जहाजों outputs/skill-mcp-apps-spec.md. इसे फ्रेमवर्क कोड लिखने से पहले ऐप अनुबंध की समीक्षा करने के लिए उपयोग करें। यह लेखक को वर्तमान कोर आवरण, विस्तार बातचीत, बैकअप, UI संसाधन, कैश नीति, CSP, अनुमतियां, पुल विधियां और सहमति सीमा निर्दिष्ट करने के लिए मजबूर करता है।

व्यायाम

  1. रिक्त विस्तार मानचित्र पर क्लाइंट क्षमता बदलें. पुष्टि tools/listउपकरण को बनाए रखता है लेकिन UI बंधन को हटा देता है।
  2. भेजेंMcp-Name: ui://notes/other.htmlएक शरीर के साथ जो समय रेखा पढ़ता है। त्रुटि की पुष्टि करें-32020. .
  3. संसाधन को में बदलेंcacheScope: private. उपयोगकर्ता विशिष्ट स्थिति का वर्णन करें जो इसे उचित ठहराती है।
  4. स्क्रिप्ट को पर ले जाएँhttps://static.example.com/app.js. उस मूल को जोड़ें resourceDomainsऔर नई आपूर्ति श्रृंखला जोखिम की व्याख्या।
  5. एक जोड़ें notes_openउपकरण और रूट बटन होस्ट के माध्यम से क्लिक करें. होस्ट में उपयोगकर्ता अनुमोदन रखें.

प्रमुख शर्तें

TermMeaning
MCP AppsOptional extension for interactive HTML rendered by an MCP host
io.modelcontextprotocol/uiExtension identifier advertised by both peers
ui://Resource scheme for an App's UI template
text/html;profile=mcp-appMIME type for MCP App HTML
server/discoverCurrent RPC for protocol and capability discovery
resources/listMandatory resource listing method when the server advertises resources
resultTypeRequired discriminator for modern successful results
ui/initializeFirst Apps bridge request, separate from removed core initialization
ui/notifications/initializedApps View readiness notification sent after the host responds
CSPBrowser policy that restricts scripts, styles, images, and network origins
Text fallbackTool behavior retained for a host without Apps support

आगे पढ़ना

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.