فاز 13 · درس 12

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

نوع
ساختنی
زمان
حدود 60 دقیقه
زبان‌ها
Python
پیش‌نیاز
فاز 13 · درس 07 (سرور MCP)، فاز 13 · درس 11 (الگوی بی‌وضعیت MRTR)
یک فرم دیجیتالی تایید هویت شناور در کنار مرزهای حفاظتی خط‌کشی‌شده و کلیدهای دیجیتال
فهرست مطالب
  1. اهداف یادگیری
  2. دو مسئله که شبیه به نظر می‌رسند
  3. ریشه‌ها بستری برای مهاجرت هستند
  4. قانون سه‌لایه
  5. استخراج ورودی هنوز وجود دارد، اما شیوه‌ی ارسال تغییر کرده است
  6. مذاکره‌ی قابلیت‌ها به‌ازای هر درخواست است
  7. حالت فرم
  8. حالت URL
  9. شاخه‌های پاسخ
  10. محافظت از وضعیت مخرب در الگوی MRTR
  11. پیاده‌سازی از صفر
  12. اجرای عملی
  13. خروجی این درس
  14. تمرین‌ها
  15. اصطلاحات کلیدی
  16. سازگاری با نسخه‌های قدیمی
  17. برای مطالعه‌ی بیشتر

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

در این درس با مشخصات مدرن MCP آشنا می‌شوید و یاد می‌گیرید چگونه دامنه‌ی دسترسی را به‌صورت آرگومان‌های صریح تعریف کنید، اعتبارسنجی و مهار مسیر (Containment) را سمت سرور به انجام برسانید و فرآیند دریافت تعاملی ورودی از کاربر را با الگوی بی‌وضعیت MRTR و بدون نیاز به نشست‌های مداوم مدیریت کنید.

قابلیت ریشه‌ها (Roots) در نسخه‌ی 2026-07-28 پروتکل MCP منسوخ شده است و اساساً هیچ‌وقت هم سندباکس امنیتی نبوده است. دامنه‌ی دسترسی (scope) را داخل آرگومان‌های پیدای ابزار یا URIهای منبع بگذارید، مجوز آن را سمت سرور صادر کنید و هر جا ابزار واقعاً به ورودی کاربر نیاز دارد، از MRTR استفاده کنید. کاربر تصمیم را می‌بیند، مدل شناسه را دریافت می‌کند و هر نمونه‌ای از سرور می‌تواند تلاش مجدد (retry) را پردازش کند.

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

  • جایگزینی ریشه‌های منسوخ‌شده با پارامترهای صریح محیط کاری (workspace)، URIهای منبع یا پیکربندی سمت سرور.
  • تفکیک راهنماهای دامنه (scope hints) از مجوزدهی (authorization)، مهار مسیر (path containment) و سندباکس‌سازی در سطح سیستم‌عامل.
  • ارائه‌ی elicitation/create در حالت فرم از طریق نتیجه‌ی input_required در الگوی MRTR.
  • اعلان پشتیبانی از استخراج ورودی (elicitation) در قابلیت‌های کلاینت به‌ازای هر درخواست و رد حالت‌های پشتیبانی‌نشده.
  • اعتبارسنجی مقادیر accept، decline و cancel به‌عنوان پیامدهای کاملاً متمایز.
  • متصل‌کردن تأییدیه‌ی عملیات مخرب به هویت احرازشده (authenticated principal)، آرگومان‌های اصلی، مجموعه‌ی گزینه‌ها و زمان انقضا.

دو مسئله که شبیه به نظر می‌رسند

یک ابزار مدیریت یادداشت این درخواست را دریافت می‌کند: «گزارش قدیمی TPS را حذف کن.»

سرور باید به دو پرسش کاملاً متفاوت پاسخ دهد:

  1. این عملیات مجاز به دسترسی به کدام محیط کاری است؟
  2. منظور کاربر دقیقاً کدام‌یک از سه یادداشتِ مشابه بوده است؟

مورد اول مربوط به دامنه و مجوزدهی است؛ مورد دوم مربوط به ابهام‌زدایی (disambiguation) تعاملی است. یکی دانستن این دو به طراحی‌های خطرناکی ختم می‌شود؛ مثل این‌که پوشه‌ی ارسالی کلاینت را دلیلی بر این بدانیم که فراخواننده حق دارد همه‌چیز را داخل آن حذف کند.

