فاز 13 · درس 10

منابع و پرامپت‌ها در MCP: کانتکست آدرس‌پذیر برای سرورهای بی‌وضعیت

نوع
ساختنی
زمان
حدود 60 دقیقه
زبان‌ها
Python
نموداری ساختاریافته از سه جعبه با نمادهای فایل، آچار و قالب متن که با برچسب‌های متصل به سرور و کلاینت جریان داده را نشان می‌دهند
فهرست مطالب
  1. اهداف یادگیری
  2. از مصرف‌کننده شروع کنید
  3. بسته‌ی بی‌وضعیت ویرایش 2026-07-28
  4. منابع قراردادهای پایدار URI هستند
  5. قالب‌های منابع
  6. محتوا دستورالعمل قابل‌اعتماد نیست
  7. پرامپت‌ها قالب‌های تحت کنترل کاربر هستند
  8. راهنماهای کش بخشی از درستی عملکرد هستند
  9. اشتراک‌ها از استریم پاسخی استفاده می‌کنند که کلاینت باز کرده است
  10. کارگاه تعاملی
  11. تمرین عملی
  12. خروجی این درس
  13. اعتبارسنجی
  14. ارتباط با پروژه پایانی
  15. تمرین‌ها
  16. اصطلاحات کلیدی
  17. برای مطالعه‌ی بیشتر

در طراحی سرورهای مبتنی بر پروتکل کانتکست مدل (Model Context Protocol)، تفکیک وظایف اهمیت بسیار بالایی دارد. معمولاً این اشتباه رخ می‌دهد که هر نوع بازخوانی اطلاعات به شکل یک ابزار (Tool) یا پرامپت پیاده‌سازی می‌شود، در حالی که پروتکل MCP برای محتوای خواندنی و پایدار، سازوکار مشخصی به نام منابع (Resources) و برای جریان‌های کاری ساخت‌یافته، مفهوم پرامپت‌ها (Prompts) را در نظر گرفته است.

این درس به شما کمک می‌کند معماری تعامل مدل و سرور را بر مبنای قراردادهای بدون وضعیت (Stateless) تنظیم کنید. با درک نحوه‌ی اعلام قابلیت‌ها در متد `server/discover`، تعیین سیاست‌های امنیتی و راهنماهای کش، و پیاده‌سازی سیستم اشتراک رویدادها از طریق استریم‌های پایدار، سروری استاندارد، پیش‌بینی‌پذیر و ایمن می‌سازید که بدون وابستگی به تاریخچه‌ی اتصال کلاینت، پاسخ‌ها را با دقت بازمی‌گرداند.

ابزارها عملیات انجام می‌دهند. منابع محتوای آدرس‌پذیر را ارائه می‌دهند. پرامپت‌ها قالب‌های پیامِ انتخابی کاربر را بسته‌بندی می‌کنند. یک سرور MCP خوب این قراردادها را تفکیک‌شده و قابل‌پیش‌بینی نگه می‌دارد.

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

  • انتخاب درست میان ابزارها، منابع و پرامپت‌ها بر اساس نیت مصرف‌کننده.
  • اعلام دامنه‌ی منابع و پرامپت‌ها از طریق متد الزامی server/discover.
  • ساخت نتایج قطعی و تکرارپذیر برای resources/list و prompts/list.
  • به‌کارگیری ttlMs و cacheScope بدون نشت داده‌های اختصاصی کاربران.
  • بازگرداندن خطای JSON-RPC با کد -32602 برای URIهای نامعتبر یا ناشناخته‌ی منابع.
  • باز کردن استریم پاسخ POST برای subscriptions/listen و تطبیق هر رویداد با شناسه اشتراک.
  • برخورد با محتوای منابع و قالب‌های پرامپت به‌عنوان خروجی غیرقابل‌اعتمادِ سرور.

از مصرف‌کننده شروع کنید

راحت‌ترین راه برای استفاده‌ی نادرست از MCP این است که کار را با کد پیاده‌سازی شروع کنید. یک پرس‌وجوی دیتابیس تبدیل به ابزار می‌شود، صرفاً چون با مفهوم تابع آشنایید؛ یک گردش کارِ با قابلیت استفاده‌ی مجدد تبدیل به منبع می‌شود چون در یک فایل ذخیره شده است؛ و یک پرامپت تبدیل به سیاست‌های پنهان می‌شود چون میزبان می‌تواند آن را تزریق کند.

