Phase 13: Tools & Protocols

الموارد والمطالبة في MCP: السياق المُعالج للخادمات التي لا تملك ولاية

أدوات تقوم بعمليات. الموارد تعرض المحتوى المُعالج. تطلب من الحزمة نماذج الرسائل التي حددها المستخدم. خادم MCP جيد يحافظ على هذه العقود منفصلة ومتوقعة.

Type: Build

Languages: Python

Prerequisites: Phase 13, Lesson 07 (Building an MCP Server), Phase 13, Lesson 09 (MCP Transports)

Time: ~60 minutes

أهداف التعلم

  • اختر من بين الأدوات والموارد والإشارات من نية المستهلك.
  • إعلان عن الموارد والسطح السريع من خلال الإجبارية server/discover. . .
  • بناء تحديدات resources/listوprompts/listالنتائج
  • التطبيقttlMsوcacheScopeبدون تسريب بيانات محددة للمستخدم.
  • إرجاع خطأ JSON-RPC -32602لـ URI غير صالح أو مجهول للموارد.
  • افتحsubscriptions/listenتحرك POST- ردود الفعل وتنسجم كل حدث عن طريق معرف الاشتراك.
  • تعامل محتوى الموارد والعلامات التشريعية على أنها خروج خادم غير موثوق بها.

ابدأ من المستهلك

أسهل طريقة للاستخدام السيء لمكب هو البدء في كود التنفيذ. تصبح استفسار قاعدة البيانات أداة لأن الوظائف مألوفة. تصبح سير العمل القابل لإعادة الاستخدام مصدرًا لأنه يتم تخزينه في ملف. يصبح الإشارة سياسة مخفية لأن المضيف يمكنه حقنها.

ابدأ من يختار وما يتوقعه

PrimitivePrimary intentSelection ownerTypical result
ToolPerform an operationModel or applicationStructured action result
ResourceRead content at a URIHost, application, or userText or binary content
PromptStart a reusable message workflowUser through host UIOne or more prompt messages

ملاحظة فيnotes://note-1هو مصدر لأنه محتوى قابل للتعديل. delete_noteهو أداة لأنه يغير الحالة.review_noteهو طلب لأن المستخدم يختار سير عمل مراجعة جاهز.

لا تظهر عملية واحدة ككل ثلاثة فقط لتبدو كاملة. كل سطح إضافي يحتاج إلى اكتشاف، والإذن، والخزن الآلي، ومعالجة الأخطاء، والاختبارات، والوثائق.

غلاف العدالة 2026-07-28

هذا الدروس يهدف إلى مراجعة بروتوكول MCP 2026-07-28لا توجد أي إضافة يد أو جلسة بروتوكول في هذا الملف . كل طلب يحمل نسخة بروتوكوله و قدرات العميل في محجوز_metaالمفاتيح

json{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "resources/list",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientInfo": {
        "name": "course-client",
        "version": "1.0.0"
      },
      "io.modelcontextprotocol/clientCapabilities": {}
    }
  }
}

يجب على الخادم تنفيذserver/discover. إعلانات النتيجة مدعومة

الإصدارات، وقدرات الموارد والإسراع، و هوية التنفيذ،

يُمكن لعميل أن يطلب طريقة أخرى مباشرة، لكن الاكتشاف يعطيه

صورة دقيقة واحدة مستقرة قبل أن تبني واجهة اتصال.

json{
  "resultType": "complete",
  "supportedVersions": ["2026-07-28"],
  "capabilities": {
    "resources": {"listChanged": true, "subscribe": true},
    "prompts": {"listChanged": true}
  },
  "ttlMs": 3600000,
  "cacheScope": "public"
}

نتيجة طبيعية"resultType": "complete"ردّة_metaيحدد تنفيذ الخدمة مع io.modelcontextprotocol/serverInfoهذه المعلومات مفيدة للتشخيص. انها ليست هوية تصديقة. طلب يحمل مراجعة غير مدعومة يعود-32022مع كل من مراجعة الطلب والإصلاحات المدعومة من الخادم.

العقد غير الحكومي يغير غرائز التصميم الخاصة بك. ليست القائمة يمكن أن تعتمد على اتصال سابق على اتصال واحد. قد تغير الإذن مجموعة مرئية لأن الإثباتات هي إدخال طلب، ولكن تاريخ الاتصال لا يجب.

الموارد هي عقود URI مستقرة

الموارد هي المحتوى الذي يتم تحديده بواسطة URI. صمم URI قبل المدير.