ریشه‌ها بستری برای مهاجرت هستند

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

نسخه‌ی 2026-07-28 متدهای roots/list و notifications/roots/list_changed را برای طراحی‌های جدید منسوخ کرده است. بهتر است از یکی از این جایگزین‌های صریح استفاده کنید:

  • آرگومان ابزار مثل workspaceUri یا directory، وقتی دامنه در هر فراخوانی تغییر می‌کند.
  • یک URI منبع، وقتی عملیات از قبل روی یک منبع مشخص متمرکز است.
  • پیکربندی سمت سرور، وقتی یک استقرار فقط به یک محیط کاریِ ثابت اختصاص دارد.
  • سندباکس فرآیند یا سیستم‌فایل محصور (jailed filesystem)، وقتی کد از نظر فنی نباید تحت هیچ شرایطی بتواند به بیرون فرار کند.

اگر یک سامانه‌ی فعلی 2026-07-28 در طول دوره‌ی گذار هنوز به roots/list نیاز داشته باشد، سرور آن را داخل inputRequests در MRTR قرار می‌دهد و نباید درخواست معکوسِ زنده (live reverse request) بفرستد. این روش یک تطبیق‌دهنده (adapter) برای مهاجرت است؛ هندلرهای جدید باید مستقیماً دامنه‌ی صریح را بپذیرند.

مدل می‌تواند شناسه‌ی صریح را ببیند و همان را تکرار کند. در مقابل، دامنه‌ای که در نشست بستر انتقال (transport session) پنهان شده باشد، بررسی، بازپخش، ممیزی و مسیریابی‌اش به‌مراتب دشوارتر است.

قانون سه‌لایه

یک URI صریح هم به‌خودی‌خود به خودش مجوز نمی‌دهد. هر سه لایه را پیاده‌سازی کنید:

  1. مجوزدهی: آیا این هویتِ احرازشده اجازه‌ی استفاده از این محیط کاری را دارد؟
  2. مهار (Containment): آیا URI هدفِ نرمال‌سازی‌شده داخل مرز محیط کاریِ مجاز باقی می‌ماند؟
  3. سندباکس: آیا در صورت نفوذ به سرور، سیستم‌عامل می‌تواند مانع خروج فرآیند به بخش‌های دیگر شود؟

سروری که در این درس اجرا می‌کنیم، فهرستی مجاز (allowlist) از URIهای محیط کاری نگه می‌دارد، مسیرهای کدگذاری‌شده با کاراکتر درصد را نرمال می‌کند، مرز اجزای مسیر واقعی را می‌سنجد و درست پیش از حذف، مهار مسیر را دوباره بررسی می‌کند.

بررسی‌های سطحی و ابتدایی با پیشوند رشته‌ای اشتباه هستند:

allowed:   file:///work/notes
attacker:  file:///work/notes-evil/secret.md
traversal: file:///work/notes/%2e%2e/private.md

هر دو مسیر خصمانه‌ی بالا با رشته‌ای فریبنده شروع می‌شوند. ابتدا مسیر را نرمال کنید و سپس اجزای آن را بسنجید. سرور فایل در محیط عملیاتی باید در برابر تداخل لینک‌های نمادین (symbolic-link races) و رفتار اختصاصی مسیرها در پلتفرم‌های مختلف هم ایمن باشد.

استخراج ورودی هنوز وجود دارد، اما شیوه‌ی ارسال تغییر کرده است

استخراج ورودی قابلیت فعلی کلاینت برای دریافت ورودی از کاربر حین اجرای tools/call، prompts/get یا resources/read است. نام متد همچنان elicitation/create مانده، اما جهت جریان داده روی بستر ارتباطی عوض شده است.

در نسخه‌ی 2026-07-28، سرور دیگر درخواست معکوس JSON-RPC نمی‌فرستد، بلکه یک InputRequiredResult برمی‌گرداند:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "resultType": "input_required",
    "inputRequests": {
      "delete_choice": {
        "method": "elicitation/create",
        "params": {
          "mode": "form",
          "message": "Choose one matching note and confirm deletion.",
          "requestedSchema": {
            "type": "object",
            "properties": {
              "note_id": {
                "type": "string",
                "enum": ["note-3", "note-7", "note-14"]
              },
              "confirm": {"type": "boolean"}
            },
            "required": ["note_id", "confirm"]
          }
        }
      }
    },
    "requestState": "integrity-protected-delete-state"
  }
}