نقطه‌ی شروع باید این باشد: چه کسی انتخاب می‌کند و چه انتظاری دارد؟

مولفه‌ی پایه (Primitive) نیت اصلی چه کسی آن را انتخاب می‌کند؟ خروجی معمول
ابزار (Tool) انجام یک عملیات مدل یا برنامه کاربردی نتیجه‌ی ساختاریافته‌ی یک اقدام
منبع (Resource) خواندن محتوا در یک URI مشخص میزبان، برنامه یا کاربر محتوای متنی یا باینری
پرامپت (Prompt) شروع یک گردش کار پیامیِ قابل‌استفاده‌ی مجدد کاربر از طریق رابط کاربری میزبان یک یا چند پیام پرامپت

یک یادداشت در مسیر notes://note-1 یک منبع است، چون محتوایی آدرس‌پذیر است. delete_note یک ابزار است، چون وضعیت (state) را تغییر می‌دهد. review_note یک پرامپت است، چون کاربر یک گردش کارِ آماده‌ی بررسی را انتخاب می‌کند.

صرفاً برای اینکه همه‌چیز کامل به نظر برسد، یک عملیات را در قالب هر سه مولفه پیاده نکنید. هر سطح و رابط اضافه، نیازمند اکتشاف، تعیین سطح دسترسی، کش‌کردن، مدیریت خطا، تست و مستندسازی است.

بسته‌ی بی‌وضعیت ویرایش 2026-07-28

این درس نسخه‌ی 2026-07-28 پروتکل MCP را هدف قرار داده است. در این ساختار، هیچ دست‌دادن (handshake) برای مقداردهی اولیه یا نشست پروتکلی (protocol session) وجود ندارد. هر درخواست، نسخه‌ی پروتکل و قابلیت‌های کلاینتِ خود را در کلیدهای رزروشده‌ی _meta همراه دارد.

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "resources/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {
        "name": "course-client",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

پیاده‌سازی متد server/discover برای سرور الزامی است. خروجی این متد نسخه‌های پشتیبانی‌شده، قابلیت‌های منابع و پرامپت‌ها، هویت پیاده‌سازی و راهنماهای کش را اعلام می‌کند. کلاینت می‌تواند مستقیماً متد دیگری را فراخوانی کند، اما این اکتشاف پیش از ساخت رابط کاربری یک اسنپ‌شات پایدار در اختیارش می‌گذارد.

{
  "resultType": "complete",
  "supportedVersions": ["2026-07-28"],
  "capabilities": {
    "resources": {"listChanged": true, "subscribe": true},
    "prompts": {"listChanged": true}
  },
  "ttlMs": 3600000,
  "cacheScope": "public"
}

یک پاسخ عادی، وضعیت "resultType": "complete" را اعلام می‌کند. فیلد _meta در پاسخ، پیاده‌سازی ارائه‌دهنده را با io.modelcontextprotocol/serverInfo مشخص می‌کند. این اطلاعات برای عیب‌یابی مفید است، اما هویتی برای احراز هویت محسوب نمی‌شود. اگر درخواستی نسخه‌ای پشتیبانی‌نشده را ارسال کند، خطای -32022 همراه با نسخه‌ی درخواستی و نسخه‌های پشتیبانی‌شده‌ی سرور برگردانده می‌شود.

این قراردادِ بی‌وضعیت، درک شما را از طراحی تغییر می‌دهد. هیچ فهرستی نباید به فراخوانی پیشین در طول همان اتصال وابسته باشد. اعتبارسنجی ممکن است مجموعه‌ی قابل‌مشاهده را تغییر دهد چون اطلاعات هویتی ورودیِ درخواست هستند، اما تاریخچه‌ی اتصال نباید چنین تأثیری بگذارد.

منابع قراردادهای پایدار URI هستند

منبع، محتوایی است که با یک URI شناخته می‌شود. ساختار URI را پیش از نوشتن هندلر طراحی کنید.

ویژگی‌های یک URI مناسب:

  • به‌اندازه‌ی کافی پایدار باشد تا بتوان آن را بوکمارک کرد یا بین درخواست‌ها فرستاد.
  • در فضای نامِ (namespace) دامنه‌ی سرور تعریف شده باشد.
  • از شناسه‌ی پردازه (process ID) یا اتصال مستقل باشد.
  • پیش از دسترسی به فضای ذخیره‌سازی اعتبارسنجی شود.
  • در هر بار خواندن، سطح دسترسی آن بررسی شود.

