Phase 13: Tools & Protocols

بناء خادم MCP: بيثون بلا حالة و TypeScript

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

Type: Build

Languages: Python, TypeScript

Prerequisites: Phase 13, Lesson 06

Time: ~85 minutes

أهداف التعلم

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

المشكلة

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

المفوضية2026-07-28يحل بروتوكول جزء من هذه المشكلة عن طريق جعل كل طلب وصف الذاتي. لا يزال تطبيقك يمكن أن تحتفظ بقوائم دائمة، وظائف، أو التعاملات الحالة الصريحة. ما لا يمكن أن تحتفظ به هو حالة بروتوكول مخفية التي تغير كيفية فك طلب لاحقا.

هذه الدروس تبني خادم ملاحظات مرتين. تستخدم إصدارات Python و TypeScript فقط مكتباتها القياسية للبرنامج الأساسي. كلاهما يعرض نفس الطرق ويفرض نفس العقد السلكي.

المفهوم

حلقة الرسائل الحديثة

textread one JSON-RPC line
parse the envelope
if it is a notification, do not respond
validate params._meta for this request
route by method
wrap success with resultType and serverInfo
write one JSON-RPC response line
forget request-scoped metadata

ثلاثة قواعد استوديو لا تزال مهمة:

  • اكتب فقط رسائل JSON-RPC إلى stdout أرسل التشخيص إلى stderr
  • حدد الرسائل مع خط جديد وفرز كل رد
  • اخرج فوراً عندما يصل القائم إلى مركز الطيران

عمر العملية هو حياة النقل. إنه ليس جلسة MCP الحديثة.

التحقق من التحقق من التحقق من التحقق من التحقق

كل طلب يجب أن يكون:

json{
  "params": {
    "_meta": {
      "io.modelcontextprotocol/protocolVersion": "2026-07-28",
      "io.modelcontextprotocol/clientCapabilities": {},
      "io.modelcontextprotocol/clientInfo": {
        "name": "notes-client",
        "version": "1.0.0"
      }
    }
  }
}

الحقول الأولى والثانية مطلوبة.clientInfoيوصى به. تأكيد شكل هوية موجود، ولكن لا تعامله كتحقق.

إذا كان الإصدار غير مدعوم، عودة الرمز -32022معrequestedوsupported. المعلومات المفقودة عن الطلب غير صالحة-32602لا تملأ أبداً الحقول المفقودة من مكالمة سابقة

الاكتشاف المفروض

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

json{
  "resultType": "complete",
  "supportedVersions": ["2026-07-28"],
  "capabilities": {
    "tools": {"listChanged": false},
    "resources": {"listChanged": false, "subscribe": false},
    "prompts": {"listChanged": false}
  },
  "ttlMs": 3600000,
  "cacheScope": "public",
  "_meta": {
    "io.modelcontextprotocol/serverInfo": {
      "name": "notes-server",
      "version": "2.0.0"
    }
  }
}

لا يفتح "ديسكوير" الخادم، قد يتصل العميلtools/listدون أن نسمي اكتشافاً لأنtools/listيحتوي بالفعل على نفس البيانات المعدنية للمطالبة.

الأدوات

tools/listيعود قائمة تحديدية من وصفات الأدوات. يحسن ترتيب الاستجابة من تخزين الاستجابة ويبقي سياق النموذج مستقرا. النتيجة تتطلب أيضا ttlMsوcacheScope. . .

tools/callيعيد كتلة المحتوى وisError. استخدم خطأ JSON-RPC عندما تكون غلاف البروتوكول أو معايير الطريقة غير صالحة. استخدم isError: trueعندما يتم تشغيل دعوة أداة صالحة ولكن الأداة نفسها تفشل.

تعليقات الأدوات لا تزال إشارات، وليس إجراءات:

  • readOnlyHint
  • destructiveHint
  • idempotentHint
  • openWorldHint

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

الموارد

