Phase 13: Tools & Protocols

بناء عميل MCP: اكتشاف، توجيه، والعودة إلى العصر المزدوج

يقوم عميل MCP الحديث بتكرار عقده على كل طلب. أصعب قرار التوافق هو معرفة متى يكون الخادم القديم قديمًا حقًا ومتى يقوم الخادم الحديث بتقديم إخطاء يمكن تصحيحه.

Type: Build

Languages: Python

Prerequisites: Phase 13, Lesson 07

Time: ~85 minutes

أهداف التعلم

  • بناء كل MCP 2026-07-28الطلب مع البيانات المعدنية الحالية.
  • استكشاف الخوادم الاستوديو مع server/discoverو اختر نسخة تدعمها بعضها البعض
  • أذن بمسح التراث المحدود فقط لأقران مسموحين صراحة.
  • تقبل عصر التراث فقط بعد التحقق من إيجابيةinitializeالنتيجة لإعادة النظر المدعومة.
  • دمج قائمة أدوات تحديدية دون تغطية الصدامات بصمت.
  • اتصالات طريق إلى الزميل الذي يمتلك كل أداة دون اختراع جلسات بروتوكول.

المشكلة

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

  • نعم2026-07-28يسهل مراجعة حالة الاستقرار لأن كل طلب مستقل. يجعلها التوافق أكثر دقة. قد يواجه العميل:
  • خادم حديث يدعم الإصدار المفضل
  • خادم حديث يعيد نسخة معترف بها أو خطأ رأس؛
  • خادم سابق لم يسمع به من قبلserver/discover(إنه)
  • خادم سابق يبقى صامتًا حتى يتلقىinitialize. . .

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

المفهوم

زميل، وليس جلسة بروتوكول

الحفاظ على سجل نقل واحد لجميع عمليات الخادم أو نقاط النهاية:

  • وظيفة التحويل أو إرسال؛
  • عصر و نسخة البروتوكول المختارة
  • آخر قدرات الخادم التي اكتشفتها؛
  • قائمة أدوات تحديد الأخيرة
  • بطلبات الهوية المعلقة للتصديق؛
  • الصحة النقلية

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

بناء كل طلب حديث من الصفر

pythondef modern_request(request_id, method, params, version, capabilities):
    return {
        "jsonrpc": "2.0",
        "id": request_id,
        "method": method,
        "params": {
            **params,
            "_meta": {
                "io.modelcontextprotocol/protocolVersion": version,
                "io.modelcontextprotocol/clientCapabilities": capabilities,
                "io.modelcontextprotocol/clientInfo": CLIENT_INFO,
            },
        },
    }

لا تضع البيانات المعدنية مرة واحدة على كائن الاتصال وتفترض أنها وصلت إلى الأسلاك.

اكتشاف حديث

server/discoverيعود الإصدارات المدعومة، وقدرات الخادم، والتعليمات، وتلميحات التخزين الآلي، و هوية الخادم الموصى بها. يختار العميل أعلى إصدار جديد مدعوم بشكل متبادل.

اكتشاف هو اختياري لعميل حديث فقط، ولكن يوصى به على الاستوديوه. بعض الخوادم القديمة تقبل عملية قبل البدء، لذلك إرسال tools/listيمكن أن يؤدي ذلك إلى نجاح غير واضحserver/discoverيخلق حدود عصرا نظيفة

صنعة التوافق مع الاستديو

موكيل استديو من عصر مزدوج يرسلserver/discoverمع البيانات المعدنية الحديثة المفضلة قبل أي طلب آخر. هناك ثلاث فئات النتيجة:

  1. DiscoverResult.الخادم حديث، اختر نسخة مدعومة بشكل متبادل واستمر في إعداد البيانات المعدنية حسب الطلب.
  2. Recognized modern error.الخادم حديث-32022، اختر من بينdata.supportedو حاول مرة أخرى باستخدام معرف طلب جديد. لخطأ الرأس أو القدرة، تصحيح الطلب. لا ترسل initialize. . .
  3. Ambiguous signal.خطأ JSON-RPC غير معروف ، أو وقت انتهاء، أو إغلاق الاتصال ، أو استجابة فارغة لا تعريف عصر. يتم إغلاق الفشل ما لم يتم تكوين هذا النظير الدقيق للتوافق القديم.