آدرس notes://note-1 از note-1 بهتر است، چون فضای نام آن مشخص و صریح است. یک سرور فایل ممکن است از URIهای file:// استفاده کند، اما همچنان باید پس از حل کردن لینک‌های نمادین (symlinks) و بخش‌های نسبی مسیر، مرزهای دایرکتوری‌های مجازِ پیکربندی‌شده را بررسی کند.

متد resources/list منابعی را برمی‌گرداند که در حال حاضر برای فراخواننده قابل‌مشاهده هستند. خروجی را بر اساس یک کلید پایدار مثل URI مرتب کنید. این نظم قطعی مانع از دست رفتن بیهوده‌ی کش (cache misses)، تغییر اسنپ‌شات‌ها و پرش رابط کاربری میزبان بین تازه‌سازی‌ها می‌شود.

{
  "resultType": "complete",
  "resources": [
    {
      "uri": "notes://note-1",
      "name": "Architecture decision",
      "description": "Why the service uses a stateless boundary",
      "mimeType": "text/markdown"
    }
  ],
  "ttlMs": 300000,
  "cacheScope": "public",
  "_meta": {
    "io.modelcontextprotocol/serverInfo": {
      "name": "notes-server",
      "version": "2.0.0"
    }
  }
}

متد resources/read یک یا چند آیتم محتوایی را برمی‌گرداند. یک URI ناشناخته به معنی خواندنِ موفق یک محتوای خالی نیست. بر اساس مشخصات فعلی منابع در MCP، برای URIهای نامعتبر یا ناشناخته‌ی منابع، خطای پارامترهای نامعتبرِ JSON-RPC با کد -32602 در نظر گرفته شده است.

{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32602,
    "message": "Unknown or invalid resource URI",
    "data": {
      "uri": "notes://missing"
    }
  }
}

این تفکیک به کلاینت اجازه می‌دهد نبود سند را از یک سند معتبر اما خالی تشخیص دهد. همچنین از بازگشت ناخواسته‌ی سیستم به یک جست‌وجوی گسترده‌تر جلوگیری می‌کند.

قالب‌های منابع

یک قالب منبع (resource template)، خانواده‌ای از URIهای پارامتربندی‌شده را توصیف می‌کند. وقتی فهرست کردن تک‌تک آیتم‌های عینی هزینه‌بر یا بی‌پایان باشد، از قالب استفاده کنید. برای مثال، notes://projects/{project}/decisions/{decision} به کلاینت نشان می‌دهد چطور بدون نیاز به دریافت تک‌تک تصمیم‌ها، آدرس معتبری بسازد.

استفاده از قالب، اعتبارسنجی را ضعیف نمی‌کند. متغیرها را تجزیه کنید، اعتبارسنجی سطح دسترسی را اعمال کنید، محدودیت طول و کاراکترها را در نظر بگیرید و پرس‌وجوهای ذخیره‌سازی را با پارامترهای تایپ‌شده بسازید. هرگز بخش انتهاییِ دلخواه یک URI را مستقیماً به مسیر فایل‌سیستم یا دستور دیتابیس الحاق نکنید.

محتوا دستورالعمل قابل‌اعتماد نیست

متن منابع ممکن است حاوی تزریق پرامپت، داده‌های محرمانه، دستورات گمراه‌کننده یا نشانه‌گذاری‌های معیوب باشد. میزبان باید منشأ و سندیت را حفظ کند و با محتوای منبع صرفاً به عنوان داده برخورد کند. سرور نیز باید حجم محتوا را محدود کند، نوع MIME دقیق برگرداند، فیلدهایی را که فراخواننده به آن‌ها دسترسی ندارد پنهان کند و از بازگرداندن رکوردهای غیرمرتبط بپرهیزد.

پرامپت‌ها قالب‌های تحت کنترل کاربر هستند

پرامپت‌های MCP برای انتخاب صریح توسط کاربر طراحی شده‌اند. میزبان می‌تواند آن‌ها را در قالب دستورات اسلش (slash commands)، گزینه‌های منو یا دکمه‌های گردش کار نمایش دهد. پروتکل رابط کاربری خاصی را تحمیل نمی‌کند.

خروجی prompts/list برای یک درخواست با سطح دسترسی یکسان، باید همیشه قطعی و یکدست باشد. هر پرامپت به نامی پایدار، توضیحی مفید و تعریف آرگومان‌هایی نیاز دارد که به میزبان امکان دهد پیش از فراخوانی prompts/get، ورودی‌ها را جمع‌آوری کند.

