Phase 13: Tools & Protocols

برنامه های MCP در مورد پروتکل بی شهرت

یک نتیجه تعاملی هنوز یک ابزار MCP و مبادله منابع است. هسته 2026-07-28 باعث می شود که این مبادله مستقل باشد، در حالی که افزونه اپلیکیشن سطح مرورگر sandboxed را اضافه می کند.

Type: Build

Languages: Python

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

Time: ~75 minutes

اهداف یادگیری

  • تبلیغات اپلیکیشن های MCP را از طریق server/discoverو قابلیت های گسترش در صورت درخواست.
  • اعلامیه ایui://منابع روی یک ابزار قبل از اینکه ابزار را فراخوانید.
  • نتایج کامل ابزار و منابع را در سیم بی دولتی 2026-07-28 بازگردانید.
  • برنامه ها را جدا کنید ui/initializeپیام پل از دست دادن هسته MCP حذف شده.
  • استفاده از اعتبارنامه اصلی، sandboxing، CSP و مجوزهای کمترین امتیاز.

مشکل

یک نتیجه متن می تواند یک خط زمانی را توصیف کند. این نمی تواند به کاربر یک خط زمانی را بدهد که می تواند فیلتر، بررسی یا عمل کند.

MCP Apps مشکل ارائه را با یک تمدید اختیاری حل می کند.ui://میزبان می تواند قبل از اجرای ابزار، آن منبع را جمع آوری و بررسی کند، آن را در یک iframe sandboxed ارائه دهد و تمام اقدامات برنامه را از طریق یک پل JSON-RPC میانجیری کند.

پروتکل اصلی در سال 2026-07-28 تغییر کرد. برنامه ای را در چرخه عمر اتصال قدیمی بسته نکنید:

  • هسته ای وجود ندارهinitializeدرخواست یاnotifications/initializedاطلاع رسانی
  • هیچکس نیستMcp-Session-Idسرنخ
  • هر درخواست نسخه پروتکل و قابلیت های مشتری را در params._meta. .
  • یک سرور اجرا می کند server/discoverتا مشتریان بتوانند نسخه ها، قابلیت های اصلی و افزونه ها را بررسی کنند.
  • هر نتیجه موفق يه نتیجه دارهresultTypeتبعیضگر
  • HTTP قابل پخش از یک POST در هر درخواست استفاده می کند. نقاط ورود GET و DELETE مدرن 405 را باز می کنند.

پل اپلیکیشن هنوز روش ای داره که اسمش رو میگهui/initialize. به زبانه ی iframe postMessage تعلق داره . این یک جلسه MCP اصلی را بازنمی سازد

مفهوم

دو پروتکل، یک ویژگی

لایه ها رو واضح نگه داريد:

  1. هسته MCP حمل می کندserver/discover،tools/list،tools/call،resources/listوresources/read. .
  2. توسعه برنامه های MCP UI را اعلام می کند و پل iframe-to-host را تعریف می کند.
  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
}

میزبان قبلاً می داند که کدام نمای متعلق به ابزار است. از اختراع یک بلوک محتوای جدید برای تکرار URI اجتناب کنید.

به عنوان منبع اپلیکیشن استفاده کنید

سرور اعلان ميکنهresourcesدر کشف، بنابراین همچنین اجرای اجباریresources/listعملکرد. ورودی فهرست تعیین کننده آن شامل URI کانونیک، نام ثابت، توصیف و نوع MIME است. نتیجه لیست شامل resultType, متاداتا هویت سرور ,ttlMsوcacheScope، درست مثل لیست ابزار تعیین کننده

میزبان فرستادهresources/readدر HTTP Streamable، درخواست دارای:

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://URI، هویت و نسخه سرور مجاز، هضم محتوای منابع و زمینه مجوز زمانی که cacheScopeهرگز از یک منبع خصوصی اپلیکیشن در سراسر پرینترها استفاده نکنید زیرا HTML یا متاداتا های سیاست آن ممکن است حتی زمانی که URI یکسان باشد متفاوت باشد.

در صورت عدم اعتبار این ورودی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 را بخواند. تمام کارهای امتیاز یافته باید از پل عبور کنند.

از این پیش فرض ها استفاده کنید:

  • تمام لیست دامنه های CSP را خالی بگذارید، سپس فقط منابع مورد نیاز اپلیکیشن را اضافه کنید. استفاده کنید 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میزبان باید قبل از ارسال پیام به View منتظر این اطلاعیه برنامه باشد.

