چیتشیت
تسکها، استخراج ورودی و Apps در MCP
MCP Tasks, Elicitation and Apps
دامنهی صریح، استخراج ورودی MRTR، تسکهای پایا، منابع UI در Apps و لغو ایمن در MCP 2026-07-28.
فهرست مطالب
رفتوبرگشت استخراج ورودی با MRTR
گامبهگام- کلاینتدرخواست
tools/callبا شناسه 1 وelicitation: {"form": {}}در قابلیتهای_metaمیفرستد. - سرورمقدار
resultType: "input_required"را همراه باinputRequests.delete_choiceبرمیگرداند. - سرور
requestStateرا با شناسه کاربر (principal)، متد،argumentsDigest،candidateIds، نانس و انقضا امضا میکند. - میزبانفرم را رندر میکند. کاربر یکی از گزینههای پذیرش، رد یا لغو را انتخاب میکند.
- کلاینت
tools/callرا با شناسه جدید 2،inputResponsesو همانrequestStateمجدداً ارسال میکند. - سروروضعیت را اعتبارسنجی میکند، فضای کاری را مجدداً مجوزدهی کرده و مهار مسیر را بازبینی میکند.
- سرورنانس را یکبار مصرف میکند، حذف را انجام داده و
resultType: "complete"برمیگرداند.
چرخهی حیات تسک روی هسته بیوضعیت
معماریمتدها و سیگنالهای Task
دستورها| دستور | عملکرد |
|---|---|
tasks/get | اسنپشات کامل. resultType بیرونی همیشه complete است |
tasks/update | inputResponses را ارسال میکند. یک تاییدیه خالی برمیگرداند |
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 میلیثانیه
پاسخهای استخراج ورودی
مقایسه| فاکتور | accept | decline | cancel |
|---|---|---|---|
| معنا | کاربر ارسال کرد | کاربر نپذیرفت | کاربر بست |
| اقدام سرور | اعتبارسنجی محتوا، ادامه فرایند | نتیجه امتناع کامل | توقف ایمن |
| نانس | همراه با حذف مصرف شد | مصرف شد، بدون حذف | مصرف نشد |
| تلاش مجدد در آینده | خیر | خیر | بله، تا زمان انقضا |
| نتیجه | deleted: True | deleted: False | deleted: False |
اعداد و مقادیر پیشفرض
پیشفرضها| تنظیم | پیشفرض | نکته |
|---|---|---|
Protocol version | 2026-07-28 | در _meta برای هر درخواست |
Task `ttl_ms` | 900_000 | محاسبه از زمان ایجاد |
Task `poll_interval_ms` | 1_000 | حداقل تاخیر پیشنهادی برای بررسی دورهای |
`server/discover` `ttlMs` | 300_000 | cacheScope معادل public |
`tools/list` `ttlMs` | 60_000 | مرتبشده بر اساس نام ابزار |
`requestState` expiry | 300 | ثانیههای پس از فرم |
`ReplayStore` `max_entries` | 1_000 | پر شدن ذخیرهساز خطای -32023 میدهد |
Backoff cap | 8_000 | 250 میلیثانیه ضرب در 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از سر گرفته میشود؟ - خیر. یک درخواست گوشدادن جدید ثبت و واکشی مجدد کنید.