{
  "resultType": "complete",
  "prompts": [
    {
      "name": "review_note",
      "title": "Review a note",
      "description": "Review one note for a named concern",
      "arguments": [
        {
          "name": "uri",
          "description": "The note resource URI",
          "required": true
        }
      ]
    }
  ],
  "ttlMs": 600000,
  "cacheScope": "public"
}

متد prompts/get آرگومان‌ها را به پیام تبدیل می‌کند، اما جایگزین دستورالعمل‌های سیستمی میزبان نمی‌شود. میزبان خودش تصمیم می‌گیرد پیام‌های برگشتی چگونه وارد زمینه‌ی مدل شوند و سیاست‌های معتبر خود را در اولویت بالاتری نگه می‌دارد.

آرگومان‌های پرامپت را در مرز ورودی سرور اعتبارسنجی کنید. URI پرامپت باید همان بررسی‌های دسترسیِ متد خواندن مستقیم منبع را پشت سر بگذارد. نگذارید پرامپت به کانالی فرعی برای دور زدن محدودیت‌های دسترسی به منابع تبدیل شود.

راهنماهای کش بخشی از درستی عملکرد هستند

فیلد ttlMs به کلاینت می‌گوید یک نتیجه تا چه مدت قابل‌استفاده‌ی مجدد است. فیلد cacheScope نیز مشخص می‌کند چه کسانی می‌توانند آن مقدار کش‌شده را به اشتراک بگذارند.

دامنه (Scope) معنی کاربرد معمول
public در صورت مجاز بودن دسترسی، می‌تواند بین کاربران مختلف استفاده شود کاتالوگ عمومی پرامپت‌ها
private محدود به کاربر یا بستر هویتیِ درخواست‌دهنده محتوای یادداشت متعلق به یک کاربر

مقدار TTL را بر اساس نرخ تغییر داده‌ها و میزان آسیبی که کهنگی داده وارد می‌کند تعیین کنید. برای مثال، 5 دقیقه ممکن است برای یک کاتالوگ عمومی پرامپت مناسب باشد؛ اما خواندن یک یادداشت شخصی شاید به 1 دقیقه زمان نیاز داشته باشد.

پروتکل MCP فقط public و private را به عنوان مقادیر مجاز برای cacheScope تعریف کرده است. برای نتایج حساس حاوی اطلاعات محرمانه یا نتایجی که به‌سرعت تغییر می‌کنند، مقدار cacheScope: "private" را همراه با ttlMs: 0 برگردانید و سپس قوانین سخت‌گیرانه‌ترِ عدم ذخیره‌سازی را در سیاست‌های کش میزبان اعمال کنید. خودِ no-store یکی از مقادیر معتبر cacheScope در MCP نیست.

راهنماهای کش هرگز جایگزین کنترل دسترسی نمی‌شوند. کلید کش باید شامل تمام ابعاد درخواست باشد که بر میزان دسترسی تأثیر می‌گذارند؛ از جمله شناسه مستأجر (tenant)، کاربر، دامنه، زبان و مکان (locale) و نشانگر صفحه‌بندی (cursor). اگر یک کش مشترک نمی‌تواند این ابعاد را با امنیت مدیریت کند، از دامنه‌ی private با TTL صفر و سیاست عدم ذخیره‌سازی در سطح میزبان استفاده کنید.

اشتراک‌ها از استریم پاسخی استفاده می‌کنند که کلاینت باز کرده است

الگوی مدرن اشتراک‌ها جایگزین متد قدیمی RPC با عنوان resources/subscribe و اندپوینت قدیمی رویدادها مبتنی بر HTTP GET شده است.

کلاینت متد subscriptions/listen را به عنوان یک درخواست عادی JSON-RPC ارسال می‌کند. در بستر Streamable HTTP، این یک درخواست POST است که پاسخ آن به عنوان یک استریم SSE باز می‌ماند. شیء notifications نقش یک لیست مجاز (allowlist) را دارد؛ سرور نباید رویدادهایی با انواعی که درخواست نشده‌اند ارسال کند.

{
  "jsonrpc": "2.0",
  "id": 17,
  "method": "subscriptions/listen",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "course-client",
        "version": "1.0.0"
      }
    },
    "notifications": {
      "resourcesListChanged": true,
      "promptsListChanged": true,
      "resourceSubscriptions": [
        "notes://note-1"
      ]
    }
  }
}