این دست دادن محلی یک پل بین یک iframe و یک host frame ایجاد می کند. این نسخه پروتکل MCP را مذاکره نمی کند، وضعیت سرور ایجاد نمی کند یا یک جلسه حمل و نقل ایجاد نمی کند. توجه به پیشگویی دقیق: هستهnotifications/initializedحذف شد و اپلیکیشن هاui/notifications/initializedیک درخواست اصلی که توسط یک تماس ابزار پل ایجاد شده است یک درخواست مستقل جدید با یک شناسه JSON-RPC جدید و متاداتا کامل درخواست است.

زمینه میزبان، اقدامات و لغو

میزبان پس از شروع کردن پل، مجوز باقی می ماند. یک View می تواند از یک اقدام ابزار، ناوبری، استفاده از کلپبورد یا دیگر اثر امتیازات فقط از طریق یک قابلیت که میزبان تبلیغ می کند درخواست شده را تأیید کند. میزبان درخواست تایپ شده، کاربر فعلی، هدف و استدلال را تأیید می کند، سیاست تأیید را اعمال می کند و ممکن است از آن رد کند. یک کلیک دکمه و یک پیام پل معتبر قصد بیان را نشان می دهد؛ هیچ یک از آنها مجوز را نمی دهد.

موضوع، اندازه و دسترسی را به عنوان تغییر زمینه میزبان به جای ورودی های یک بار نمایش داده کنید:

  • توکن های رنگ و تایپوگرافی ارائه شده توسط میزبان را اعمال کنید، سپس هنگامی که موضوع یا اولویت های تعارض تغییر می کند واکنش نشان دهید.
  • اجازه دهید نمایش ابعاد مورد نظر را گزارش کند، اما اجازه دهید میزبان را پوشش دهید و اندازه iframe را اعمال کنید تا محتوای نمی تواند از طرح خود فرار کند یا پوشش های فریبنده ایجاد کند.
  • حفظ ترتیب صفحه کلید، تمرکز قابل مشاهده، نام های قابل دسترسی، وضعیت خواننده صفحه، تعادل کافی، زوم و رفتار حرکتی کاهش یافته در داخل iframe.
  • انتقال تمرکز بین کنترل های میزبان و کنترل های View را پس از تغییر اندازه و تغییر رنگ دوباره آزمایش کنید.

قابلیت ها می توانند در حالی که اپلیکیشن باز است، به دلیل تغییر حساب، تغییر سیاست، قرنطینه سرور یا محدود کردن رضایت میزبان، لغو شوند. قابلیت ها و مجوزها را در زمان عمل بررسی کنید، نه تنها در زمان عمل.ui/initializeدر زمان فسخ، تماس های امتیاز یافته منتظر را رد کنید، فعالیت شبکه ای را که دیگر با سیاست ها مطابقت ندارد متوقف کنید، وضعیت حساس ارائه شده را پاک کنید و زمانی که خود منبع UI دیگر مجاز نیست، دوباره نصب یا به متن برگردید. یک View باید رد را به عنوان یک نتیجه عادی اداره کند، نه دوباره تلاش کند تا میزبان تسلیم شود.

بازپرداخت به قرارداد مربوطه

یک سرور آگاه از برنامه ها هنوز می تواند میزبان هایی را که توسعه UI را تبلیغ نمی کنند، خدمت کند:

  • بدون اون ابزار رو برگردونيد_meta.uiدرtools/list. .
  • یک نتیجه متن مفید را برای tools/call. .
  • ردش کنresources/readبرای UI با خطا قابلیت گمشده.
  • هرگز فرض نکنید که یک iframe وجود دارد در هنگام تصمیم گیری در مورد اینکه آیا ابزار تکمیل شده است.

آن را بسازید

code/main.pyیک مدل پروتکل کوچک در فرآیند بدون SDK ایجاد می کند. این پاکت درخواست فعلی و ارزش های روتینگ HTTP Streamable را تأیید می کند، برنامه ها را از طریق server/discover، ابزارها و منابع را لیست می کند، ابزار را اجرا می کند و یک منبع HTML مستقل را ارائه می دهد.

این مدل از قبل اجسام تجزیه شده و سرنخ های روتینگ را دریافت می کند. این یک آداپتور HTTP کامل نیست و تجزیه نمی کند Content-TypeیاAccept. درسي 09 را براي تمام آداپتور HTTP Streamable استفاده کنيد که نیاز داره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.