خصائص URI الجيدة:

  • مستقر بما فيه الكفاية لتعليق أو تمرير بين الطلبات.
  • تم تحويل الاسم إلى نطاق الخادم
  • مستقل عن هوية العملية أو الاتصال.
  • تم التحقق من التحقق من الوصول إلى المخزن
  • مُصرح بكل قراءة

notes://note-1هو أفضل منnote-1لأن مساحة أسمائها واضحة. قد يستخدم خادم الملفات file://و لكن يجب أن تحقق حدود الإداريات المكوّنة بعد حل الروابط المُتَشابكة والجزء النسبي.

resources/listيعيد الموارد المرئية حاليا للمدعو. يتم فرزها بمفتاح مستقرة مثل URI. النظام التحديدي يمنع إغفال الاحتفاظ السريع، وتغيير اللقطات الفورية، وUI المضيف التي تتفوق بين التحديثات.

json{
  "resultType": "complete",
  "resources": [
    {
      "uri": "notes:TOK0
      "name": "Architecture decision",
      "description": "Why the service uses a stateless boundary",
      "mimeType": "text/markdown"
    }
  ],
  "ttlMs": 300000,
  "cacheScope": "public",
  "_meta": {
    "io.modelcontextprotocol/serverInfo": {
      "name": "notes-server",
      "version": "2.0.0"
    }
  }
}

resources/readيعيد عنصرًا أو أكثر من المحتوى. لا تعتبر URI غير معروفة قراءة فارغة ناجحة. تُخصص تخصيص الموارد الحالية URI غير صالحة أو غير معروفة للموارد إلى معايير JSON-RPC غير صالحة ، رمز -32602. . .

json{
  "jsonrpc": "2.0",
  "id": 2,
  "error": {
    "code": -32602,
    "message": "Unknown or invalid resource URI",
    "data": {
      "uri": "notes://missing"
    }
  }
}

هذا التمييز يسمح للعميل بفصل غياب من وثيقة فارغة سارية. كما يمنع الانكماش العشوائي إلى بحث أوسع.

نماذج الموارد

نموذج الموارد يصف عائلة من المعلمات URIs. استخدم واحدة عند إدراج كل عنصر ملموس سيكون مكلفا أو غير محدود. على سبيل المثال، notes://projects/{project}/decisions/{decision}يخبر العميل كيفية تشكيل عنوان صالح دون إرجاع كل قرار

لا يضعف الشكل التحقق من التحقق من المصادقة. تحليل المتغيرات، وتطبيق الإذن، وتنفيذ حدود الطول والشخصيات، وبناء استفسارات التخزين مع المعلمات المكتوبة. لا تخلق أبداً سلسلة تعسفية من ذيل URI في مسار نظام الملفات أو بيان قاعدة البيانات.

المحتوى ليس تعليم موثوق به

قد يحتوي نص الموارد على حقن سريع أو أسرار أو أوامر مضللة أو علامات غير مُصممة. يجب على المضيف الحفاظ على منشأ المحتوى الموارد ومعاملة المحتوى الموارد كبيانات. يجب على الخادم الحد من حجم المحتوى، وإرجاع نوع MIME دقيق، وتحرير الحقول التي لا يستطيع المُتصل الوصول إليها، وتجنب إرجاع السجلات غير ذات الصلة.

الإشارات هي نماذج يتم التحكم فيها من قبل المستخدم

تم تصميم طلبات MCP لتحديد المستخدم صريح. يمكن للمضيف أن يعرضها كأوامر شرائح أو عناصر قائمة أو أزرار سير العمل. لا يتطلب البروتوكول واجهة اتصال واحدة.

prompts/listيجب أن تكون محددة لنفس تصريح الطلب. كل عرض يحتاج إلى اسم ثابت وصف مفيد، وإعلانات الحجج التي تسمح للمضيف جمع المدخلات قبل prompts/get. . .

json{
  "resultType": "complete",
  "prompts": [
    {
      "name": "review_note",
      "title": "Review a note",
      "description": "Review one note for a named concern",
      "arguments": [
        {
          "name": "uri",
          "description": "The note resource URI",
          "required": true
        }
      ]
    }
  ],
  "ttlMs": 600000,
  "cacheScope": "public"
}

prompts/getيحل الحجج في الرسائل. لا يحل محل تعليمات النظام المضيف. يقرر المضيف كيفية إدخال الرسائل المرجعة في سياق النموذج ويضع سياسة الثقة الخاصة به في الأولوية العليا.

تأكيد الحجج المطلوبة في حدود الخادم. يجب أن تمر URI المطلوبة نفس فحص التأذن مثل قراءة الموارد المباشرة. لا تجعل من المطلوبة قناة جانبية حول وصول الموارد.

إشارات الاحتفاظ بها هي جزء من الصواب