شناسه‌ی درخواست، همان شناسه اشتراک است. پیش از ارسال هر رویداد درخواست‌شده، سرور رویداد notifications/subscriptions/acknowledged را می‌فرستد. فیلتر موجود در این پیام تنها شامل زیرمجموعه‌ای است که سرور آن را پذیرفته است.

{
  "jsonrpc": "2.0",
  "method": "notifications/subscriptions/acknowledged",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 17
    },
    "notifications": {
      "resourcesListChanged": true,
      "resourceSubscriptions": [
        "notes://note-1"
      ]
    }
  }
}

تمام رویدادهای بعدی در آن استریم نیز همان متادیتا را با خود دارند.

{
  "jsonrpc": "2.0",
  "method": "notifications/resources/updated",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 17
    },
    "uri": "notes://note-1"
  }
}

این اعلان می‌گوید منبع تغییر کرده است. سپس کلاینت مجدداً آن را از طریق resources/read و با توجه به سطح دسترسی فعلی می‌خواند. کلاینت فرض نمی‌کند که متن رویداد حتماً شامل سند جدید باشد.

چندین اشتراک می‌توانند از یک کانال stdio مشترک استفاده کنند. شناسه اشتراک به کلاینت امکان می‌دهد آن‌ها را تفکیک کند. در بستر HTTP، بستن استریم پاسخ به معنای لغو اشتراک است. سروری که استریم را به‌درستی خاتمه می‌دهد، یک پاسخ نهایی با وضعیت resultType: "complete" مرتبط با درخواست اصلی ارسال می‌کند.

از استریم اشتراک به عنوان نشست پروتکل استفاده نکنید. درخواست خواندنِ بعدی همچنان یک درخواست مستقل و کامل است که می‌تواند به هر نمونه‌ی سالمی از سرور ارسال شود.

دسته‌بندی مولفه‌هاابزار، منبع یا پرامپت
PRIMITIVE SORTNot everything is a tool. If the model should decide to call it per query, it is a tool. If the user attaches it as context, it is a resource. If the reusable unit is a whole workflow, it is a prompt. Sorting a notes server this way removes model round-trips for plain reads and gives each capability the UX surface hosts already build for it.قابلیتواحد؟ابزارتغییر یا جستجومنبعضمیمه به عنوان بافتارپرامپتاجرای مجدد گردش‌کارnotes_searchnotes://42/review_note
همه چیز ابزار نیست. اگر مدل باید بر اساس هر پرسش تصمیم به فراخوانی آن بگیرد، ابزار است. اگر کاربر آن را به عنوان بافتار ضمیمه می‌کند، یک منبع است. اگر واحد با قابلیت استفاده مجدد کل یک گردش‌کار باشد، پرامپت است. مرتب‌سازی سرور یادداشت‌ها به این شیوه، رفت‌وبرگشت‌های مدل را برای خواندن‌های ساده حذف می‌کند و رابط کاربری اختصاصی را در اختیار هر قابلیت قرار می‌دهد.

کارگاه تعاملی

با استفاده از تصویر، 5 قابلیت یک سیستم مدیریت پروژه را دسته‌بندی کنید: جزئیات ایشو (issue details)، ایجاد ایشو (create issue)، قالب بررسی اسپرینت (sprint review template)، سیاست‌های پروژه (project policy) و بستن ایشو (close issue). سپس مشخص کنید کدام لیست‌ها می‌توانند به‌صورت عمومی کش شوند، کدام خواندن‌ها باید خصوصی بمانند و کدام منابع شایسته‌ی دریافت اعلان‌های به‌روزرسانی هستند.

برای هر دسته‌بندی، مشخص کنید چه کسی انتخاب‌کننده است. اگر مدل اقدامی انجام می‌دهد، از ابزار استفاده کنید. اگر میزبان محتوایی آدرس‌پذیر با URI را می‌خواند، از منبع استفاده کنید. اگر کاربر یک گردش کارِ آماده از پیام‌ها را شروع می‌کند، از پرامپت استفاده کنید.

تمرین عملی

شبیه‌ساز را از ریشه‌ی مخزن اجرا کنید:

cd phases/13-tools-and-protocols/10-mcp-resources-and-prompts/code
python3 main.py
python3 -m unittest discover tests -v

