چیت‌شیت

تسک‌ها، استخراج ورودی و Apps در MCP

MCP Tasks, Elicitation and Apps

دامنه‌ی صریح، استخراج ورودی MRTR، تسک‌های پایا، منابع UI در Apps و لغو ایمن در MCP 2026-07-28.

  • ۱۱ بخش
  • ۴ درس مرتبط
  • کد و دستورها عیناً از دوره‌ی اصلی
فهرست مطالب
  1. رفت‌وبرگشت استخراج ورودی با MRTR
  2. چرخه‌ی حیات تسک روی هسته بی‌وضعیت
  3. متدها و سیگنال‌های Task
  4. پیشبرد یک وظیفه پایا
  5. پایایی در تکرار، بافرها و اتصال مجدد
  6. پاسخ‌های استخراج ورودی
  7. اعداد و مقادیر پیش‌فرض
  8. خطاها و شکست‌ها
  9. قوانین Apps
  10. قوانین دامنه (Scope)
  11. پرسش‌ها

رفت‌وبرگشت استخراج ورودی با MRTR

گام‌به‌گام
  1. کلاینتدرخواست tools/call با شناسه 1 و elicitation: {"form": {}} در قابلیت‌های _meta می‌فرستد.
  2. سرورمقدار resultType: "input_required" را همراه با inputRequests.delete_choice برمی‌گرداند.
  3. سرورrequestState را با شناسه کاربر (principal)، متد، argumentsDigest، candidateIds، نانس و انقضا امضا می‌کند.
  4. میزبانفرم را رندر می‌کند. کاربر یکی از گزینه‌های پذیرش، رد یا لغو را انتخاب می‌کند.
  5. کلاینتtools/call را با شناسه جدید 2، inputResponses و همان requestState مجدداً ارسال می‌کند.
  6. سروروضعیت را اعتبارسنجی می‌کند، فضای کاری را مجدداً مجوزدهی کرده و مهار مسیر را بازبینی می‌کند.
  7. سرورنانس را یک‌بار مصرف می‌کند، حذف را انجام داده و resultType: "complete" برمی‌گرداند.

چرخه‌ی حیات تسک روی هسته بی‌وضعیت

معماری
_metataskIdleaseworkertasks/updateworkertasks/cancelکلاینتاکستنشن tasks را اعلام می‌کندtools/callresultType taskذخیره‌ساز پایاذخیره پیش از بازگرداندن پاسخWorkeradvance_workerworkingstatusMessageinput_requiredinputRequestscompletedنتیجه تودرتولغوشده یا ناموفقخطا در صورت ناموفق بودن

متدها و سیگنال‌های Task

دستورها
دستورعملکرد
tasks/getاسنپ‌شات کامل. resultType بیرونی همیشه complete است
tasks/updateinputResponses را ارسال می‌کند. یک تاییدیه خالی برمی‌گرداند
tasks/cancelنیت لغو را ثبت می‌کند. تاییدیه دریافتی وضعیت نهایی نیست
subscriptions/listenدرخواست POST با استریم پاسخ SSE از اسنپ‌شات‌های وظیفه
notifications/tasksاسنپ‌شات کامل برچسب‌گذاری‌شده با شناسه درخواست listen
notifications/cancelledدرخواست لغو فقط روی stdio؛ هرگز برای Task استفاده نمی‌شود
Close the response streamدرخواست لغو روی پروتکل HTTP جریانی
`tasks/status`, `tasks/result`, `tasks/list`حذف شد. متد یافت نشد

پیشبرد یک وظیفه پایا

کد
python
service = TaskService(directory)       # TaskStore مبتنی بر فایل
created = service.dispatch(make_request(1, "tools/call",
    {"name": "generate_report", "arguments": {"size": "large"}}))
task_id = created["result"]["taskId"]  # resultType task، working
service = TaskService(directory)       # نمونه جدید آن را بازخوانی می‌کند
service.advance_worker(task_id)        # working به input_required
service.dispatch(make_request(3, "tasks/get", {"taskId": task_id}))
service.dispatch(make_request(4, "tasks/update", {"taskId": task_id,
    "inputResponses": {"approve_outline": {"action": "accept",
                                           "content": {"approved": True}}}}))
service.advance_worker(task_id)        # مرحله 2 به completed
body, headers = make_http_request(5, "tasks/get", {"taskId": task_id})
headers["Mcp-Name"]                    # برابر با params.taskId

پایایی در تکرار، بافرها و اتصال مجدد

کد
python
ledger = MutationLedger(Path(directory) / "mutations.sqlite3")
ledger.charge("acct-7", 1200, rpc_id=41, idempotency_key="checkout-7")
ledger.charge("acct-7", 1200, rpc_id=42, idempotency_key="checkout-7")
ledger.executions                                       # یک اجرا، همان رسید
classify_retry(side_effect=True, idempotency_key=None)  # ناامن
buffer = BoundedSseBuffer(3)                            # ظرفیت حداقل دو مورد
buffer.push_final(response)                             # پاسخ نهایی هرگز دور ریخته نمی‌شود
reconnect_plan(previous_subscription_id, affected_resources,
               unsafe_mutation_was_in_flight=True)      # sendLastEventId معادل False
retry_delay_ms("<client>", attempt)                     # محدود به 8000 میلی‌ثانیه

پاسخ‌های استخراج ورودی

مقایسه
فاکتورacceptdeclinecancel
معناکاربر ارسال کردکاربر نپذیرفتکاربر بست
اقدام سروراعتبارسنجی محتوا، ادامه فرایندنتیجه امتناع کاملتوقف ایمن
نانسهمراه با حذف مصرف شدمصرف شد، بدون حذفمصرف نشد
تلاش مجدد در آیندهخیرخیربله، تا زمان انقضا
نتیجهdeleted: Truedeleted: Falsedeleted: False

