فاز 19 · درس 13

پروژه پایانی MCP بی‌وضعیت: اتصال به رجیستری و حاکمیت داده

نوع
پروژه‌ی پایانی
زمان
حدود 17 دقیقه
زبان‌ها
Python, TypeScript reference models; any production language
پیش‌نیاز
فاز 11، فاز 13، فاز 14، فاز 17، و فاز 18
تصویر مفهومی بدون متن شامل دو سرور موازی بدون وضعیت، کلید امنیتی طلایی، قراردادهای دیجیتال قفل‌شده و کابل‌های شبکه‌ای متقارن
فهرست مطالب
  1. اهداف یادگیری
  2. مسیر پیش‌نیاز الزامی MCP
  3. صورت مسئله
  4. دو لایه‌ی شناسایی
  5. هسته‌ی بی‌وضعیت MCP
  6. شناسایی کش‌پذیر
  7. پروتکل HTTP جریانی
  8. احراز هویت و مجوزها
  9. تأییدیه یک سند است، نه یک دامنه‌ی جادویی
  10. پیاده‌سازی از صفر
  11. 1. مدل‌سازی فراداده‌های انتشار
  12. 2. پیاده‌سازی شناسایی زنده
  13. 3. پیاده‌سازی بسته‌ی بی‌وضعیت
  14. 4. ساخت رابط ابزارها
  15. 5. افزودن فهرست‌بندی آگاه از کش
  16. 6. افزودن احراز مجوز و خط‌مشی
  17. 7. تفکیک اعتبارسنجی رجیستری از زمان اجرا
  18. 8. ثبت شواهد رویدادها
  19. 9. ارزیابی مقیاس‌پذیری افقی
  20. 10. آزمون واقعی روی شبکه
  21. بسته‌ی شواهد الزامی
  22. مدل‌های مرجع محلی
  23. نمونه تبادل داده روی شبکه
  24. انتشار نهایی
  25. تمرین‌ها
  26. اصطلاحات کلیدی
  27. برای مطالعه‌ی بیشتر

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

در این درس پروژه پایانی، یاد می‌گیرید چگونه یک سرور MCP کاملاً بی‌وضعیت (Stateless) را بر مبنای آخرین ویرایش استاندارد پیاده‌سازی کنید. با استفاده از Streamable HTTP و کپسوله‌سازی کامل فراداده‌ها در هر درخواست، نیاز به چسبندگی نشست (Session Affinity) از بین می‌رود و می‌توانید سرویس را به سادگی در زیرساخت‌های چندنسخه‌ای مقیاس‌پذیر کنید.

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

سرور MCP در محیط عملیاتی (پروداکشن) صرفاً یک فرایند سروری منفرد نیست، بلکه زنجیره‌ای از قراردادها است: فراداده‌ی قابل انتشار، شناسایی زنده‌ی قابلیت‌ها، بسته‌ی بی‌وضعیت (Stateless Envelope) درخواست، احراز هویت و مجوزها، خط‌مشی‌ها، ثبت رویدادها (Audit) و شواهد استقرار.

مطالعه‌ی دقیق و الزامی این درس‌های MCP پیش‌نیاز است: درس 28: قراردادهای ابزار، درس 29: قابلیت اطمینان، درس 30: زنجیره‌ی تأمین رجیستری و درس 31: عملیات انطباق با استاندارد نسخه‌ی هدف پروتکل: پروتکل MCP نسخه‌ی 2026-07-28 زمان تخمینی: حدود 25 ساعت

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

  • پیاده‌سازی بسته‌ی بی‌وضعیت برای درخواست و نتیجه‌ی MCP.
  • تفکیک کامل فراداده‌ی رجیستری از شناسایی زنده‌ی پروتکل.
  • ساخت سازوکار قطعی و آگاه از کش برای شناسایی ابزارها.
  • اعمال صادرکننده (Issuer)، مخاطب (Audience)، دامنه (Scope) و خط‌مشی تأییدیه برای تک‌تک فراخوانی‌های ابزار.
  • استقرار پروتکل HTTP جریانی (Streamable HTTP) بدون وابستگی به نشست (Session affinity).
  • ارائه‌ی اثبات رفتاری در مرزهای تبادل داده روی شبکه، مجوزها، خط‌مشی، رجیستری و ثبت رویدادها.

مسیر پیش‌نیاز الزامی MCP