گزارش اجرا را به همین ترتیب بررسی کنید:

  1. مطمئن شوید server/discover نسخه‌ی فعلی و هر دو قابلیت را اعلام می‌کند.
  2. مطمئن شوید هر دو نتیجه‌ی فهرست مرتب شده‌اند و از resultType: "complete" استفاده می‌کنند.
  3. مطمئن شوید نتایج فهرست و خواندن، راهنماهای کش هدفمندی دارند.
  4. آدرس خواندن را به notes://missing تغییر دهید و خطای -32602 را مشاهده کنید.
  5. مطمئن شوید تأیید اشتراک پیش از رویداد منبع ارسال می‌شود.
  6. مطمئن شوید رویداد و پایان عادی استریم، هر دو شناسه اشتراک 5 را دارند.

مدل پایتون اتصال واقعی HTTP برقرار نمی‌کند؛ بلکه پیام‌هایی را نشان می‌دهد که SDK باید روی استریم پاسخی با دامنه‌ی درخواست قرار دهد. برای بخش بسته‌بندی داده‌ها و بستر انتقال در محیط عملیاتی، از SDKهای رسمی استفاده کنید.

خروجی این درس

فایل outputs/skill-primitive-splitter.md یک بازبینیِ طراحیِ قابل‌استفاده‌ی مجدد برای انتخاب مولفه‌های پایه‌ی MCP است. این سند اکنون بررسی اکتشاف قطعی، محدوده‌ی کش، رفتار در مواجهه با URI نامعتبر و فیلترهای اشتراک مدرن را پوشش می‌دهد.

همچنین فایل assets/primitive-split.svg ارائه شده که نسخه‌ای ثابت از مرز مولفه‌های پایه و اشتراک‌ها برای مطالعه‌ی آفلاین است.

اعتبارسنجی

cd phases/13-tools-and-protocols/10-mcp-resources-and-prompts/code
python3 main.py
python3 -m unittest discover tests -v

نتیجه‌ی مورد انتظار: برنامه‌ی اصلی یک خروجی JSON چاپ می‌کند و دستور تست موفقیت حداقل 12 تست را گزارش می‌دهد.

ارتباط با پروژه پایانی

زمانی که سرور پروژه‌ی پایانی شما دانشی آدرس‌پذیر را در کنار عملیات‌ها ارائه می‌دهد، از این قرارداد استفاده کنید. کار شما باید شامل یک اسنپ‌شات قطعی از کاتالوگ، یک خواندن منبع با احراز هویت، حل یک پرامپت، یک حالت URI نامعتبر و گزارش کامل یک اشتراک باشد.

شواهد شما باید نشان دهند که هیچ فهرستی به تاریخچه‌ی اتصال وابسته نیست و رویدادِ اشتراک هرگز به خودی خود دسترسی به منبع اصلی را فراهم نمی‌کند.

تمرین‌ها

  1. قالب منبع notes://projects/{project}/notes/{id} را اضافه کرده و هر دو متغیر را اعتبارسنجی کنید.
  2. صفحه‌بندی را به resources/list اضافه کنید، طوری که ترتیب خروجی قطعی و پایدار بماند.
  3. محدوده‌ی کش یک منبع را به cacheScope: "private" با ttlMs: 0 تغییر دهید، سیاست عدم ذخیره‌سازی در سطح میزبان را اضافه کنید و تهدیدی را که دلیل استفاده از هر دو کنترل است توضیح دهید.
  4. یک اشتراک برای تغییرات فهرست پرامپت‌ها اضافه کنید و ثابت کنید وقتی فیلتر فاقد promptsListChanged است، هیچ رویدادی ارسال نمی‌شود.
  5. دو اشتراک هم‌زمان بسازید و نشان دهید هر رویداد شناسه‌ی درخواست درست را حمل می‌کند.
  6. یک شناسه کاربر (subject) برای اعتبارسنجی دسترسی به هندلر خواندن اضافه کنید و نشان دهید مقدار کش‌شده نمی‌تواند بین کاربران مختلف به اشتراک گذاشته شود.

