توسيع مهام المفوضية: العمل المستدام على أساس بلا جنسية
tools/call، أي حالة يمكن أن تجيبtasks/getومدخل العميل يصل من خلالtasks/updateبدون إحياء جلسات البروتوكولType: Build
Languages: Python
Prerequisites: Phase 13 · 09 (transports), Phase 13 · 11 (stateless MRTR), Phase 13 · 12 (elicitation)
Time: ~90 minutes
أهداف التعلم
- تمييز النقل البروتوكول بدون ولاية عن حالة مهمة التطبيق الدائمة.
- التفاوض
io.modelcontextprotocol/tasksتوسيع قدرات الطلب وserver/discover. . . - أعد إرسال محرك الخادم
CreateTaskResultمعresultType: "task"إلا بعد خلق دائم - استطلاع مع
tasks/get، اجتياز مدخل المهمة معtasks/update، وطلب إلغاء التعاون معtasks/cancel. . . - إزالة الأكبر سنا
tasks/status،tasks/resultوtasks/listالافتراضات - الاشتراك في إشعارات المهام الاختيارية عبر
subscriptions/listenعلى سلسلة SSE الإجابة POST. - انتهاء صلاحية المهام النموذجية، وإعادة تشغيل الاسترداد، وتقليل النسخة في مفتاح المدخل، وأخطاء التنفيذ بشكل صحيح.
لماذا المهام هي امتداد
ظهرت المهام لأول مرة كجزء تجريبي أساسي في 2025-11-25.io.modelcontextprotocol/tasksالتوسع حتى يتمكن العملاء والسيرفر من اختيار دورة حياة إضافية دون توسيع بروتوكول الأساس للجميع.
تبقى مواصفات التوسع مسودة سطحية على الرغم من أنها هي الموقع الرسمي الحالي للمهام. قم بتثبيت إصدار التوسع المدعوم من SDK الخاص بك، وتشغيل سيناريوهات التوافق، وعزل مكيّفات الأسلاك من مستخدمك ومجال التخزين.
استخدم المهمة عندما يكون للعملية واحدة أو أكثر من هذه الخصائص:
- قد تفوق وقت الطلب العادي
- نظام عمل عمل خارجي يمتلك بالفعل تنفيذ.
- العميل بحاجة إلى التعافي بعد إعادة تشغيله
- يتم وقف العملية لإدخال المستخدم أو النموذج أثناء التنفيذ.
- الإلغاء والحصول على النتائج الدائمة هي متطلبات المنتج.
لا تخلق مهمة للبحث التحديدي الرخيص. التدخل، الاستمرار، الاستطلاع، انتهاء الصلاحية، والإلغاء تعقيدا حقيقيا.
أساسية بدون جنسية، تطبيق دولي
إزالة MCP 2026-07-28 initialize،notifications/initialized، جلسات البروتوكول، وMcp-Session-Idهذا لا يحظر المنتجات الحكومية
تُعد هوية المهمة حالة تطبيق صريحة:
- الخادم يصرّ عليه قبل إعادتها
- العميل يمكنه تخزينها وتجربة مرة أخرى بعد إعادة تشغيلها
- يمكن أن يُوجّه الهوية إلى أي نسخة مدعومة من نفس المتجر الدائم.
- يتم التحقق من الائتمان على كل طريقة المهمة.
- يتم تعريف انتهاء الصلاحية والحذف من خلال حقل المهام، وليس مدة حياة النقل.
هذا مختلف عن الحالة الخفية المرتبطة بالاتصال.
أبقوا أربع حياة منفصلة
| State | Lifetime | Where it belongs |
|---|---|---|
| Protocol metadata | One request | params._meta, validated again on every call |
| Transport work | One stdio request or HTTP response | In-flight coordinator with a bounded deadline |
| MRTR continuation | One retry sequence | Integrity-protected requestState, plus replay controls when needed |
| Durable task | Across requests, replicas, restarts, and reconnects | Shared application store keyed by an authorized taskId |
نقل سجل المهام إلى ذاكرة العملية لا يجعل MCP حالة. يجعل التطبيق غير موثوق به. البروتوكول يبقى بلا حالة، ولكن في وقت لاحق tasks/getلا يمكن استرداد السجل. استمر قبل إعادة المقبض، ثم جعل كل طريقة المهمة لحل نفس السجل المشترك تحت الفائز والفحص الرئيسي.
التفاوض حول القدرة
يعلن العميل عن الدعم على كل طلب مؤهل:
json{
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
},
"io.modelcontextprotocol/clientInfo": {
"name": "lesson-client",
"version": "1.0.0"
}
}
}الخادم يعود بالضبطsupportedVersions، القدرات ،ttlMsوcacheScopeمنserver/discoverحيث أنها تعلن عن الأدوات، فإنها تنفيذ أيضا إلزاميةtools/listهذا النتيجة تعود إلى تحديدgenerate_reportوصف، كائن صالح inputSchema،resultType: "complete"، بيانات الهوية الخادم، وتلميحات التخزين العام.
طريقة مهمة من عميل لم يعلن عن إرجاع التوسع -32021, عدم وجود القدرة المطلوبة للعميل ، معdata.requiredCapabilitiesالمحددة إلى{"extensions":{"io.modelcontextprotocol/tasks":{}}}. تُعيد سلسلة بروتوكول غير مدعومة-32022مع دقةsupportedوrequestedالبيانات ؛ إعادة نسخة مفقودة أو غير سلسلة -32602. . .
غلاف بدون JSON-RPC idهو إشعار. قد يعالج المستلمها ، لكنه لا ينبعث عن نتيجة JSON-RPC أو خطأ. يعود مكيّف HTTP قابل للتدفق 202 Acceptedبدون هيئة للإخطار المقبول.
في الوقت الحالي فقطtools/callيدعم تنفيذ مهام معززة. تصميم التجريد الداخلي الخاص بك بحيث أن أنواع الطلبات المستقبلية لا تتطلب إعادة كتابة التخزين.
إنشاء المهام الموجهة إلى الخادم
العلم القديم للعميلparams._meta.task.requiredيُعلن العميل دعم التوسع، ثم يقرر الخادم ما إذا كان هناكtools/callيصبح مهمة
الطلب:
json{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "generate_report",
"arguments": {"size": "large"},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
}
}رد:
json{
"jsonrpc": "2.0",
"id": 1,
"result": {
"resultType": "task",
"taskId": "tsk_786512e29e0d",
"status": "working",
"statusMessage": "Preparing report outline.",
"createdAt": "2026-08-21T10:30:00Z",
"lastUpdatedAt": "2026-08-21T10:30:00Z",
"ttlMs": 900000,
"pollIntervalMs": 1000
}
}يجب أن لا يعيد الخادم هذه المقبضة حتىtasks/getفي متجر متسق في نهاية المطاف، انتظر رؤية القراءة قبل الإجابة. خلاف ذلك يمكن للعميل الحصول على هوية صالحة تبدو و تحصل على "لا يمكن العثور على" على الفور.
لا يتم طلب استجابة للمهمة بمعنى أن العميل لا يطلب وضع المهمة. لا يتم التفاوض عليه: لا يزال على الطلب الحالي إعلان التوسع.
شكل المهمة
كل مهمة تحمل:
taskId: معرف مستقر منخفض الخادمstatus:working،input_required،completed،cancelledأوfailed(إنه)createdAtوlastUpdatedAt: طوابع زمنية ISO 8601ttlMs: مدة انتهاء الصلاحية من الابتكار، أوnullبدون حد إعلاني- اختيارية
pollIntervalMs: الحد الأدنى المفترض للحصول على الانتخابات من الخادم - اختيارية
statusMessage: سياق يستهدف المستخدم أو النموذج.
تظهر الحقول الخاصة بالحالة فقط عندما تكون ذات صلة:
input_requiredيشملinputRequests. . .completedيتضمن طلب الأصليresultالشكلfailedيتضمن JSON-RPCerror-أجسام
يجب على العميل أن يحترمpollIntervalMsقد يحدد الخادم المعدلات التي تستهدف استطلاعات أكثر عدوانية ويمكن أن يغير الفاصل على مدى عمر المهمة.
استطلاع معtasks/get
العميل يطلب صورة حالية:
httpPOST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tasks/get
Mcp-Name: tsk_786512e29e0djson{
"jsonrpc": "2.0",
"id": 2,
"method": "tasks/get",
"params": {
"taskId": "tsk_786512e29e0d",
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
}
}tasks/getنفسها قد اكتملت، لذلك نتيجة لها دائماresultType: "complete"المهمة المُعقدة لا تزال قد تكونstatus: "working"أوstatus: "input_required". . .
هذا التمييز يمنع حدوث خطأ عام في المصفح:
textresult.resultType = complete means the tasks/get RPC finished
result.status = working means the represented job is still runningلا يوجدtasks/resultعندما تنتهي المهمة، القادمtasks/getرد يطابق الأصلي CallToolResultتحتresult:
json{
"resultType": "complete",
"taskId": "tsk_786512e29e0d",
"status": "completed",
"createdAt": "2026-08-21T10:30:00Z",
"lastUpdatedAt": "2026-08-21T10:34:12Z",
"ttlMs": 900000,
"result": {
"resultType": "complete",
"content": [
{"type": "text", "text": "Generated large report with approved outline."}
],
"structuredContent": {"size": "large", "approved": true},
"isError": false,
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "tasks-demo",
"version": "1.0.0"
}
}
},
"_meta": {
"io.modelcontextprotocol/serverInfo": {
"name": "tasks-demo",
"version": "1.0.0"
}
}
}الخارجيresultTypeيقولtasks/getتم إكمال عملية التجربةresult.resultTypeيقول أن الاتصال الأصلي للدوائر قد تم، ويتطلب ذلك التمييز المتعثر.CallToolResultيجب أن تحمل أيضاًio.modelcontextprotocol/serverInfoهذا الدروس يتضمنها بدلا من تخزين حمولة مفيدة غير محددة.
لا يوجدtasks/list. لا يمكن لخادمات غير الجلسة استنتاج الآمن عن المهام التي تنتمي إلى قائمة محددة عن الاتصال. يجب على التطبيقات التي تحتاج إلى تاريخ الكشف عن أداة نطاق مصرح بها مع مرشحات صريحة وقواعد الملكية.
إدخال أثناء تنفيذ المهمة
إن إدخال المهمة و MRTR الأساسية تبدو متشابهة ولكنها تستخدم مواصلات مختلفة.
الإدخال المطلوب قبل إنشاء المهمة
النواة العائدةresultType: "input_required"من الأصليtools/callالعميل يقوم بذلك ويحاول مرة أخرى الاتصال الأصلي فقط إخلال المهمة بعد انتهاء تلك الجولات المزامنة
الإدخال المطلوب بعد إنشاء المهمة
حدد المهمةinput_required. .tasks/getيُكشف عن المميزاتinputRequestsو يقوم العميل بإرسال الردود من خلالtasks/updateالعميل لا يحاول إعادة التطبيق الأصليtools/call. . .
صورة سريعة:
json{
"resultType": "complete",
"taskId": "tsk_786512e29e0d",
"status": "input_required",
"createdAt": "2026-08-21T10:30:00Z",
"lastUpdatedAt": "2026-08-21T10:31:00Z",
"ttlMs": 900000,
"inputRequests": {
"approve_outline": {
"method": "elicitation/create",
"params": {
"mode": "form",
"message": "Approve the generated report outline?",
"requestedSchema": {
"type": "object",
"properties": {"approved": {"type": "boolean"}},
"required": ["approved"]
}
}
}
}
}تحديث:
httpPOST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tasks/update
Mcp-Name: tsk_786512e29e0djson{
"jsonrpc": "2.0",
"id": 4,
"method": "tasks/update",
"params": {
"taskId": "tsk_786512e29e0d",
"inputResponses": {
"approve_outline": {
"action": "accept",
"content": {"approved": true}
}
},
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
}
}رد النجاح هو اعتراف فارغ بالإضافةresultType: "complete"قد يكون التغيير في الدولة متسقًا في النهاية، لذا يواصل العميل إجراء الاستطلاع أو الاستماع.
كل واحدinputRequestsيجب أن تكون مفتاحها فريدة طوال عمر المهمة.tasks/getقد تظهر اللقطات الفورية نفس المفتاح المتبقي؛ العملاء يقللون من واجهة المستخدم ويتجاهلون الخوادم الاستجابات لمفاتيح غير معروفة أو استبدلت أو تمت بالفعل.input_requiredحتى يتم الإجابة على جميع المفاتيح المطلوبة
الإلغاء هو تعاون
tasks/cancelإشارات النية وتعطي إقرارًا فارغًا كاملًا. هذا الإقرار لا يضمن توقف العامل. قد ينتهي العمل أولاً، أو يتجاهل الإلغاء أو الانتقال في وقت لاحق.
httpPOST /mcp HTTP/1.1
Content-Type: application/json
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tasks/cancel
Mcp-Name: tsk_786512e29e0djson{
"jsonrpc": "2.0",
"id": 5,
"method": "tasks/cancel",
"params": {
"taskId": "tsk_786512e29e0d",
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientCapabilities": {
"extensions": {
"io.modelcontextprotocol/tasks": {}
}
}
}
}
}لكل أساليب المهمة الثلاثةMcp-Nameالمرآةparams.taskId. لا تكرر اسم طريقة JSON-RPC. code/main.pyيمركز هذا القاعدة في make_http_request. . .
يقوم العامل في الدروس بتشرف الإلغاء على الفور، ويعمل على المكالمات المتكررة غير قابلة. لا يزال على عميل الإنتاج أن يعامل الإلغاء كمتعاون بدلاً من استنتاج حالة المهمة النهائية من التأكيد.
لا تستخدمnotifications/cancelledلتحل مهمة، هذا الإخطار ينتمي إلى طلب إلغاء، وليس مهمات دائمة.
الاختلاف مهم في حدود التوجيه. استبعد الطلب يستهدف عملية JSON-RPC واحدة في الطيران أو استجابة HTTP المحددة لطلبها. إذا tools/callلقد عاد بالفعلresultType: "task"، أن الطلب كامل وإغلاق النقل لا يمكن أن يذكر أو توقف العمل الدائم. tasks/cancelهو مركز جديد مصرح به.params.taskId، مرآة تلك الهوية فيMcp-Name، يحل الخلفية المملكة للمهمة، ويُسجل نية إلغاء التعاون، ويُعيد تأكيدًا دون أن يدعي العامل أنه توقف.
وبالتالي يجب على البوابة أن تحتفظ بمنسقات الطلبات وطرق المهام في جداول مختلفة. يمكن أن تختفي جدول الطلبات عند انتهاء الاستجابة. يجب أن تبقى مسار المهام حتى تنتهي الحالة النهائية والاحتفاظ بها. Lesson 29: MCP Reliability, Cancellation, and Flow Controlيُبني السباق، وقتاً وقفياً، وفرصاً، و ضغوطاً، و إعادة محاولة القواعد لكلا الطرق.
الإخطارات الاختيارية
الاستطلاع هو الخط الأساسي العميل الذي يريد تحديثات دفع يرسلهاsubscriptions/listenمع أرقام المهام. بالنسبة إلى HTTP المباشر ، هذه هي POST التي تكون استجابةها تدفق SSE المطلوب. لا يوجد تدفق حدث GET مستقل ولا جلسة بروتوكول للحفاظ على الحياة.
الجهاز يقر بأسم الشخصية المقبولة مع notifications/subscriptions/acknowledgedويمكن بعد ذلك إرسال اللقطات الفورية الكاملة من خلال notifications/tasks. الإقرار وكل إشعار مهمة يحملio.modelcontextprotocol/subscriptionIdفي_meta, يساوي subscriptions/listenكل إشعار مهمة يعادل ما هو عليهtasks/getسيعود في تلك اللحظة
يجب على العملاء أن يعلنوا على طول المهام. يجب أن يعيدوا الاتصال واستئناف من أوراق تعريف المهام الدائمة بدلاً من الاعتماد على إعادة عرض الأحداث أو Last-Event-ID. . .
النقص في النطقية
استخدم طبقتين الخطأ بشكل صحيح.
خطأ بروتوكول
عدة معايير غير صالحة للطريقة أو اسم مهم مجهول يعيد خطأ JSON-RPC، عادة -32602. غياب بيانات دعم التمديد-32021مع جسم القدرة المطلوب.
نتائج تنفيذ المهمة
- نتيجة أداة طبيعية مع
isError: trueما زالcompletedالمهمة لأن دعوة الأداة قدمت نتيجة محددة. - خطأ JSON-RPC أثناء التنفيذ المؤجل يجعل المهمة
failedوتخزن خطأ JSON-RPC تحتerror. . . - الرفض المستخدم يمكن أن يؤدي إلى
cancelledنتيجة رفض كاملة أو نتيجة آمنة أخرى محددة للمجال.
استمرارية، انتهاء صلاحية، وملكية
استمر على الأقل في تحديد اسم المهمة ، والحالة ، والخوابات الزمنية ، ttl ، فترة الاستطلاع ، والمتلكية الأصلية للعملية ، والنتيجة أو الخطأ ، والطلبات المتبقية للمدخول ، وجميع مفاتيح المدخل الصادرة.
يجب أن يحتوي مفتاح التخزين على مستأجر ومدير مصرح أو يحل ذلك. لا يجب أن يمنح معرفة هوية المهمة الوصول. تحقق من ملكية كل tasks/get،tasks/update،tasks/cancel، والإشتراك
ttlMsيمكن للمستخدمين أن يستخدموا هذه المعلومات في التطبيقات، ويمكن أن يستخدمها في التطبيقات، ويمكن أن يتم قياسها من وقت إنشاءها ويمكن أن يتغير. يمكن للمستخدمين التعامل معها كمساعدة خلفية عندما توقفت المهمة عن إنتاج تحديثات قابلة للملاحظة. قد يفشل الخادم ويمحو في وقت لاحق مهمة انتهت صلاحيتها. لا تصفها كوعد بالاحتفاظ بالنتيجة المكتملة لعدة ملثانية بعد الانتهاء.
استخدام الكتب الذرية أو المعاملات. الدرس يكتب ملفًا مؤقتًا ويُعيد تسميته بشكل ذري. يجب أن تستخدم خدمة متعددة النسخة متجرًا دائمًا مشتركًا وترخيص عامل أو تحكم متزامن معادلة.
بناءها
code/main.pyتنفيذ خدمة مهمة تحديدية:
server/discoverالعائداتsupportedVersions، إشارات التخزين، ومدّة المهامtools/listيعود تحديد، قابلة للتخفيضgenerate_reportوصف مع مخطط إدخال صالح.tools/callيخلق و يواصل المهمة قبل العودةresultType: "task". . .- مثال خدمة جديد يُعيد تحميل نفس المهمة، يُظهر إعادة تشغيل التعافي.
tasks/getيعيد صور اللقطات الكاملة للمهمة.- العامل ينتقل من
workingإلىinput_required. . . tasks/updateيقبل استجابة من النموذج ويرد إقرارًا كاملًا فارغًا.- العامل يحتفظ بمثابة عُش
CallToolResultمع أفرادهاresultTypeو هويت الخادم ، ثم الانتقال إلىcompleted. . . tasks/cancelلا يُمكن أن يكون ذلك ممكناً في هذا التنفيذ.- أجهزة بناء HTTP
Mcp-Nameإلىparams.taskIdلـtasks/get،tasks/updateوtasks/cancel. . . - المساعدون في الإخطار يستخدمون
notifications/subscriptions/acknowledgedوnotifications/tasks، كلاهما مع علامة اسم طلب الاستماع. - الإخطارات بدون ID لا تنتج استجابة JSON-RPC.
يعمل العامل بشكل صريح بدلاً من النوم في خيط خلفي، مما يجعل كل انتقال حالة محدداً ويحافظ على مثال البروتوكول منفصل عن ميكانيكا الصف.
استخدمها
من جذور المخبأ:
bashcd phases/13-tools-and-protocols/13-mcp-async-tasks/code
python3 main.py
python3 -m unittest discover tests -vتسلسل النتائج المتوقع:
textid=0 resultType=complete status=ack
id=1 resultType=task status=working
id=2 resultType=complete status=working
id=3 resultType=complete status=input_required
id=4 resultType=complete status=ack
id=5 resultType=complete status=completedأيضاً تأكد من ذلكtasks/status،tasks/resultوtasks/listطريقة العودة لا توجد في الخدمة الحديثة.
تأكد من ذلكtools/listهو تحديدية وكل طريقة مهمة HTTP الحالية تعكس اسم المهمة من خلال Mcp-Name. . .
أرسله
outputs/skill-task-store-designer.mdالآن تنتج تصميمًا واعًا للتوسع: تفاوض القدرات، إنشاء استمرار قبل العودة، والطرق الحالية، وتدفق تحديث المدخلات، والمالك، والانتهاء من الصلاحية، والإلغاء، والإشتراك، والهجرة من الطرق التجريبية المزودة.
التمارين
- إضافة مفتاح إدخال ثانياً لا يزال قائماً. أرسل مفتاح جزئي
tasks/updateو إثبات أن المهمة لا تزال قائمةinput_requiredحتى يتم الإجابة على كلتا المفاتيح - إضافة ملكية المستأجر إلى المتجر ورفض هوية مهمة صالحة قدمتها رئيس المصادقة الخطأ.
- إضافة عقد تأجير العمال مع انتهاء صلاحيتها. إثبات أن حالات الخدمة لا يمكن أن تقوم بنفس المهمة في وقت واحد.
- تنفيذ مُعدل SSE للرد على POST
subscriptions/listenلا تضيف GETLast-Event-IDأو عنوان جلسة - إضافة تنظيف انتهاء الصلاحية. تمييز مهمة انتهت الصلاحية من هوية مهمة خاطئة دون تسريب وجود المتبادل المستأجر.
الشروط الرئيسية
| Term | Meaning in the current extension |
|---|---|
| Tasks extension | Optional io.modelcontextprotocol/tasks capability for durable async work |
CreateTaskResult | Server-directed resultType: "task" response to an eligible request |
tasks/get | Poll a full current task snapshot, including terminal result or pending input |
tasks/update | Submit responses to a task's outstanding inputRequests |
tasks/cancel | Acknowledge cooperative cancellation intent |
input_required | Task status indicating client input is outstanding |
pollIntervalMs | Server-suggested minimum delay before another poll |
ttlMs | Expiry duration measured from task creation |
| Durable-before-return | Rule that the task id must resolve before its handle is sent |
notifications/tasks | Optional full task snapshot delivered on a subscribed SSE response |
التوافق مع التراث
السطح التجريبي 2025-11-25 استخدم زيادة المهام التي طلبها العميلtasks/status،tasks/result، و اختياري tasks/list. إبقوا هذه الأسماء فقط داخل مُعدّل إرث مُثبت . العميل الحالي يستخدم إمكانية التوسع ، يقبل المُسَلّطات المُوجّهة إلى الخادم ، استطلاعاتtasks/get، يقدم المدخلات مع tasks/update، ويقرأ النتيجة النهائية من صورة المهام.
المزيد من القراءة
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.