Phase 13: Tools & Protocols

دامنه واضح و درخواست بدون تابعیت

ریشه ها در MCP 2026-07-28 منسوخ شده اند و هرگز یک جعبه قشنگ امنیتی نبوده است. دامنه را در استدلال ابزار قابل مشاهده یا URIs منابع قرار دهید، آن را در سرور مجاز کنید و زمانی که ابزار واقعا به ورودی کاربر نیاز دارد MRTR را استفاده کنید. کاربر تصمیم را می بیند، مدل دستی را می بیند و هر نمونه سرور می تواند دوباره تلاش را پردازش کند.

Type: Build

Languages: Python

Prerequisites: Phase 13 · 07 (MCP server), Phase 13 · 11 (stateless MRTR)

Time: ~60 minutes

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

  • جایگزین کردن ریشه های قدیمی با پارامترهای صریح فضای کار، URIs منابع یا پیکربندی سرور.
  • نشانه های محدوده جداگانه از مجوز، بازداشت مسیر و sandboxing سیستم عامل.
  • روش ارسال فرمelicitation/createاز طریق MRTRinput_requiredنتیجه
  • پشتیبانی از درخواست را در قابلیت های مشتری در هر درخواست تبلیغ کنید و حالت های پشتیبانی نشده را رد کنید.
  • اعتبارش را تایید کنaccept،declineوcancelو نتیجه های مشخصی.
  • تایید تخریب کننده را به یک اصل معتبر، استدلال های اصلی، مجموعه کاندیداها و انقضاء مربوط کنید.

دو مشکل مشابه

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

سرور بايد به دو سوال جواب بده

  1. اين عمليات مي تونه به چه فضاي کاري دست بزنه؟
  2. از سه تا نوت همپوشون، کاربر به کدام یک اشاره داشت؟

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

ریشه ها یک سطح مهاجرت هستند

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

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

  • AworkspaceUriیاdirectoryدر مورد بحث ابزار زمانی که دامنه هر تماس متفاوت است.
  • یک URI منابع زمانی که عملیات قبلاً یک منبع را هدف قرار می دهد.
  • پیکربندی سرور زمانی که یک انتشار یک فضای کاری ثابت را مالک می کند.
  • یک جعبه قشنگ فرآیند یا سیستم فایل زندانی زمانی که کد باید از نظر فنی قادر به فرار نباشد.

اگر یک ادغام موجود در سال 2026 تا 2728 هنوز لازم باشدroots/listدر طول پنجره تخفیف، سرور آن را در MRTR قرار می دهد inputRequests. نباید درخواست برگشت زنده را ارسال کند. این یک آداپتور مهاجرت است؛ در عوض، دستیاران جدید باید دامنه صریح را قبول کنند.

مدل می تواند یک دستی صریح را ببیند و تکرار کند. دامنه محموله حمل و نقل پنهان را بررسی، تکرار، حسابرسی و مسیر دشوارتر است.

قانون سه لایه

یک URI صریح هنوز خودش را مجاز نمی کند.

  1. Authorization:آیا این مدیر معتبر اجازه دارد از این فضای کار استفاده کند؟
  2. Containment:آیا URI هدف عادی در داخل مرز فضای کاری مجاز باقی می ماند؟
  3. Sandbox:آیا سیستم عامل می تواند مانع از فرار یک سرور آسیب دیده به هر حال باشد؟

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

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

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

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

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

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

یک سرور 2026-07-28 یک درخواست JSON-RPC معکوس را ارسال نمی کند.InputRequiredResult:

json{
  "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با یک شناسه تازه:

json{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "notes_delete",
    "arguments": {
      "workspaceUri": "file:TOK0
      "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": {}}
      }
    }
  }
}

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

مذاکره در مورد قابلیت ها به صورت درخواست صورت می گیرد

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

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

يه قدرت اجراء خالی"elicitation": {}, به عنوان یک معادل برای پشتیبانی از مطابقت فقط شکل باقی می ماند."elicitation": {"form": {}}همچنین از حالت فرم پشتیبانی می کند. یک اعلامیه فقط برای URL، "elicitation": {"url": {}}سرور نباید حالت غایب از قابلیت های درخواست فعلی را در خود قرار دهد، حتی اگر در یک درخواست قبلی آن را تبلیغ کند.

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

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

clientInfoباید برای تشخیص شامل شود، اما خود گزارش شده است و نمی تواند کاربر را برای مجوز شناسایی کند.

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

حالت فرم

حالت فرم از یک طرح JSON محدود طراحی شده برای دیالوگ های قابل استفاده استفاده استفاده می کند. ریشه یک شی است و خواص آن زمینه های اولیه یا صف های enum پشتیبانی شده است. شی های عمیق و طرح های سند عمومی شامل یک دیالوگ تأیید نیستند.

حالت فرم را برای:

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

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

سرور محتوای بازگردانده را دوباره تأیید می کند. تأیید فرم در طرف مشتری UX را بهبود می بخشد اما اعتماد ایجاد نمی کند.

حالت URL

حالت URL یک URL وب امن برای تعامل خارج از باند ارسال می کند:

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

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

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

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

شاخه های پاسخگویی

اقدامات را به عنوان تصمیمات محصول و نه نام مستعار در نظر بگیرید:

ActionMeaningSafe server behavior
acceptUser submitted the interactionValidate content and continue
declineUser explicitly refusedReturn a complete, non-error refusal outcome
cancelUser dismissed or could not finishStop safely and allow a later retry

هرگز محتوای گمشده را به عنوان رضایت تفسیر نکنید. هرگز کاهش را به یک حلقه مکرر فوری تبدیل نکنید.

حفاظت از وضعیت MRTR تخریب کننده

لیست کاندیداها نمی تواند تنها در یک مقدار Base64 فوری یا غیر امضا شده زندگی کند. یک مشتری کنترل همه چیز را که می فرستد را کنترل می کند.

درسي يه بار فايدي دولت که شامل:

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

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

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

قبل از اینکه درخواست عدم وجود را انجام دهید، تعامل را تأیید کنید.cancelهيچ جهش اي انجام نميده و تا زمان انقضاء حالت رو بازتوليد ميکنهdeclineنهايت است، پس درس بدون حذف چيزي از آن استفاده ميکنه.

آن را بسازید

code/main.pyنشان دهنده یک مدرن استnotes_deleteابزار:

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

ذخیره داده ها در حافظه است بنابراین رفتار پروتکل را بررسی کنید. قوانین امنیتی با یک پایگاه داده یکسان باقی می ماند.

ازش استفاده کن

از ریشه مخزن:

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

نقاط بازرسی انتظار می رود:

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

-باده

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

تمرینات

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

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

TermMeaning in 2026-07-28
RootsDeprecated informational workspace hints, not authorization or sandboxing
Explicit scopeWorkspace, directory, or resource handle visible in request arguments
ContainmentNormalized path-component check that keeps a target inside a boundary
ElicitationClient feature for obtaining user input during an MCP operation
Form modeIn-band structured user input using a restricted flat schema
URL modeOut-of-band interaction for sensitive or external workflows
MRTRStateless input-required result followed by a fresh retry
requestStateOpaque state echoed exactly and integrity-checked by the server
DeclineExplicit user refusal
CancelDismissal or incomplete interaction without approval

مطابقت میراث

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

خواندن بیشتر

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.