میزبان فرم را نمایش می‌دهد. کاربر می‌تواند آن را بپذیرد، صریحاً رد کند یا ببندد. سپس کلاینت درخواست اصلی tools/call را با یک شناسه‌ی تازه تکرار می‌کند:

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "notes_delete",
    "arguments": {
      "workspaceUri": "file:///Users/alice/Documents/Notes",
      "title": "TPS report"
    },
    "inputResponses": {
      "delete_choice": {
        "action": "accept",
        "content": {"note_id": "note-14", "confirm": true}
      }
    },
    "requestState": "integrity-protected-delete-state",
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {
        "elicitation": {"form": {}}
      }
    }
  }
}

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

مذاکره‌ی قابلیت‌ها به‌ازای هر درخواست است

کلاینتی که از استخراج ورودی در حالت فرم پشتیبانی می‌کند، این را اعلان می‌کند:

{
  "io.modelcontextprotocol/clientCapabilities": {
    "elicitation": {"form": {}}
  }
}

برای حفظ سازگاری، اعلانِ خالیِ قابلیت استخراج به‌صورت "elicitation": {} همچنان معادل پشتیبانی انحصاری از حالت فرم است. مقدار صریح "elicitation": {"form": {}} هم از حالت فرم پشتیبانی می‌کند. اما اعلانِ صرفاً URL به‌صورت "elicitation": {"url": {}} شامل فرم نمی‌شود. سرور نباید حالتی را داخل پاسخ بگنجاند که در قابلیت‌های درخواست فعلی وجود ندارد؛ حتی اگر درخواستی قبلی آن را اعلان کرده باشد.

همه‌ی درخواست‌ها فیلد io.modelcontextprotocol/protocolVersion را هم همراه دارند. اگر این نسخه ارسال نشود یا از نوع رشته نباشد، خطای -32602 برمی‌گردد. رشته‌ی پشتیبانی‌نشده خطای -32022 را همراه با داده‌های دقیق supported و requested برمی‌گرداند. اگر قابلیت استخراج اعلام نشود یا فقط حالت URL فرستاده شود، خطای -32021 با مقدار data.requiredCapabilities برابر با {"elicitation":{"form":{}}} بازگردانده می‌شود.

پاکتی که فاقد id در JSON-RPC باشد، اعلان (notification) است. آن را پردازش کنید، بدون این‌که پاسخ موفقیت یا خطای JSON-RPC بفرستید. در بستر Streamable HTTP، اعلانِ پذیرفته‌شده کد 202 Accepted را بدون بدنه می‌گیرد.

بهتر است clientInfo برای خطایابی ارسال شود، اما چون این داده را خود کلاینت اعلام می‌کند، نمی‌توان برای مجوزدهی به آن تکیه کرد.

سرور متد server/discover را پیاده‌سازی می‌کند و مقادیر supportedVersions، قابلیت‌ها، ttlMs و cacheScope را با resultType: "complete" برمی‌گرداند. این سرور در این طراحی مدرن ریشه‌ها را اعلان نمی‌کند. چون ابزارها را معرفی می‌کند، پیاده‌سازی متد الزامی tools/list هم ضروری است. این خروجی توصیف‌گرِ قطعیِ notes_delete، یک inputSchema معتبر از نوع شیء، متادیتای شناسه‌ی سرور و راهنماهای کَش عمومی را برمی‌گرداند.

حالت فرم

حالت فرم از یک اسکیمای JSON محدود استفاده می‌کند که برای پنجره‌های تعاملیِ کاربردی طراحی شده است. ریشه‌ی آن یک شیء است و ویژگی‌هایش فیلدهای اولیه‌ی مسطح یا آرایه‌هایی از enumهای پشتیبانی‌شده هستند. اشیای عمیقاً تو‌در‌تو و اسکیماهای همه‌منظوره‌ی سندها جایی در دیالوگ‌های تأیید ندارند.

از حالت فرم برای این موارد استفاده کنید:

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

از حالت فرم برای گذرواژه‌ها، کلیدهای API، توکن‌های دسترسی یا اطلاعات پرداخت استفاده نکنید. این داده‌های محرمانه از کلاینت MCP عبور می‌کنند و ممکن است به لاگ‌ها یا کانتکست مدل برسند.

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

حالت URL