اعداد و مقادیر پیش‌فرض

پیش‌فرض‌ها
تنظیمپیش‌فرضنکته
Protocol version2026-07-28در _meta برای هر درخواست
Task `ttl_ms`900_000محاسبه از زمان ایجاد
Task `poll_interval_ms`1_000حداقل تاخیر پیشنهادی برای بررسی دوره‌ای
`server/discover` `ttlMs`300_000cacheScope معادل public
`tools/list` `ttlMs`60_000مرتب‌شده بر اساس نام ابزار
`requestState` expiry300ثانیه‌های پس از فرم
`ReplayStore` `max_entries`1_000پر شدن ذخیره‌ساز خطای -32023 می‌دهد
Backoff cap8_000250 میلی‌ثانیه ضرب در 2 در هر تلاش

خطاها و شکست‌ها

عیب‌یابی
  • -32602

    علت
    نسخه پروتکل ناموجود یا غیررشته‌ای است
    راه‌حل
    نسخه را در _meta ارسال کنید
  • -32022

    علت
    رشته نسخه پشتیبانی نمی‌شود
    راه‌حل
    داده‌های supported و requested را بخوانید
  • -32021

    علت
    قابلیت form یا tasks یا ui وجود ندارد
    راه‌حل
    آن را در این درخواست اعلام کنید
  • -32020

    علت
    ناهماهنگی هدر و بدنه
    راه‌حل
    Mcp-Method و Mcp-Name را مطابقت دهید
  • شناسه تسک خطای not found می‌دهد

    علت
    هندل قبل از امکان خواندن توسط ذخیره‌ساز ارسال شده
    راه‌حل
    پیش از بازگرداندن پاسخ داده را ذخیره کنید
  • عملیات تغییردهنده دو بار اجرا می‌شود

    علت
    شناسه جدید JSON-RPC برای حذف تکرار استفاده شده
    راه‌حل
    یک کلید یکتایی تراکنش پایا اضافه کنید
  • کار معلق هرگز پایان نمی‌یابد

    علت
    پیشرفت با هر ضرب‌الاجل بازنشانی می‌شود
    راه‌حل
    یک مهلت حداکثری قطعی در نظر بگیرید
  • واسط کاربری وضعیت را متوقف اعلام می‌کند، worker در حال اجراست

    علت
    تاییدیه لغو به عنوان وضعیت نهایی خوانده شده
    راه‌حل
    وظیفه را تا رسیدن به وضعیت نهایی پایش کنید

قوانین Apps

مفهوم‌ها
اکستنشن
io.modelcontextprotocol/ui، اعلام‌شده توسط هر دو طرف ارتباط در هر درخواست.
اتصال (Binding)
مقدار _meta.ui.resourceUri روی ابزار در tools/list، قبل از هر فراخوانی.
منبع
ui://notes/timeline.html با نوع MIME معادل text/html;profile=mcp-app.
سیاست CSP
فیلدهای connectDomains، resourceDomains، frameDomains و baseUriDomains به‌طور پیش‌فرض خالی هستند.
رابط (Bridge)
نما ابتدا ui/initialize و پس از پاسخ میزبان ui/notifications/initialized را ارسال می‌کند.
طرح پشتیبان
نبود قابلیت ui، ابزار را بدون _meta.ui و همراه با نتیجه متنی ارائه می‌دهد.
کلید حافظه پنهان
شناسه یکتای ui://، هویت سرور و نسخه، خلاصه‌ی محتوای منبع، و در صورت خصوصی بودن، شناسه کاربر.

قوانین دامنه (Scope)

نکته‌ها
  • ریشه‌ها منسوخ شده‌اند. دامنه را در آرگومان workspaceUri یا یک شناسه یکتای منبع قرار دهید.
  • سه لایه را اعمال کنید: مجوزدهی، مهار مسیر و یک ساندباکس در سطح سیستم‌عامل.
  • ابتدا URI را نرمال‌سازی کنید. سپس بخش‌های مسیر را مقایسه کنید، نه پیشوندهای متنی را.
  • هرگز از حالت فرم برای گذرواژه‌ها، کلیدهای API، توکن‌ها یا داده‌های پرداخت استفاده نکنید.
  • گزینه accept در حالت URL یعنی کاربر با باز کردن پیوند موافقت کرده، نه اثبات تکمیل کار.
  • مقدار خالی "elicitation": {} به معنای پشتیبانی از فرم است؛ حالت فقط-URL چنین نیست.

پرسش‌ها

پرسش و پاسخ
چه کسی تصمیم می‌گیرد یک فراخوانی به وظیفه تبدیل شود؟
سرور. کلاینت فقط اکستنشن را اعلام می‌کند.
نتیجه نهایی وظیفه کجاست؟
زیر فیلد result در اسنپ‌شات بعدی متد tasks/get.
ورودی قبل از ایجاد وظیفه است یا بعد از آن؟
قبل: تلاش مجدد MRTR. بعد: متد tasks/update.
آیا ui/initialize یک نشست MCP آغاز می‌کند؟
خیر. صرفاً دست‌دادن رابط کاربری iframe است.
آیا نتیجه ابزار با isError: true یک وظیفه ناموفق است؟
خیر. وضعیت وظیفه completed است.
آیا استریم قطع‌شده با Last-Event-ID از سر گرفته می‌شود؟
خیر. یک درخواست گوش‌دادن جدید ثبت و واکشی مجدد کنید.