تشمل الأخطاء المعترف بها في بروتوكول الحديث:

  • -32020الرأس غير متطابق
  • -32021المطلوب (المستقبل)
  • -32022غير مدعوم بروتوكول الإصدار

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

لا تعالج-32601كدليل إيجابي على التراث. يجعل فقط من المسموح به صراحة أن يكون مؤهلاً لمسح واحد إرث. نفس القاعدة تنطبق على وقت وقف، إغلاق الاتصال، أو رد الفراغ.

الإذن هو نية المشغل، وليس دليل

يجب أن تكون التوافق التراثية خاصية صريحة لتنسيق واحد من الأقران:

pythonclient.add_server("archive", archive_transport, allow_legacy=True)

ربط هذا الخيار بالقيادة أو نقطة النهاية الموضحة. لا تستخدم بطاقة برية تسمح لخادم تعسفي بتخيار نفسه في التعريفات الأساسية الأضعف.allow_legacy=Trueيفشل بعد نتائج اكتشاف غامضة ولا يحصل أبداًinitialize. . .

المُسجل يمنح الإذن بالتحقيق، لا يختار العصر، يرسله العميلinitializeفي غضون موعد محدد فرض النقل، ثم يتطلب كل ما يلي:

  • JSON-RPC 2.0الإجابة بتصريح الطلب المماثل
  • بالضبط واحدresultو لاerror(إنه)
  • أprotocolVersionفي مجموعة مراجعات القديمة المكوّنة للعميل؛
  • قيمة كائن capabilitiesالحقل
  • أserverInfoكائن مع سلسلة غير فارغة nameوversionالحقول

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

حفظ العصر المحدد لزميل النقل لا تُسائل مرة أخرى قبل كل مكالمة

التراث هو فرع التوافق

بمجرد أن يعود المسح المحدود إلى دليل إيجابي صحيح على التراث، يستخدم العميل النسخة المختارة للتراث بالضبط كما هو محدد في تلك المراجعة:

  1. التحقق من غلاف الاستجابة و رقم العلاقة.
  2. التحقق من أن الإصلاح المفاوض عليه موجود في مجموعة التراث المثبتة.
  3. سجل القدرات الموثقة و هوية الخادم.
  4. أرسلnotifications/initializedفقط بعد مرور كل الشيكات
  5. استخدم أشكال طلبات سابقة لهذا عمر النقل.

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

أدوات اكتشاف وتخزين الاحتفاظ بالملف

لكل زميل نشط، اتصلtools/listالنتيجة الحديثة تشملresultType،ttlMsوcacheScope. احترم إشارة الطفولة في سياق الترخيص الصحيح . إعادة التسجيل بعد انتهاء الصلاحية أو حدث تغيير القائمة المشترك

العملاء يجب أن يعالجوا المفقودينresultTypeمن خادم سابق مثل "complete"لا تتطلب حقل التخزين الحديثة على استجابة من عصر سابق من التفاوض.

يجب على الخادم إرجاع التنظيمات الحتمية. يجب على العميل أيضًا فرز قبل الاندماج بحيث لا يعتمد ترتيب السجل المحلي على توقيت بدء العملية.

دمج مساحة الأسماء الآمنة من الاصطدام

خادمين قد يكتشفون كل منهماsearchاختر السياسة المعلنة:

  1. Prefix on collision.احتفظ بالاسم القنوني الأول واكشف التصادمات اللاحقة<server>/<tool>. . .
  2. Reject on collision.لا تحميل المكرر وتظهر خطأ واضح في التكوين.
  3. Silent overwrite.لا تستخدم هذه أبداً إنها تخفي أي خادم يتلقى إجراءً تم اختياره من النموذج

تخزين كل من الاسماء القنونية والمقلية. النموذج يرى الاسم القنوني. الخروج tools/callيستخدم الاسم المحلي الذي أعلن عنه الخادم المالك.

توجيه مكالمة

التوجيه هو البحث البسيط:

textcanonical tool name
  -> peer name + local tool name
  -> new JSON-RPC request id
  -> modern request metadata or explicit legacy shape
  -> matching response id

لا ترسل مكالمة عندما لا تكون النقل المالك متاحة. اعيد ربط النقل أو إعادة تشغيله، ثم إعادة تشغيل اكتشاف و tools/listيمكن إعادة محاولة طلبات الطيران الحديثة المفقودة في عملية النقل المكسورة باستخدام هوية JSON-RPC الجديدة عندما تسمح سياسة السلامة العملية بذلك.