پیش از آنکه این پروژه‌ی پایانی را آماده‌ی محیط عملیاتی بدانید، این چهار درس فاز 13 را به ترتیب پشت سر بگذارید:

  1. درس 28 قراردادهای ابزار، اسکیما، محتوا، صفحه‌بندی، تکمیل خودکار، مسیریابی و خطاهایی را که این سرور باید ارائه دهد مشخص می‌کند.
  2. درس 29 رفتارهای مربوط به رقابت لغو (Cancellation race)، مهلت‌های زمانی، کلید یکتایی تراکنش (Idempotency key)، پس‌زدگی (Backpressure)، تلاش مجدد و اتصال دوباره را تعیین می‌کند.
  3. درس 30 شواهد مربوط به فضای نام، منشأ و سندیت (Provenance)، قفل پذیرش، وضعیت رجیستری، انحراف، دفترکل و بازگشت به عقب (Rollback) را مشخص می‌کند.
  4. درس 31 متن ارتباطات استاندارد و منفی (Negative transcript)، دوره‌های نسخه‌گذاری دقیق، ارزیابی مقایسه‌ای SDK (یا SDK differential)، اثبات صحت پراکسی، پاک‌سازی داده‌های حساس (Redaction)، بررسی سلامت و دروازه‌های انتشار را تعیین می‌کند.

این پروژه‌ی نهایی، تمام دست‌سازه‌های (Artifacts) بالا را یکپارچه می‌کند و هرگز نباید آن‌ها را با یک تست ساده‌ی مسیر ایده‌آل (Happy-path) روی SDK جایگزین کرد.

صورت مسئله

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

بخش دشوار کار، ثبت کردن یک تابع نیست؛ بلکه هماهنگ نگه‌داشتن هم‌زمان شش حقیقت متفاوت است:

  1. فایل server.json مشخص می‌کند سرور کجا قابل نصب است یا چطور می‌توان به آن رسید.
  2. اندپوینت server/discover اعلام می‌کند فرایند زنده در حال حاضر از چه مواردی پشتیبانی می‌کند.
  3. هر درخواست مشخص می‌کند از چه ویرایشی از پروتکل و کدام قابلیت‌های کلاینت استفاده می‌کند.
  4. مجوزها فراخواننده را دقیقاً به صادرکننده، منبع و دامنه‌های صحیح مقید می‌کنند.
  5. خط‌مشی تصمیم می‌گیرد که آیا این اقدام خاص اجازه‌ی اجرا دارد یا خیر.
  6. شواهد ثبت رویدادها ضبط می‌کنند چه داده‌هایی از مرز سیستم رد شده‌اند، بدون آنکه اسرار امنیتی یا بارهای داده‌ی حساس فاش شوند.

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

دو لایه‌ی شناسایی

رجیستری و سرور زنده‌ی MCP به دو پرسش کاملاً متفاوت پاسخ می‌دهند.

لایه قرارداد پرسشی که پاسخ می‌دهد
انتشار server.json و API رجیستری این سرور چیست، پکیج یا اندپوینت مخزن راه‌دور (Remote) آن کجاست و چگونه پیکربندی می‌شود؟
محیط اجرا (Runtime) server/discover این فرایند در حال حاضر از کدام نسخه‌های پروتکل، قابلیت‌ها، افزونه‌ها و هویت سرور پشتیبانی می‌کند؟

رجیستری رسمی از اسکیمای نسخه‌دار server.json استفاده می‌کند. مدخل‌های مربوط به مخزن راه‌دور می‌توانند نشانی اینترنتی پروتکل HTTP جریانی را مشخص کنند:

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "com.example/internal-readonly",
  "title": "Internal Read-Only Tools",
  "description": "Read-only incident and data lookup tools.",
  "version": "1.0.0",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://mcp.internal.example.com/readonly"
    }
  ]
}

نسخه‌ی اسکیمای رجیستری و نسخه‌ی ویرایش پروتکل MCP مستقل از یکدیگرند. هرگز تاریخ یکی را برای مطابقت با دیگری بازنویسی نکنید؛ هر سند را فقط با قرارداد خودش اعتبارسنجی کنید.