ttlMsيخبر العميل كم من الوقت يمكن إعادة استخدام النتيجة. cacheScopeيصف من قد يشارك هذه القيمة المحفوظة.

ScopeMeaningTypical use
publicMay be reused across users when authorization permitsPublic prompt catalog
privateBound to the requesting user or credential contextUser-owned note content

اختر TTL من معدل تغيير البيانات وتلف التأخير. خمس دقائق قد تناسب كتالوجية استقالة عامة. قد تستغرق ملاحظة خاصة قراءة دقيقة واحدة.

المخططات المحددة فقط publicوprivateكـcacheScopeقيم. لتحقيق نتيجة سرية أو تتغير بسرعة، عودة cacheScope: "private"معttlMs: 0، ثم تطبيق أي قاعدة أكثر صرامة لا متجر في سياسة مخزن المضيف. no-storeهو نفسه ليس مؤسسة إدارة الأعمالcacheScopeقيمة

لا تحل إشارات الاحتفاظ بالمكان أبداً محل الإذن. يجب أن يتضمن مفتاح الاحتفاظ بالمكان كل بعد طلب يغير المرئية ، بما في ذلك المستأجر والمستخدم ومدى الموقع ومؤشر البيانات. إذا لم يتمكن الاحتفاظ بالمكان المشترك من تعبير هذه الأبعاد بأمان ، فاستخدم privateمع صفر TTL وسياسة عدم وجود متجر على مستوى المضيف.

الاشتراكات استخدام تدفق الاستجابة المفتوحة من العميل

النمط الحديث للتسجيل يحل محل السابق resources/subscribeRPC والنقطة النهائية القديمة لحدث HTTP GET.

العميل يرسلsubscriptions/listenعلى HTTP Streamable هذا هو POST الذي يبقى استجابة مفتوحة كمتد SSE.notificationsالمواد هي قائمة السماح. يجب أن لا يقدم الخادم أنواع الإخطارات التي لم يتم طلبها.

json{
  "jsonrpc": "2.0",
  "id": 17,
  "method": "subscriptions/listen",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "course-client",
        "version": "1.0.0"
      }
    },
    "notifications": {
      "resourcesListChanged": true,
      "promptsListChanged": true,
      "resourceSubscriptions": [
        "notes://note-1"
      ]
    }
  }
}

هو اسم الطلب هو اسم الاشتراك قبل أي حدث مطلوب، يقوم الخادم بإرسال notifications/subscriptions/acknowledged. فالتشريعه يحتوي فقط على مجموعة فرعية القبول بها الخادم

json{
  "jsonrpc": "2.0",
  "method": "notifications/subscriptions/acknowledged",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 17
    },
    "notifications": {
      "resourcesListChanged": true,
      "resourceSubscriptions": [
        "notes://note-1"
      ]
    }
  }
}

كل حدث لاحقا على هذا التيار يحمل نفس البيانات

json{
  "jsonrpc": "2.0",
  "method": "notifications/resources/updated",
  "params": {
    "_meta": {
      "io.modelcontextprotocol/subscriptionId": 17
    },
    "uri": "notes://note-1"
  }
}

الإخطار يقول أن الموارد تغيرت. العميل يقرأها مرة أخرى من خلال resources/readلا يفترض أن الحدث يحتوي على الوثيقة الجديدة.

يمكن لمعظم الاشتراكات مشاركة قناة استوديو واحدة. يسمح معرف الاشتراك بالعميل بتخسيف عددها. عبر HTTP ، إغلاق تيار الاستجابة يلغي الاشتراك. يقوم الخادم الذي ينتهي من التدفق بإعجاب بإرجاع آخر resultType: "complete"رد مرتبط بالطلب الأصلي.

لا تستخدم تدفق الاشتراك كجلسة بروتوكول. القراءة اللاحقة لا تزال طلبًا كاملًا يمكن أن يصل إلى أي حالة خادم صحية.

المختبر التفاعلي

استخدم الرقم لتصنيف خمسة قدرات من متابعة المشروع: تفاصيل الإصدار، إنشاء مشكلة، نموذج مراجعة السباق، سياسة المشروع، وإغلاق مشكلة. ثم تحدد أي القوائم يمكن تخزينها علنا، والتي يجب أن تبقى سرية، والموارد التي تستحق إشعارات تحديث.

لكل تصنيف، اسم المختار. إذا كان النموذج يقوم بعمل، استخدم أداة. إذا كان المضيف يقرأ المحتوى الموجهة بـ URI، استخدم مصدر. إذا بدأ المستخدم سير عمل رسالة جاهز، استخدم طلب.

مختبر التدريب