حالت URL یک آدرس وب امن برای تعامل خارج از کانال (out-of-band) ارسال می‌کند:

{
  "method": "elicitation/create",
  "params": {
    "mode": "url",
    "message": "Connect the report service to continue.",
    "url": "https://mcp.example.com/connect/report-service"
  }
}

از این حالت زمانی استفاده کنید که اطلاعات حساس باید مستقیماً وارد یک جریان وبیِ تحت کنترل سرور شوند؛ مثل مجوزدهی به سرویس‌های شخص ثالث. کلاینت مقصد کامل را به کاربر نشان می‌دهد و پیش از باز کردن آن رضایت می‌گیرد. کلاینت نباید این URL را از قبل واکشی کند (prefetch).

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

استخراج ورودی از طریق URL جایگزین اعطای مجوز میان کلاینت MCP و سرور MCP نیست. این سازوکار برای تعاملی خارجی است که سرور MCP باید به نیابت از کاربر انجام دهد. سرور باید کاربری را که در مرورگر است به همان هویت احرازشده‌ای متصل کند که عملیات MCP را آغاز کرده بود.

شاخه‌های پاسخ

با این عملیات‌ها مثل تصمیم‌های محصولی برخورد کنید، نه نام‌های جایگزین:

عمل معنا رفتار امن سرور
accept کاربر تعامل را ثبت کرد محتوا را اعتبارسنجی کن و ادامه بده
decline کاربر صریحاً رد کرد یک خروجیِ کامل و بدون خطا از نوع امتناع برگردان
cancel کاربر پنجره را بست یا نتوانست تمام کند کار را در نقطه‌ای امن متوقف کن و اجازه‌ی تلاش مجدد در آینده را بده

هرگز نبودِ محتوا را به‌معنای موافقت در نظر نگیرید. هرگز رد درخواست (decline) را به یک حلقه‌ی تکراری از پرامپت‌ها تبدیل نکنید.

محافظت از وضعیت مخرب در الگوی MRTR

فهرست گزینه‌ها نباید صرفاً داخل پرامپت یا یک مقدار Base64 بدون امضا قرار بگیرد. کلاینت روی تمام داده‌هایی که برمی‌گرداند کنترل دارد.

در این درس، وضعیت ذخیره‌شده شامل این موارد است و امضا می‌شود:

  • هویت احرازشده؛
  • متد مبدأ؛
  • چکیده‌ی workspaceUri و title؛
  • شناسه‌های مجاز یادداشت‌ها که در فرم نمایش داده شده‌اند؛
  • مرحله‌ی عملیات؛
  • زمان انقضای کوتاه.

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

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

پیش از ثبت و مصرف نانس، تعامل را اعتبارسنجی کنید. پاسخی که ساختار نادرست داشته باشد یا لغو (cancel) شود، تغییری ایجاد نمی‌کند و وضعیت تا زمان انقضا برای تلاش مجدد باقی می‌ماند. رد صریح (decline) پایانی است؛ بنابراین در این درس نانس بدون حذف هیچ داده‌ای مصرف می‌شود.

دامنه منبع صریحاستفاده از Roots برای طراحی‌های جدید منسوخ شده است
EXPLICIT RESOURCE SCOPEPass the authorized directory or resource URI as an explicit tool argument, resource reference, or server configuration. The server resolves and contains every path before access, so the inside read succeeds and the outside path is rejected. MCP Roots remain available only during their deprecation window and never replace authorization or an OS sandbox.notes serverدامنه را بررسی می‌کندtool arg: scope=file:///project/Notesmeeting.md~/.ssh/id_rsaخواندنخواندنخارج از ریشه: رد شد
دایرکتوری یا URI منبع مجاز را به عنوان آرگومان صریح ابزار، ارجاع منبع یا پیکربندی سرور ارسال کنید. سرور قبل از دسترسی، هر مسیر را اعتبارسنجی و محدود می‌کند؛ بنابراین خواندن مسیر داخلی موفق بوده و مسیر بیرونی رد می‌شود. قابلیت MCP Roots تنها در بازه منسوخ‌شدن در دسترس است و هرگز جایگزین احراز مجوز یا سندباکس سیستم‌عامل نمی‌شود.

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