اصطلاحات کلیدی

  • منبع (Resource): محتوای آدرس‌پذیر با URI که توسط یک سرور MCP ارائه می‌شود.
  • پرامپت (Prompt): قالب پیامی تحت کنترل کاربر که توسط یک سرور MCP ارائه می‌شود.
  • فهرست قطعی (Deterministic list): نتیجه‌ی یک فرایند اکتشاف که با ورودی‌های یکسان، همیشه اعضا و ترتیب پایداری دارد.
  • ttlMs: مدت‌زمان تازگی کش به میلی‌ثانیه.
  • cacheScope: مرز به‌اشتراک‌گذاری یک نتیجه‌ی کش‌شده.
  • subscriptions/listen: درخواستی با طول عمر بالا که استریم پاسخ آن اعلان‌های صراحتاً فیلترشده را تحویل می‌دهد.
  • شناسه اشتراک (Subscription ID): شناسه‌ی درخواست listen اصلی که در متادیتای اعلان تکرار می‌شود.
  • پارامترهای نامعتبر (Invalid parameters): خطای JSON-RPC با کد -32602 که برای URI نامعتبر یا ناشناخته‌ی منبع استفاده می‌شود.
  • نسخه پروتکل پشتیبانی‌نشده (Unsupported protocol version): خطای JSON-RPC با کد -32022 که شامل نسخه‌های supported و requested است.
  • server/discover: متد الزامی سرور که نسخه‌های پشتیبانی‌شده، قابلیت‌ها، هویت و راهنماهای اختیاری کش را برمی‌گرداند.

برای مطالعه‌ی بیشتر

خودآزمایی

به سؤال‌ها جواب بدهید تا ببینید چقدر از درس در ذهنتان مانده است.

  1. پیش از درسیک میزبان نیاز دارد یک یادداشت معماری پایدار را از طریق URI بازیابی کند. کدام مولفه MCP مناسب‌تر است؟
  2. حین درسهنگامی که resources/read یک URI منبع ناشناخته دریافت می‌کند، یک سرور 2026-07-28 چه پاسخی باید برگرداند؟
  3. حین درسکدام سیاست کش برای یک یادداشت متعلق به کاربر که توسط resources/read بازگردانده شده، امن‌تر است؟
  4. حین درسچه چیزی تک‌تک اعلان‌ها را در جریان پاسخ subscriptions/listen شناسایی می‌کند؟
  5. پس از درسچرا متدهای resources/list و prompts/list برای ورودی‌های یکسان درخواست باید قطعی (deterministic) باشند؟
  6. پس از درسیک سرور فعلی MCP باید چه چیزی را پیاده‌سازی کند، حتی اگر کلاینت‌ها مستقیماً resources/list را فراخوانی کنند؟

سؤالات متداول

تفاوت اصلی بین ابزار (Tool)، منبع (Resource) و پرامپت (Prompt) در MCP چیست؟

ابزارها عملیات انجام می‌دهند و وضعیت را تغییر می‌دهند (توسط مدل یا برنامه انتخاب می‌شوند)؛ منابع محتوای خواندنیِ آدرس‌پذیر با URI هستند؛ و پرامپت‌ها قالب‌های پیامی از پیش‌آماده‌اند که کاربر مستقیماً آن‌ها را انتخاب و اجرا می‌کند.

اگر کلاینت MCP یک URI ناشناخته یا نامعتبر از منابع را درخواست کند چه خطایی بازگردانده می‌شود؟

سرور نباید یک پاسخ خالی برگرداند؛ بلکه باید خطای استانداردی با کد JSON-RPC برابر با -32602 (پارامترهای نامعتبر) ارسال کند.

مقادیر مجاز cacheScope در مشخصات MCP چیست و داده‌های بسیار حساس چگونه کنترل می‌شوند؟

فقط مقادیر public و private مجاز هستند. برای داده‌های حساس، باید cacheScope: "private" همراه با ttlMs: 0 بازگردانده شود و سیاست‌های سخت‌گیرانه‌تر مانند no-store در سطح میزبان اعمال گردد.

مکانیزم اشتراک‌ها (Subscriptions) در نسخه جدید MCP چگونه کار می‌کند؟

کلاینت درخواستی با عنوان subscriptions/listen می‌فرستد که پاسخ آن به صورت استریم SSE باز می‌ماند. اعلان‌ها با شناسه‌ی اشتراک تفکیک می‌شوند و تغییر را اعلام می‌کنند؛ سپس کلاینت خود سند جدید را مجدداً از طریق resources/read می‌خواند.

ما رو توی گوگل بیشتر ببین

با افزودن نکست ادمین به «منابع ترجیحی» گوگل، درس‌ها و مطالب ما را در بخش اخبار برتر جستجو بیشتر می‌بینید.