تشغيل المحاكي من جذور المخبأ:

bashcd phases/13-tools-and-protocols/10-mcp-resources-and-prompts/code
python3 main.py
python3 -m unittest discover tests -v

تحقق من النسخة في هذا الترتيب:

  1. تأكّدserver/discoverيعلن عن المراجعة الحالية وكلا الإمكانيات.
  2. تأكد من أن نتائج القائمة مرتبة واستخدامهاresultType: "complete". . .
  3. تأكيد القائمة و نتائج القراءة تحمل إشارات مخزنية متعمدة.
  4. تغيير URI القراءة إلى notes://missingوراقب-32602. . .
  5. تأكيد تأكيد الاشتراك قبل حدث الموارد.
  6. تأكيد الحدث و إغلاقها بشكل لطيف كل من تحمل بطاقة الاشتراك5. . .

نموذج Python لا يفتح اتصال HTTP حقيقي. إنه يمثل الرسائل التي يجب أن تضعها SDK على تيار الاستجابة المتفق على الطلب. استخدم SDK الرسمي للإطار والنقل في الإنتاج.

الأثاث المُرسل

outputs/skill-primitive-splitter.mdهو مراجعة تصميم قابلة لإعادة الاستخدام لانتخاب MCP البدائي. فإنه يفتتح الآن اكتشافات تحديدية، نطاق التخزين الآلي، سلوك URI غير صالح، وصفائم الاشتراك الحديثة.

الدرس أيضاً سفنassets/primitive-split.svg، نسخة ثابتة من الحدود البدائية والإشتراك للدراسة غير متصلة.

تحقق من ذلك

bashcd phases/13-tools-and-protocols/10-mcp-resources-and-prompts/code
python3 main.py
python3 -m unittest discover tests -v

النتيجة المتوقعة: البرنامج الرئيسي يطبخ نسخة JSON ويقوم أمر الاختبار بإبلاغ عن اثني عشر اختبارا على الأقل.

اتصال كابستون

استخدم هذا العقد عندما يعرض خادم الحجر النهائي المعرفة المقدمة للعنوان إلى جانب الإجراءات. تضم صورة مفاجئة من الكتالوج المحددة، وقراءة مصدر مصرح به، وحل واحد سريع، حالة URI غير صالحة، ونسخة الاشتراك واحدة.

يجب أن تظهر أدلة أن أي قائمة تعتمد على تاريخ الاتصال وأن حدث الاشتراك لا يمنح أبداً الوصول إلى الموارد الأساسية.

التمارين

  1. إضافةnotes://projects/{project}/notes/{id}نموذج الموارد وتؤكد على كلا المتغيرين.
  2. إضافة صفحة إلى resources/listمع الحفاظ على النظام التحديدي
  3. تغيير مصدر واحد إلى cacheScope: "private"معttlMs: 0، إضافة سياسة عدم وجود متجر على مستوى المضيف، وتفسير التهديد الذي يبرر كلا التحكمين.
  4. إضافة اشتراك لتغيير قائمة الاستعلامات وإثبات عدم إرسال أي حدث عند حذف المرشح promptsListChanged. . .
  5. إعداد اشتراكات متزايدة و إثبات أن كل حدث يحمل معرف الطلب الصحيح.
  6. إضافة تفويض موضوع إلى المعاملة القراءة وإثبات إدخال التخزين الآلي لا يمكن أن تتقاطع الموضوعات.

الشروط الرئيسية

  • Resource:المحتوى المُعَدَّى بـ URI الذي كشف عنه خادم MCP.
  • Prompt:نموذج رسائل يسيطر عليه المستخدم يتم عرضها من قبل خادم MCP.
  • Deterministic list:نتيجة اكتشاف مع عضوية مستقرة وتطلب نفس المدخلات الطلب.
  • ttlMs:تخزين مدة الطفولة في الميلي ثانية
  • cacheScope:الحدود المشتركة لنتائج مخزنة
  • subscriptions/listen:طلب طويل الأمد يقدم تدفق الاستجابة فيه إخطارات مختصة صراحة.
  • Subscription ID:هوية طلب الاستماع الأصلية، تكرر في بيانات البيانات المعلوماتية.
  • Invalid parameters:خطأ JSON-RPC -32602، يستخدم لـ URI غير صالح أو مجهول للموارد.
  • Unsupported protocol version:خطأ JSON-RPC -32022، بما في ذلكsupportedوrequestedالإصلاحات
  • server/discover:طريقة خادم إلزامية تعيد الإصلاحات المدعومة والقدرات والهوية والإشارات الاحتياطية الاختيارية.

المزيد من القراءة

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.