فایل code/main.py یک ابزار مدرن notes_delete را پیاده‌سازی می‌کند:

  • متد tools/list یک توصیف‌گرِ قطعی و قابل کَش همراه با اسکیمای لازم برای محیط کاری و عنوان برمی‌گرداند.
  • دامنه یک آرگومان صریح به نام workspaceUri است.
  • پیکربندی سرور به آن محیط کاری برای هویتِ این درس مجوز می‌دهد.
  • نرمال‌سازی URI تداخل پیشوندها و پیمایش دایرکتوری با کاراکترهای کدگذاری‌شده را رد می‌کند.
  • هر حذفِ مخرب نیازمند استخراج ورودی در حالت فرم است.
  • استخراج ورودی داخل ساختار resultType: "input_required" ارسال می‌شود.
  • مقدارِ امضاشده‌ی requestState فهرست دقیق گزینه‌ها و آرگومان‌های اصلی را مقید می‌کند.
  • مخزنِ بازپخشِ تزریق‌شده مانع از این می‌شود که یک وضعیتِ پذیرفته‌شده یا ردشده روی دو نمونه‌ی مختلف سرور دوباره اجرا شود.
  • تلاش مجدد با یک شناسه درخواستِ تازه انجام می‌شود و خروجی resultType: "complete" برمی‌گرداند.

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

اجرای عملی

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

cd phases/13-tools-and-protocols/12-mcp-roots-and-elicitation/code
python3 main.py
python3 -m unittest discover tests -v

چک‌پوینت‌های مورد انتظار:

  • شناسایی (Discovery) ابزارها را بدون ریشه‌ها اعلان می‌کند.
  • شناسایی ابزارها متد notes_delete را همراه با resultType، متادیتای شناسه‌ی سرور و راهنماهای کَش برمی‌گرداند.
  • شناسه‌ی درخواست 1 فرم را در inputRequests.delete_choice برمی‌گرداند.
  • شناسه‌ی درخواست 2 وضعیت امضاشده را بازتاب می‌دهد و عملیات حذف را به پایان می‌رساند.
  • هر دو مسیر پیشوندی و پیمایش کدگذاری‌شده در شرط مهار مسیر رد می‌شوند.
  • عنوانی که تغییر کرده باشد نمی‌تواند از وضعیت تأیید اولیه‌اش دوباره استفاده کند.
  • رد عملیات، یادداشت را دست‌نخورده باقی می‌گذارد.
  • دو شیء سرور که وضعیت یادداشت و بازپخش را به اشتراک دارند، نمی‌توانند هر دو یک تأییدیه را اجرا کنند.
  • اعلان‌های خالی و صریح فرم کار می‌کنند، در حالی که پشتیبانی از صرفاً URL دقیقاً خطای الزامات فرم -32021 را بازمی‌گرداند.
  • خطاهای نسخه‌ی پشتیبانی‌نشده دقیقاً ساختار داده‌ی -32022 را برمی‌گردانند.
  • اعلانِ بدون شناسه هیچ پاسخ JSON-RPC تولید نمی‌کند.

خروجی این درس

فایل outputs/skill-elicitation-form-designer.md دامنه‌ی صریح، بررسی‌های مجوز، فرم MRTR، شاخه‌های پاسخ و پیوند وضعیت را طراحی می‌کند. این فایل ریشه‌های منسوخ را سندباکس در نظر نمی‌گیرد و از جمع‌آوری اطلاعات حساس از طریق حالت فرم پرهیز می‌کند.

تمرین‌ها

  1. مخزن بازپخش درون‌حافظه‌ای را با SQLite جایگزین کنید. با یک تراکنش نانس را مصرف و یادداشت را حذف کنید؛ سپس نشان دهید دو فرآیند نمی‌توانند هر دو عملیات commit را با هم انجام دهند.
  2. مذاکره‌ی قابلیت url و یک جریان راه‌اندازی خارج از کانال را اضافه کنید. اطلاعات کاربری سرویس شخص ثالث را بیرون از inputResponses نگه دارید.
  3. نگاشت درون‌حافظه‌ای یادداشت را با یک پایگاه داده‌ی موقت SQLite عوض کنید. مجوز و مهار مسیر را دوباره داخل همان تراکنشِ تغییر بازبینی کنید.
  4. برای پیاده‌سازی واقعی روی سیستم‌فایل، سیاست پیوند نمادین (symlink) اضافه کنید. توضیح دهید چرا بررسی صرفاً واژگانیِ مهار در URI نمی‌تواند جلوی گریز از طریق پیوند نمادین را بگیرد.
  5. یک تطبیق‌دهنده برای نسخه‌ی 2025-11-25 طراحی کنید که خروجی هندلر مدرن MRTR را به استخراج ورودی قدیمیِ آغازشده توسط سرور تبدیل کند. این منطق را از هندلر فعلی جدا نگه دارید.

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