الإخطارات والتسجيلات

تغييرات القائمة والموارد الحديثة تأتي فقط على العميل المفتوح subscriptions/listenالعميل يرسل مرشح الإخطار، ينتظرnotifications/subscriptions/acknowledged، وترتبط الأحداث مع اسم طلب الاستماع في بيانات البيانات المعلوماتية.

عند إيقاف الاتصال، افتح طلب الاستماع الجديد وإعادة إعادة إعادة إعادة القوائم أو الموارد ذات الصلة.Last-Event-ID. . .

لا يوجد طلبات من الخادم

الخوادم الحديثة لا تدعو العميل مع طلبات JSON-RPC المستقلة لنظرية العينات أو الإجراءات أو الجذور.input_required، والعميل يحاول مرة أخرى الطلب الأصلي بعد استيفاء طلبات المدخلات المضمنة.

لا تمنع قراءة استجابة الزملاء أثناء إكمال المدخلات. الحفاظ على التواصل وإنشاء هوية JSON-RPC الجديدة للمحاولة المُجددة.

استخدمها

code/main.pyيستخدم وظائف النظير في العملية بحيث تبقى قرارات البروتوكول مرئية. يربط مع اثنين من النظيرين الحديثين ونظير واحد من النظيرين المترافقين المُسَمَح به عمداً، ثم يدمج ويرسل أدواتهم. يتلقى جهاز الاتصال النقل ميزانية فترة فترة حتى لا يمكن لقعة التوافق إخفاء صفقة غير محدودة.

bashcd code
python3 main.py
python3 -m unittest discover tests -v

الاختبارات تثبت حدود التي تفوت الديمو العادية:

  • الطلبات الحديثة تكرر البيانات المعدنية.
  • -32022إعادة الاكتشاف الحديث دون تشغيل؛
  • الأخطاء الحديثة المعترف بها لا تخفض أبداً، حتى بالنسبة لزميل مسموح به؛
  • التوقفات الزمنية، إغلاق الاتصال، الاستجابات الفارغة، والخطأ غير المعترف به لا يؤدي إلىinitializeبدون مسجلة
  • يصبح النسيق المُسجل في القائمة إرثًا فقط بعد وجود مؤلف معتمدinitializeالنتيجة
  • النتائج المتبقية غير المثبتة والتي لم يتم دعمها تجعل النسخة غير متوفرة.
  • يتم حفظ عصر مختار بنجاح على طول عمر النقل.

أرسله

هذه الدروس تُسافرoutputs/skill-mcp-client-harness.md. يضمن طوابع الطلبات الحديثة ، وتفاوض عصر الاستديو ، وتدمير مساحة الأسماء المحددة ، والتوجه ، وفرع التوافق القديم المغلق.

التمارين

  1. إرجاع الخادم المزيف-32022لا يوجد نسخة مدعومة بشكل متبادل. تأكد فشل العميل بدلاً من إرسالinitialize. . .
  2. السماح بخادم سابق مزيف، وجعل حدوده initializeأُسَفِقُ وقتَ، وَأثبتُ أنْ يَبْقىُ أقرانهunknownو غير متوفر
  3. إضافةcacheScope: "private"قائمة الأدوات لـ"إتفاقيّة تصريحين" تأكّد أن العميل لا يشارك أبداً النتيجة المحفوظة في مخزن واحد مع الآخر.
  4. تغيير سياسة الصدام إلى رفض وجعل البدء يفشل مع كلتا الأسماء في الخطأ.
  5. إضافة مقياس محدود subscriptions/listenعند فقدان التدفق، إستمع مرة أخرى مع معرف طلب جديد وأدوات إعادة التدفق.

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

TermMeaning
PeerClient-side record for one server transport and its discovered data
Protocol eraModern per-request metadata or legacy initialization semantics
Discovery probeInitial server/discover used to identify the stdio era
Recognized modern errorError that proves modern behavior and forbids legacy fallback
Legacy allowlistOperator configuration permitting one bounded compatibility probe for a pinned peer
Positive legacy evidenceValid, correlated initialize result for an explicitly supported legacy revision
Merged namespaceCanonical tool names across all active peers
Collision policyPrefix or reject rule for duplicate tool names
Era cacheSelected modern or legacy behavior stored for one transport peer
Transport recoveryRestart or reconnect, rediscover, relist, and retry safely with a new id

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

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.