resources/listيعود وصفات URI مستقرة. resources/readيعود المحتوى المكتوب. كليهما قابلة للتخزين في 2026-07-28، لذا كلاهما يتضمنttlMsوcacheScope. . .

استخدامcacheScope: "private"لا يجوز لإعادة استخدام الاحتياطي المشترك للردود الخاصة عبر سياقات الائتمان.

التغيير الحديث لا يستخدم resources/subscribe. العميل يفتحsubscriptions/listenو الطلباتresourceSubscriptionsأو فئات تغيير القائمة. الدروس 10 تبني هذا التدفق.

الإشارات

prompts/listهو قابلة للتخفيض و تحديد.prompts/getيعطي عرضًا مسمّىً مع حجج. النتيجة المسمّمة للمساعدة كاملة، ولكنها ليست من القائمة القابلة للتخزين أو نتائج القراءة التي تتطلب إشارات التخزين.

كل نتيجة ناجحة يتم كتابتها

تستخدم الأمثلة لفاحة واحدة لكل نجاح:

pythondef complete(payload):
    return {
        "resultType": "complete",
        **payload,
        "_meta": {SERVER_INFO_KEY: SERVER_INFO},
    }

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

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

قد يرسل الخادم الحديث إشعارات تتعلق بطلب العميل ، أو إشعارات على خادم مفتوح subscriptions/listenلا يجب أن يرسل طلب JSON-RPC الخاص به.

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

التوافق الصريح مع التراث

يمكن أن ينفذ خادم عصر مزدوج أيضاً2025-11-25يضغط على فرع إرث منفصل بشكل واضح. يختار السلوك الحديث عندما يتطلب الحديث_metaالحقول موجودة وتتراث السلوك عندما يتلقى initialize. . .

لا تضع2026-07-28الطلب من خلال المسار التمسك اليدوي التراثي. لا تملأ الحديث resultTypeالنتائج التبني المترتبة على التبني المترتبة على النتائج المترتبة على التبني المترتبة على التبني المترتبة على النتائج المترتبة على التبني المترتبة على النتائج المترتبة على التبني المترتبة على النتائج المترتبة على التبني المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتائج المترتبة على النتبة

استخدمها

تشغيل عرض التجربة المحدودة لخادم Python واختبارات:

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

تشغيل منفذ TypeScript مع متشغل TypeScript:

bashnpx tsx main.ts --demo

الظهور يرسلهserver/discoverيردّ كل طلب حديث بيانات أساسية. كل نجاح يتضمن هوية الخادم.

أرسله

هذه الدروس تُسافرoutputs/skill-mcp-server-scaffolder.md. إنّه ينتج خطة خادم حديثة مع عقد اكتشاف، وتصديق حسب الطلب، وقوائم تحديدية قابلة للتخزين، ومعدّل إرث معزول اختياري.

التمارين

  1. إزالة القدرات من طلب واحد وإثبات أن الخادم لا يستخدم إعلان الطلب السابق مرة أخرى.
  2. عكس الـTOOLS،PROMPTSتأكد من أن جميع نتائج القائمة تظل مستقرة
  3. إضافة مدمرة notes_deleteأداة و تتطلب فحص الإذن داخل المنفذ.destructiveHintكلمحة عن تجربة التأثير فقط
  4. إضافةresources/templates/listمعttlMs،cacheScope، و التنظيم المحدد
  5. قم ببناء مُعدل إرث منفصل لـ 2025-11-25إضافة اختبارات تثبت أن طلب حديث لا يدخل

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

TermMeaning
Stateless serverHandles each request from its own metadata without protocol-session memory
server/discoverMandatory modern method that advertises versions and capabilities
Complete resultSuccessful modern result with resultType: "complete"
Cacheable resultDiscovery, list, or resource-read result with ttlMs and cacheScope
Deterministic listSame logical registry produces the same item order
Server identityRecommended io.modelcontextprotocol/serverInfo in result _meta
Tool errorValid tool call that returns content with isError: true
Protocol errorInvalid JSON-RPC or MCP request returned through error

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

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.