اصطلاح معنا در نسخه‌ی 2026-07-28
ریشه‌ها (Roots) راهنماهای منسوخ و اطلاع‌رسانی از محیط کاری؛ نه مجوزدهی هستند نه سندباکس
دامنه‌ی صریح (Explicit scope) شناسه‌ی محیط کاری، دایرکتوری یا منبع که در آرگومان‌های درخواست پیدا است
مهار (Containment) بررسی اجزای مسیر نرمال‌شده برای نگه‌داشتن هدف در داخل یک مرز مشخص
استخراج ورودی (Elicitation) قابلیت کلاینت برای دریافت ورودی کاربر حین اجرای عملیات MCP
حالت فرم (Form mode) دریافت ورودی ساختاریافته‌ی کاربر درون کانال با یک اسکیمای مسطح و محدود
حالت URL تعامل خارج از کانال برای جریان‌های کاری حساس یا خارجی
الگوی MRTR نتیجه‌ی بی‌وضعیتِ نیازمند ورودی که بعد از آن یک تلاش مجددِ تازه صورت می‌گیرد
وضعیت درخواست (requestState) داده‌ی مات و محرمانه‌ای که کلاینت عیناً برمی‌گرداند و یکپارچگی آن سمت سرور بررسی می‌شود
رد صریح (Decline) امتناع مستقیم و واضح کاربر
لغو (Cancel) بستن پنجره یا نیمه‌کاره ماندن تعامل بدون اعلام موافقت

سازگاری با نسخه‌های قدیمی

برای سیستمی که روی نسخه‌ی 2025-11-25 قفل شده است، ممکن است متدهای roots/list، notifications/roots/list_changed و استخراج ورودی زنده و آغازشده توسط سرور (elicitation/create) همچنان وجود داشته باشند. چنین تطبیق‌دهنده‌ای را در کد به‌عنوان نسخه‌ی قدیمی برچسب بزنید. اجازه ندهید فهرست ریشه‌های قدیمی بررسی‌های مجوز سمت سرور را دور بزند و فرضیات نشست پروتکل را وارد هندلر مدرن نکنید.

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

خودآزمایی

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

  1. پیش از درسقابلیت MCP Roots چه تضمین امنیتی ارائه می‌داد؟
  2. حین درسهنگامی که دامنه فضای کاری به ازای هر فراخوانی ابزار تغییر می‌کند، واضح‌ترین جایگزین مدرن چیست؟
  3. حین درسدریافت اطلاعات به روش فرم (form-mode elicitation) در نسخه MCP 2026-07-28 چگونه ارسال می‌شود؟
  4. حین درسکدام مقدار هرگز نباید از طریق دریافت اطلاعات به روش فرم (form-mode elicitation) جمع‌آوری شود؟
  5. پس از درسکاربر درخواست تأیید حذف را رد می‌کند. پاسخ امن و مناسب چیست؟
  6. پس از درسکدام الگو به شکل امن تأییدیه عملیات مخرب را به آنچه کاربر دیده مقید می‌سازد؟

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

چرا قابلیت ریشه‌ها (Roots) در نسخه‌ی جدید MCP منسوخ شده است؟

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

چگونه تعامل با کاربر (Elicitation) در سرورهای مدرن بدون وابستگی به نشست پیاده‌سازی می‌شود؟

سرور دیگر درخواست معکوس ارسال نمی‌کند، بلکه پاسخی با نتیجه‌ی input_required برمی‌گرداند. کلاینت فرم را به کاربر نشان داده و فراخوانی اصلی ابزار را با شناسه‌ای جدید و وضعیت امضاشده (requestState) تکرار می‌کند.

تفاوت خروجی‌های decline و cancel در پاسخ تعاملی کاربر چیست؟

مقدار decline نشان‌دهنده‌ی امتناع صریح کاربر است و یک خروجی نهایی بدون تغییر ایجاد می‌کند؛ اما cancel به معنی بستن پنجره یا ناتمام ماندن فرایند است که کار را متوقف کرده و اجازه تلاش مجدد در آینده را می‌دهد.

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

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