معتبر بودن اسکیما دلیلی بر مالکیت فضای نام نیست. ناشری که برای example.com تأیید شده، باید از فضای نام DNS معکوس com.example/* یا زیرشاخه‌های آن استفاده کند. جریان احراز هویت رجیستری، این مالکیت را اثبات می‌کند. نوشتن برچسب‌های دامنه با ترتیب عادی، نام یک فضای نام دیگر خواهد بود.

تابع validate_registry_document در مدل کتابخانه‌ی استاندارد، عمداً یک اعتبارسنج جزئی برای پروفایل راه‌دور است. این تابع فیلدهای اجباری رسمی شامل name، description و version، فیلد اختیاری title، محدودیت‌های طول و نام‌های منتشرشده، ساختار نسخه‌ی قطعی و قالب آدرس‌های HTTP(S) را در هر ریموت streamable-http یا sse بررسی می‌کند. علاوه بر این، وجود فهرست غیرخالی remotes را الزامی می‌داند، چون این پروژه‌ی نهایی همواره یک مخزن راه‌دور را به صورت زنده ارزیابی می‌کند. تابع validate_publisher_namespace به طور مجزا نام را در برابر دامنه‌ی تأییدشده‌ی ناشر بررسی می‌کند، در حالی که validate_runtime_alignment نام و نسخه‌ی منتشرشده را با serverInfo زنده تطبیق می‌دهد. اسکیمای رسمی رجیستری از رکوردهای مبتنی بر پکیج و فیلدهای ریموت بیشتری هم پشتیبانی می‌کند. قبل از انتشار نهایی، کل سند را با JSON Schema رسمی و قفل‌شده یا با mcp-publisher اعتبارسنجی کنید؛ این زیرمجموعه‌ی بدون وابستگی را اعتبارسنجی کامل اسکیما قلمداد نکنید.

سرور باید server/discover را پیاده‌سازی کند؛ کلاینت می‌تواند پیش از متدهای دیگر آن را فراخوانی کند. کلاینت این پروژه‌ی نهایی، پس از حل آدرس اندپوینت این کار را انجام می‌دهد و ویرایش فعلی پروتکل و قابلیت‌های زنده را دریافت می‌کند:

{
  "resultType": "complete",
  "supportedVersions": ["2026-07-28"],
  "capabilities": {
    "tools": {
      "listChanged": false
    }
  },
  "_meta": {
    "io.modelcontextprotocol/serverInfo": {
      "name": "com.example/internal-readonly",
      "version": "1.0.0"
    }
  },
  "ttlMs": 3600000,
  "cacheScope": "public"
}

کاتالوگ‌های خصوصی سازمان می‌توانند داده‌های مالکیت، بازبینی یا چرخه‌ی عمر را ذخیره کنند، اما نباید این داده‌ها را به شکل فیلدهای شبکه‌ای MCP یا فیلدهای ریشه‌ای server.json درآورند. خط‌مشی‌های سازمانی را در کنار رکورد منتشرشده نگه دارید. اگر نیاز به افزودن فراداده‌ی سفارشی عمومی دارید، از افزونه‌ی _meta.io.modelcontextprotocol.registry/publisher-provided در رجیستری استفاده کنید و زیر سقف 4 کیلوبایت باقی بمانید.

هسته‌ی بی‌وضعیت MCP

ویرایش 2026-07-28 پروتکل MCP، نشست‌ها و دست‌دادن (Handshake) اولیه‌ی initialize / notifications/initialized را حذف کرده است. هدر Mcp-Session-Id نیز به طور کامل کنار رفته است.

هر درخواست، زمینه‌ی پروتکل را درون params._meta به همراه دارد:

{
  "io.modelcontextprotocol/protocolVersion": "2026-07-28",
  "io.modelcontextprotocol/clientCapabilities": {},
  "io.modelcontextprotocol/clientInfo": {
    "name": "internal-platform-client",
    "version": "1.0.0"
  }
}

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

نتایج عادی شامل resultType: "complete" هستند. سرورها باید هویت خود را در فیلد _meta.io.modelcontextprotocol.registry/serverInfo <!-- REVIEW: در متن اصلی _meta.io.modelcontextprotocol/serverInfo آمده است --> در هر نتیجه بازگردانند. نبود نسخه‌ی پروتکل یا رشته‌ای نبودن آن، خطای پارامترهای نامعتبر -32602 است. خطای -32022 فقط برای حالتی است که رشته‌ی ارسالی پشتیبانی نشود؛ داده‌ی این خطا باید دقیقاً به شکل {"supported": ["2026-07-28"], "requested": "..."} باشد.

شناسایی کش‌پذیر

خروجی متد tools/list به ازای مجموعه‌ی ابزارهای یکسان، باید کاملاً قطعی باشد. این نتیجه شامل موارد زیر است:

  • مقدار ttlMs که راهنمای تازگی داده برای کلاینت است؛
  • دامنه‌ی کش (Cache Scope) که می‌تواند public یا private باشد؛
  • ترتیب پایدار ابزارها تا فهرست‌های یکسان بتوانند از کش پرامپت‌ها دوباره استفاده کنند؛
  • فیلد resultType: "complete" و فراداده‌ی هویت سرور.

وقتی مجوزها به ازای هر کاربر متفاوت است، دامنه کش معمولاً باید روی private تنظیم شود. نمایش ابزارها بر اساس کاربر را پشت یک کش اشتراکی عمومی نگذارید.

پروتکل HTTP جریانی

یک سرور تحت شبکه، یک اندپوینت واحد MCP ارائه می‌دهد که متد POST را می‌پذیرد. هر درخواست یا اعلان JSON-RPC در قالب یک POST جداگانه ارسال می‌شود.

برای هر درخواست، سرور یا یک شیء JSON و یا یک استریم SSE برمی‌گرداند که دامنه‌ی آن محدود به همان درخواست است (Request-scoped SSE). درخواست‌های طولانی‌مدت subscriptions/listen اعلان‌های تغییراتی را که کلاینت در آن‌ها عضو شده منتقل می‌کنند. در بستر انتقال فعلی، استریم مستقل GET، متد DELETE برای نشست، هدر نشست، یا بازپخش از طریق Last-Event-ID وجود ندارد.

هر درخواست شامل موارد زیر است:

  • هدر MCP-Protocol-Version که باید با فراداده‌ی بدنه‌ی پیام مطابقت داشته باشد؛
  • هدر Mcp-Method متناظر با متد JSON-RPC؛
  • هدر Mcp-Name برای متدهای tools/call، resources/read و prompts/get؛
  • هدر Accept: application/json, text/event-stream.

اگر هدرهای متناظر مغایرت داشته باشند، درخواست را با خطای مشخص‌شده‌ی -32020 رد کنید. هدر Origin را اعتبارسنجی کنید، سرورهای توسعه‌ی محلی را به آدرس Loopback محدود کنید، کلاینت‌های راه‌دور را احراز هویت نمایید، و بسته شدن پاسخ SSE در دامنه‌ی درخواست را به عنوان لغو درخواست (Request cancellation) تلقی کنید.

API رجیستریserver.jsonکلاینت MCPserver/discovertools/listدرگاه مجوزدهی و خط‌مشینسخه‌های فقط‌خواندنی MCPنسخه‌های تغییردهنده وضعیت MCPمخزن لاگ حسابرسیسجل تأیید
گیت MCP بی‌وضعیت + رجیستریفراداده و اعتبارسنجی در هر درخواست بررسی می‌شوند
STATELESS MCP GATE + REGISTRYEach JSON-RPC message gets its own POST and carries protocol version plus client capabilities. The gate validates issuer, audience, scope, tool, and arguments; a consequential call also needs an approval record bound to that exact action. The registry indexes server.json publication metadata, while a separate server/discover probe verifies what the live endpoint supports.کلاینت MCPنسخه + قابلیت‌هاسرور MCPبی‌وضعیتیک POST برای هر پیام JSON-RPCاحراز هویت + پالیسیرکورد تاییدعامل + ابزار + آرگومان + انقضارجیستریserver.jsonآزمون ارزیابی server/discover زنده
هر پیام JSON-RPC از یک POST مستقل استفاده می‌کند و نسخه پروتکل و قابلیت‌های کلاینت را به همراه دارد. گیت کنترلی صادرکننده، مخاطب، دامنه، ابزار و آرگومان‌ها را اعتبارسنجی می‌کند؛ یک فراخوانی پیامددار به یک رکورد تایید مقید به همان اقدام دقیق نیز نیاز دارد. رجیستری فراداده انتشار server.json را ایندکس می‌کند، در حالی که یک آزمون ارزیابی server/discover مستقل بررسی می‌کند که اندپوینت زنده از چه مواردی پشتیبانی می‌کند.

احراز هویت و مجوزها

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

برای سرورهای راه‌دور:

  1. فراداده‌ی منبع حفاظت‌شده (Protected-resource metadata) را کشف کنید.
  2. سرور مجوزدهی مناسب برای آن منبع را انتخاب کنید.
  3. برای ثبت‌نام کلاینت، اسناد فراداده‌ی کلاینت (Client ID Metadata Documents) را در اولویت بگذارید و ثبت‌نام پویای کلاینت را فقط برای سازگاری پشتیبانی کنید.
  4. نشانگر منبع (Resource indicator) را در طول فرایند احراز مجوز ارسال کنید.
  5. مقدار iss بازگشتی را با سرور مجوزدهی ثبت‌شده برای این جریان تطبیق دهید.
  6. اطلاعات هویتی کلاینت را بر اساس صادرکننده کلیدگذاری کنید؛ هرگز داده‌های ثبت‌نام را میان چند صادرکننده دوباره استفاده نکنید.
  7. صادرکننده‌ی توکن، مخاطب یا منبع، انقضا و دامنه‌ها را در سمت سرور MCP اعتبارسنجی کنید.
  8. یک مرحله تصمیم‌گیری خط‌مشی دیگر را روی ابزار مشخص و آرگومان‌های ارسالی اعمال کنید.

یادداشت‌های ابزار مثل readOnlyHint و destructiveHint به کلاینت‌ها در نمایش ریسک کمک می‌کنند، اما سازوکار قابل اعتمادی برای کنترل دسترسی نیستند.

تأییدیه یک سند است، نه یک دامنه‌ی جادویی

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

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

اگر جدا کردن ابزارهای پرخطر شعاع تخریب (Blast radius) را به شکل محسوسی کاهش می‌دهد، آن‌ها را در یک بستر مجزا و قابل بررسی جداگانه نگه دارید. این جداسازی تنها زمانی مفید است که اعتبارنامه‌ها، خط‌مشی‌ها، هویت استقرار و کنترل‌های ثبت رویداد نیز تفکیک شده باشند.

پیاده‌سازی از صفر

1. مدل‌سازی فراداده‌های انتشار

فایل server.json را بسازید و اسکیما را اعتبارسنجی کنید. نامی پایدار درون فضای نام تأییدشده‌ی ناشر، نسخه، توضیحات، فراداده‌های رسمی repository یا packages (در صورت نیاز) و بستر انتقال ریموت یا stdio را وارد کنید. اسرار امنیتی را به عنوان متغیرهای محیطی اعلام کنید، نه مقادیر مستقیم متنی.

2. پیاده‌سازی شناسایی زنده

پیش از ارائه‌ی هر متد دیگر، server/discover را پیاده‌سازی کنید. نسخه‌های پشتیبانی‌شده‌ی پروتکل، قابلیت‌ها، افزونه‌ها و هویت سرور را اعلام کنید. حالت رد نسخه با خطای -32022 را نیز اضافه کنید.

3. پیاده‌سازی بسته‌ی بی‌وضعیت

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

4. ساخت رابط ابزارها

کار را با دو ابزار فقط‌خواندنی و یک ابزار تغییردهنده‌ی وضعیت آغاز کنید. برای هر کدام یک JSON Schema محدود، توضیحات دقیق، ساختار نتیجه‌ی قطعی و یادداشت‌های صادقانه در نظر بگیرید. در صورتی که کلاینت به ساختار داده متکی است، اسکیمای خروجی را هم اضافه کنید.

5. افزودن فهرست‌بندی آگاه از کش

ابزارها را با ترتیبی پایدار به همراه ttlMs و cacheScope بازگردانید. رفتارهای انقضای کش و اعلان تغییر فهرست را به طور جداگانه آزمایش کنید.

6. افزودن احراز مجوز و خط‌مشی

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

7. تفکیک اعتبارسنجی رجیستری از زمان اجرا

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

8. ثبت شواهد رویدادها

کنشگر، صادرکننده، منبع، ابزار، تصمیم خط‌مشی، شناسه‌ی درخواست، زمینه‌ی ردگیری محاسبات (Trace context)، تاخیر و نتیجه را ثبت کنید. پیش از ذخیره‌سازی، آرگومان‌ها و نتایج حساس را پاک‌سازی یا خلاصه‌سازی کنید. محل ذخیره‌ی لاگ‌ها باید خارج از دید مدل باشد.

9. ارزیابی مقیاس‌پذیری افقی

دو نسخه‌ی بی‌وضعیت از سرور را پشت یک توزیع‌کننده‌ی بار قرار دهید. حداقل 100 درخواست هم‌زمان ارسال کنید. نشان دهید صحت عملکرد سیستم به وابستگی به نشست گره نخورده است. اگر ابزاری نیاز به حفظ حالت میان فراخوانی‌ها دارد، یک شناسه‌ی مات (Opaque handle) صادر کرده و آن را در یک سیستم پایدار و مشترک ذخیره کنید.

10. آزمون واقعی روی شبکه

تست‌های انطباق با استاندارد را در برابر فایل باینری واقعی سرور اجرا کنید. علاوه بر شیءهای SDK، هدرهای خام درخواست و بدنه‌های JSON را ثبت کنید. سناریوهای نسخه‌ی اشتباه، مغایرت هدرها، نبود دامنه، مخاطب نادرست، آرگومان‌های ناقص، شکست تابع، لغو درخواست و انقضای کش را بیازمایید.

بسته‌ی شواهد الزامی

پروژه‌ی ارسالی شما کامل نیست مگر اینکه هر پنج دسته‌ی شواهد زیر را در بر داشته باشد:

شواهد حداقل اثبات مورد نیاز درس مرجع
تبادل شبکه (Wire) هدرهای خام و بدنه‌های JSON-RPC پاک‌سازی‌شده برای سناریوهای مسیر ایده‌آل و منفی، شامل خطای نوع فراداده، مغایرت هدر، نسخه‌ی پشتیبانی‌نشده، نبود یا ناشناخته بودن resultType، عدم پاسخ به اعلان‌ها و تطابق شناسه‌ی پاسخ درس 31
پراکسی اجرای همان سناریوی پایدار به صورت مستقیم و از طریق میانجیِ مستقرشده، همراه با وضعیت ورودی، مبدأ و خروجی و خلاصه‌ی بدنه‌ها؛ اثبات اینکه خطاهای پروتکل به خطای عمومی 500 تبدیل نمی‌شوند و استریمینگ بافر نمی‌شود درس 29 و درس 31
پذیرش فضای نام تأییدشده‌ی ناشر، خلاصه‌ی تغییرناپذیر رکورد رجیستری، منشأ دست‌سازه یا ریموت، مشاهده‌ی زنده هویت و قابلیت‌ها با server/discover، قفل توصیف‌گر (descriptor pin)، وضعیت فعلی رجیستری، و رویداد ثبت در دفترکل پذیرش درس 30
تلاش مجدد رقابت لغو با تکمیل درخواست، مهلت زمانی مشخص، تلاش مجدد ایمن برای خواندن، کلید یکتایی تراکنش برای تغییرات، واکشی مجدد (Refetch) پس از اتصال مجدد، و اثبات اینکه لغو درخواست ناخواسته باعث لغو وظیفه‌ی ماندگار نمی‌شود درس 29
بازگشت به عقب نسخه‌ی دقیق قبلی، خلاصه‌ی پذیرش و دست‌سازه‌ها، قفل توصیف‌گر، وضعیت فعال رجیستری، بازه‌ی سلامت فعلی، نتیجه‌ی بازیابی مسیر، و شواهد تصمیم‌گیری پاک‌سازی‌شده درس 30 و درس 31

خلاصه‌ای از بسته‌ی شواهد پاک‌سازی‌شده را همراه با انتشار ذخیره کنید. اگر هر کدام از دسته‌ها موجود نباشد، انتشار را متوقف کنید. هرگز رفتار پراکسی را از روی توزیع‌کننده‌ی درون‌فرایندی، پذیرش را از صرف حضور در رجیستری، ایمنی تلاش مجدد را از یک شناسه جدید JSON-RPC، یا آمادگی بازگشت به عقب را از «استقرار قبلی» استنتاج نکنید.

مدل‌های مرجع محلی

مدل پایتون فراداده‌های رجیستری، اعتبارسنجی فضای نام معکوس ناشر، بررسی تطابق انتشار با محیط اجرا، شناسایی زنده، فهرست‌بندی قطعی ابزارها، فراداده‌های هر درخواست، بررسی صادرکننده‌ی معتبر، مخاطب، انقضا و دامنه‌ها، تأییدیه‌های مقید به عملیات، اعتبارسنج جزئی رجیستری، خط‌مشی و ثبت رویدادها را بدون باز کردن سوکت شبکه نشان می‌دهد:

cd phases/19-capstone-projects/13-mcp-server-with-registry
python3 code/main.py
python3 -m unittest discover -s code/tests -v

پروژه‌ی TypeScript ساختار JSON-RPC بی‌وضعیت را از طریق stdio و بدون استفاده از SDK پروتکل MCP پیاده‌سازی می‌کند. بخش tools/call همان اسکیمای ورودی اعلام‌شده در tools/list را اعمال می‌کند؛ آرگومان‌های نامعتبر برای یک ابزارِ شناخته‌شده، بدون فراخوانی مجری اصلی، نتیجه‌ای کامل با isError: true برمی‌گردانند:

cd phases/19-capstone-projects/13-mcp-server-with-registry/code/ts
npm install
npm run typecheck
npm test
npm run demo

این مدل‌ها منطق قراردادهای محلی را اثبات می‌کنند، اما جایگزین اثبات هدرهای HTTP، تبادل OAuth، انتشار در رجیستری، یکپارچه‌سازی OPA، توزیع بار یا دریافت لاگ‌ها در گردآورنده‌ی مرکزی نیستند.

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

POST /mcp HTTP/1.1
Host: mcp.internal.example.com
Content-Type: application/json
Accept: application/json, text/event-stream
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: postgres.readonly
Authorization: Bearer REDACTED

{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tools/call",
  "params": {
    "name": "postgres.readonly",
    "arguments": {"sql": "SELECT 1"},
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "internal-platform-client",
        "version": "1.0.0"
      }
    }
  }
}

انتشار نهایی

مخزنی ارائه دهید که شامل موارد زیر باشد:

  • فایل server.json با اسکیمای معتبر؛
  • رابط‌های سرور تفکیک‌شده برای عملیات فقط‌خواندنی و تغییردهنده‌ی وضعیت؛
  • اندپوینت server/discover، متد قطعی tools/list، و متد tools/call مجهز به بررسی خط‌مشی؛
  • استقرار پروتکل HTTP جریانی با دو نسخه‌ی تکثیرشده و قابل جایگزینی؛
  • یکپارچگی با احراز هویت، مجوزها و سازوکار تأییدیه؛
  • ناشر رجیستری یا تطبیق‌دهنده‌ی API رجیستری خصوصی؛
  • تعاریف خط‌مشی و اسناد تأییدیه‌ی مقید به عملیات؛
  • خروجی پاک‌سازی‌شده‌ی لاگ‌ها و انتشار زمینه‌ی ردگیری محاسبات؛
  • شواهد خطای شبکه و پراکسی؛
  • شواهد پذیرش، تلاش مجدد، سلامت و بازگشت به عقب همراه با خلاصه‌ی بسته‌ی پاک‌سازی‌شده.
وزن نمره معیار شواهد ارائه‌شده
25 صحت پیاده‌سازی پروتکل فراداده‌های بی‌وضعیت درخواست، شناسایی، نتایج، هدرها و سناریوهای منفی
20 مجوزها موارد مربوط به صادرکننده، مخاطب، انقضا، دامنه و تأییدیه‌های مقید به اقدام
15 سلامت رجیستری فایل معتبر server.json، رکورد انتشار، آزمون ارزیابی زنده‌ی شناسایی و گزارش انحراف
15 خط‌مشی و امنیت سناریوهای مجاز، مسدود، داده‌های ناقص، تأییدیه‌ی منقضی و مدیریت داده‌های حساس
15 مقیاس‌پذیری و قابلیت اطمینان دو نسخه بدون وابستگی به نشست، لغو درخواست، مهلت زمانی و بازیابی
10 ثبت و بازبینی‌پذیری شواهد ثبت رویدادها در سمت گیرنده به همراه زمینه‌ی ردگیری محاسبات پاک‌سازی‌شده

تمرین‌ها

  1. آدرس ریموت ثبت‌شده را در رجیستری تغییر دهید در حالی که سرور زنده تغییری نکرده است. اعتبارسنجی رجیستری را طوری تنظیم کنید که انحراف دقیق را گزارش کند.
  2. متد tools/list را دو بار با ورودی‌های کاملاً یکسان فراخوانی کنید و نشان دهید ترتیب بایت‌های ابزارها یکسان است. سپس بگذارید ttlMs منقضی شود و داده‌ها را تازه کنید.
  3. یک بدنه‌ی درخواست معتبر با هدر MCP-Protocol-Version متفاوت ارسال کنید. خطا با کد -32020 برگردانید و مطمئن شوید ابزار یا خط‌مشی اجرا نمی‌شوند.
  4. توکنی برای سرور فقط‌خواندنی صادر کنید و آن را به سرور تغییردهنده‌ی وضعیت بفرستید. نشان دهید که ارزیابی مخاطب قبل از اجرای تابع با خطا متوقف می‌شود.
  5. تأییدیه‌ای را به خلاصه‌ی آرگومان‌های نرمال‌شده مقید کنید. یک فیلد را تغییر دهید و ثابت کنید امکان بازپخش تأییدیه وجود ندارد.
  6. درخواست‌های متوالی را به صورت متناوب به نسخه‌های مختلف سرور بفرستید. هر جا جریان کاری نیازمند ماندگاری است، حافظه‌ی پنهان فرایند را با یک شناسه‌ی مات اشتراکی جایگزین کنید.
  7. اتصال SSE در دامنه‌ی درخواست را قطع کرده و با یک شناسه‌ی جدید JSON-RPC دوباره تلاش کنید. مطمئن شوید هیچ مسیری برای بازیابی از طریق Last-Event-ID استفاده نمی‌شود.

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

اصطلاح در گفتار عامیانه در واقعیت
پروتکل MCP بی‌وضعیت (Stateless MCP) «هیچ جا هیچ وضعیتی وجود ندارد» نشست پروتکل وجود ندارد؛ وضعیت میان فراخوانی‌ها صریح است و سرور آن را مدیریت می‌کند
server.json «مانیفست ابزارها» فراداده‌ی رجیستری برای نام‌گذاری، بسته‌بندی، پیکربندی و بسترهای انتقال
server/discover «دست‌دادن» یک فراخوانی RPC عادی و اجباری برای دریافت نسخه‌ها و قابلیت‌های زنده، نه ایجادکننده‌ی نشست
دامنه‌ی کش (Cache Scope) «آیا می‌توانم کش کنم؟» مشخص می‌کند آیا نتیجه‌ی کش‌پذیر برای استفاده‌ی اشتراکی امن است یا خصوصی
تصمیم‌گیری خط‌مشی (Policy Decision) «توکن معتبر است و اجازه می‌دهد» تصمیمی مجزا بر اساس کنشگر، ابزار، هدف، آرگومان‌ها و زمینه
سند تأییدیه (Approval Record) «انسان دکمه‌ی تأیید را زد» مدرکی مقید به یک کنشگر و اقدامی مشخص بر اساس خط‌مشی انقضا
شناسه‌ی مات صریح (Explicit Handle) «شناسه‌ی نشست» داده‌ی معمولی برنامه‌نویسی برای مدیریت وضعیت توسط سرور، نه وضعیت اتصال پروتکل

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

خودآزمایی

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

  1. پیش از درسچرا این پروژه نهایی هم از server.json و هم از server/discover استفاده می‌کند؟
  2. حین درسدر بازنگری 2026-07-28 پروتکل MCP، چه چیزی جایگزین دست‌دادن initialize می‌شود؟
  3. حین درسکدام رفتار tools/list از شناسایی ایمن و کارآمد پشتیبانی می‌کند؟
  4. حین درسکدام طراحی Streamable HTTP با بستر انتقال بی‌وضعیت فعلی همخوانی دارد؟
  5. پس از درسیک سرور عملیاتی قبل از اجرای هندلر ابزار تاییدشده توسط پالیسی چه مواردی را باید اعتبارسنجی کند؟
  6. پس از درسکدام شاهد به بهترین شکل از این ادعا که سرور بدون نشست‌های پروتکل مقیاس‌پذیر است پشتیبانی می‌کند؟

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

چرا در معماری Stateless MCP نشست‌ها (Sessions) حذف شده‌اند؟

حذف نشست‌ها امکان توزیع درخواست‌ها میان نمونه‌های مختلف سرور بدون نیاز به Session Affinity را فراهم می‌کند، چون هر درخواست تمام فراداده‌ها، نسخه پروتکل و قابلیت‌ها را با خود حمل می‌کند.

تفاوت فراداده در server.json و متد server/discover چیست؟

فایل server.json برای انتشار عمومی و یافتن محل سرور یا نحوه پیکربندی آن است، در حالی که متد server/discover قابلیت‌ها، نسخه‌های فعال و وضعیت لحظه‌ای پردازش زنده را اعلام می‌کند.

چگونه از اجرای ناخواسته عملیات مخرب و تغییردهنده وضعیت جلوگیری می‌شود؟

با استفاده از اسناد تأییدیه منقضی‌شونده (Approval Records) که به شناسه کاربر، نام ابزار و هش آرگومان‌های ارسالی مقید شده‌اند؛ هرگونه دستکاری در آرگومان‌ها فراخوانی را پیش از اجرا متوقف می‌کند.

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

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