كيف يستدعي خادم MCP واجهتك البرمجية نيابة عن المستخدمين: استراتيجية رمز الإنتاج
يشرح استراتيجية الرموز الخارجية لخوادم MCP: لماذا تفشل تمرير الرموز والـ M2M، وكيف يحافظ تبادل الرموز على تماشي الصلاحيات مع المستخدمين.
يشرح استراتيجية الرموز الخارجية لخوادم MCP: لماذا تفشل تمرير الرموز والـ M2M، وكيف يحافظ تبادل الرموز على تماشي الصلاحيات مع المستخدمين.
في مقالتنا السابقة، شاركنا تجربتنا العامة في بناء خادم MCP عن بعد لـ Logto. هذه المقالة تغطي تصميم البنية وتدفق OAuth بالتفصيل.
مع اعتبار خادم MCP هو الحد الفاصل، فإن عملية المصادقة لخادم MCP عن بعد تتكوّن من جزئين: الوارد والصادر.
الجزء الوارد محدد جيداً في مواصفات MCP، وهناك الكثير من النقاشات والتنفيذات في المجتمع. وكتبنا أيضًا دليل تنفيذ من قبل. ولكن الجزء الصادر يحظى باهتمام أقل بكثير: خادم MCP يحمل فقط رمزًا للوصول إلى نفسه. كيف يمكنه استدعاء واجهة أعمالك نيابة عن المستخدم؟
كان هذا هو السؤال الذي عانينا منه أثناء تطوير خادم MCP الخاص بـ Logto. Logto Cloud هو منتج B2B متعدد المستأجرين: يمكن للمستخدم الانتماء إلى العديد من المستأجرين، والصلاحيات تأتي من دور المستخدم في كل مستأجر. والذكاء الاصطناعي لا يحتاج فقط للعمل كمستخدم، بل يجب أن يكون أيضًا ضمن المستأجر الصحيح.
تعكس هذه المقالة قراراتنا الفعلية:
من منظور OAuth، يؤدي خادم MCP عن بعد دورين في الوقت نفسه:
بمعنى آخر، يلعب خادم MCP دورًا مختلفًا على كل جانب، ويستخدم كل جانب رمزًا مختلفًا. الرمز الذي يحصل عليه عميل MCP عبر OAuth يكون موجّهًا كعميل إلى خادم MCP، وبالتالي ترفضه واجهة الأعمال عند المصادقة على الجمهور (audience).
الجزء الصادر في الأساس هو مشكلة تفويض: كيف يستدعي خادم MCP واجهات برمجية تابعة له كمستخدم وضمن صلاحيات المستخدم دون أن يحتفظ ببيانات اعتماد المستخدم؟
يبدو بناء نقطة نهاية MCP داخل خدمة واجهة الأعمال ومشاركة العمليات ونفس نظام المصادقة كخيار مباشر. بعد وزن الأمر، اخترنا النشر المستقل:
يتم نشر خادم MCP على نطاقه الخاص، mcp.logto.io، بدون ترابط خاص مع الخدمة الأساسية. إذا أردنا جعله مفتوح المصدر لاحقًا فلن يمنعنا شيء.
الخيار المدمج لا يتجنب أيضًا مشكلة الرموز: نقطة نهاية MCP وواجهة الأعمال ستشتركان في نفس معرف الموارد، لذا يحصل عميل MCP على رمز يحمل جميع صلاحيات واجهات API. مسألة "بصلاحيات من يُنفذ هذا الطلب؟" تنتقل من تبادل الرموز عبر الخدمات إلى تمرير الصلاحيات خلال العملية نفسها، وتبقى المشكلة قائمة. النشر المستقل يجبرنا على رسم حدود الصلاحيات بشكل واضح، وهو ما تناقشه بقية المقالة.
تبدأ مناقشة الاتصالات الخارجية من سؤال أساسي أكثر: ما هو الجمهور المناسب (audience) للرمز الذي يحصل عليه عميل MCP؟
إعادة استخدام معرف موارد واجهة الأعمال هو الخيار الأكثر مباشرة: واجهة إدارة Logto هي بالفعل مورد محمي بمعيار OAuth، لذا يمكن لعميل MCP طلب رمزها مباشرة ويقوم الخادم بتمريره كما هو. العديد من تنفيذات خوادم MCP المبكرة فعلت هذا تمامًا.
لكن التكلفة: إذا كان جمهور رمز MCP هو واجهة الأعمال، فلا توجد حدود واضحة للصلاحيات.
لذا كان قرارنا الأول: خادم MCP هو مورد محمي مستقل، بمعرف الموارد الخاص به (https://mcp.logto.io) ونطاقه الخاص.
هذا القرار يجعل حدود الصلاحيات واضحة، ويجعل أيضًا سؤال الاتصالات الخارجية محددًا: يمكن للرمز الوصول إلى خادم MCP فقط؛ فماذا يستخدم خادم MCP للاتصال بواجهة الأعمال؟
الآن لنستعرض النهج المختلفة.
جاءت الفكرة الأولى من تشبيه طبيعي.
لوحة تحكم Logto هي تطبيق وحيد الصفحة (SPA). طريقة استدعاء واجهة الإدارة بسيطة: يسجل المستخدم الدخول عبر OAuth في المتصفح، ويحصل على رمز موجه لواجهة الإدارة، ويستدعي الواجهة مباشرة به.
هل يمكن أن يعمل خادم MCP كنموذج آخر من لوحة التحكم؟ دعه يطلب رمز واجهة الأعمال أثناء تسجيل الدخول، وينقل الرمز كما هو بدون تعديل:
جاذبية هذا النهج هي بساطته الشديدة: خادم MCP فقط ينقل الرموز. لكن له مشكلات واضحة:
أولًا، يتعارض مباشرة مع قرار حدود الصلاحيات السابق. تمرير الرموز يتطلب أن يحمل عميل MCP رمز واجهة الأعمال، وذلك ما رفضناه سابقًا.
ثانيًا، خادم MCP لم يعد موردًا محميًا حقيقيًا. الجمهور (audience) للرموز التي يستقبلها ليس الخادم نفسه، فتصبح مصادقة الجمهور بلا قيمة وتنحصر في "توقيع الرمز والجهة المُصدِرة". هذا لا يتوافق مع طريقة تعريف المواصفة الرسمية للمصادقة (يجب على خادم MCP أن يكون خادم مورد ويعلن ذلك عبر RFC 9728). في الواقع، يتنكر كخدمة خلفية على شكل SPA في المتصفح.
ثالثًا، لن يتعاون عملاء MCP. أي عميل MCP يتبع المواصفات القياسية سيطلب الرموز مقيدًا ببيانات تعريف المورد المعلن عنها، وسيكون الجمهور هو خادم MCP. لا توجد طريقة قياسية لجعله يطلب رمز واجهة الأعمال، لذلك لا يعمل هذا على جانب العميل.
إذا لم يعد رمز المستخدم فعالًا، ماذا عن هوية خادم MCP نفسه؟
أعطِ خادم MCP تطبيقًا من نوع M2M (آلة إلى آلة)، واطلب رمز عبر بيانات الاعتماد الخاصة به، واستدعي واجهة الأعمال بهذا الرمز. هذا هو المعيار المعتاد بين الخدمات الداخلية.
المصادقة الواردة تعمل بشكل جيد الآن: رمز عميل MCP موجه لخادم MCP والباقي طبيعي، ثم تتم العملية بموجب رمز M2M الخاص بالخادم.
العيب القاتل هو أن صلاحيات رمز M2M لا علاقة لها بصلاحيات المستخدم:
يركز M2M على العمليات التي لا تتطلب سياق مستخدم، مثل المهام المجدولة والمزامنة بين الأنظمة. خادم MCP مختلف: كل اتصال يبدأ من مستخدم معين، فيجب أن يعمل بهذه الهوية والصلاحيات المحددة.
بوضع دروس النهجين السابقين معًا، تظهر متطلبات التصميم الصحيح:
يشير ذلك إلى آلية قياسية: تبادل الرموز (RFC 8693). يأخذ خادم MCP بيانات اعتماد تمثل المستخدم ويستبدلها في خادم المصادقة برمز للواجهة الخلفية. تظل هوية المستخدم وصلاحياته قائمة طوال العملية.
في Logto، تأتي "بيانات الاعتماد التي تمثل المستخدم" من ميزة انتحال المستخدم: رمز الموضوع. هو رمز قصير العمر تطلبه الخادم لمستخدم معين، ويدل على أن "تبادل الرمز التالي ينفذ باسم هذا المستخدم". لا يحتاج المستخدم إلى أي تكوين، وكل العملية مؤتمتة. رمز الموضوع قصير العمر، ويُستخدم مرة واحدة فقط ويفقد صلاحيته بعد الاستخدام.
هناك أربعة أدوار في البنية. يتم نشر خادم MCP بشكل مستقل على العنوان mcp.logto.io:
تدفق الرموز الكامل خلف كل طلب أداة:
خطوة بخطوة:
① التحقق الوارد. يستدعي عميل MCP أداة محددة برمز المستخدم. الجمهور هو معرف موارد خادم MCP، والنطاق هو mcp:all. يتحقق خادم MCP من التوقيع والجهة المُصدِرة والجمهور والنطاق ويستخرج هوية المستخدم. تتوقف العملية هنا ولا يتم تمرير هذا الرمز للواجهات الأخرى.
② هوية الخدمة. يستخدم خادم MCP بيانات اعتماده الخاصة من نوع M2M ليحصل على رمز وصول بنطاق مخصص، access:mcp:api. هذا النطاق يخدم غرضًا واحدًا: استدعاء نقطة النهاية التالية.
③ طلب رمز الموضوع وهي خطوة الحسم. يستدعي خادم MCP POST /api/mcp/subject-tokens، نقطة النهاية التي وفرتها Cloud خصيصًا لـ MCP، مقدمًا بيانات اعتماد مزدوجة في الوقت نفسه:
Authorization: رمز M2M، لإثبات "أنا خادم MCP الرسمي"x-mcp-user-token: رمز المستخدم، لإثبات "هذا المستخدم منحني التفويض والرمز ما زال صالحًا"تتحقق Cloud بالكامل من رمز المستخدم: التوقيع، الجهة المصدرة، انتهاء الصلاحية، أن يكون الجمهور لخادم MCP، وأن يشمل النطاق mcp:all. بعد التحقق، معرف المستخدم يأتي مباشرة من claim sub داخل الرمز. النقطة هنا ليس لديها أي معلمة لتحديد هوية المستخدم.
هذا التصميم يمنع إساءة استخدام بيانات اعتماد M2M. لو أن نقطة النهاية قبلت معرف مستخدم تعسفي، يمكن لأي شخص لديه بيانات اعتماد M2M انتحال شخصية أي مستخدم. بهذا الشكل، لا يمكن لخادم MCP تبادل الرموز إلا حين يقدم دليلا على إذن صحيح من المستخدم.
رمز الموضوع الصادر قصير العمر ويستخدم لمرة واحدة فقط. ولا يتم تخزينه أبدًا، بل يتم طلب واحد جديد في كل مرة.
④ الحصول على الرموز التشغيلية عبر التبادل. برمز الموضوع يتم إجراء تبادل قياسي للرموز والحصول على نوعين حسب الحاجة:
⑤ الاتصال الخارجي. يستدعي واجهة الأعمال برمز التبادل ثم يعيد النتيجة إلى عميل MCP.
سياق تعدد المستأجرين يتم التعامل معه في خطوة التبادل: المستأجر يوجد في طبقة التبادل وليس في طبقة الاتصال. list_tenants تعرض الخيارات برمز Cloud API، يختار المستخدم واحدًا أثناء المحادثة، ويستبدل خادم MCP رمز مؤسسة لهذا المستأجر. نقطة نهاية واحدة تخدم الجميع، ولا حاجة لنشر منفصل لكل مستأجر، وأي مستأجر ينشأ أثناء المحادثة متاح فورًا.
تحقق من أسباب الفشل في النهجين السابقين، ستجد أن جميعها تم التعامل معها:
x-mcp-user-token، وتتوقف السلسلة الخارجية فورًا.بالنظر للوراء، نجد أن بيانات اعتماد M2M تستخدم بشكل مناسب في التصميم النهائي: تثبت "من أنا"، أما القدرة على "العمل كمستخدم" فيجب تبادلها في الحال بتفويض المستخدم الفعلي.
بالنظر للسلسلة بأكملها، تتلخص استراتيجية الرموز للخادم MCP عن بعد في بعض النقاط:
اختبر الأمر ببساطة: افترض أن رمز عميل MCP قد تسرب. كل ما يمكن للمهاجم فعله هو استدعاء الأدوات المُتحكم بها على خادم MCP وضمن صلاحيات المستخدم فقط. إذا كان بإمكانه الوصول لكامل API مباشرة، فقد انكسرت حدود الصلاحيات.
لا يزال نظام MCP يتطور بسرعة. المصادقة الواردة مغطاة بشكل جيد عبر المواصفات، بينما "كيفية استدعاء خادم MCP للواجهات الخارجية" لا تزال متروكة لكل فريق. نأمل أن تقدم تجربتنا مرجعًا مفيدًا لك.
إذا كنت تبني خادم MCP خاص لمنتجك، تفقد حل Logto لسيناريوهات الذكاء الاصطناعي: المصادقة لتطبيقات ووكلاء وخوادم MCP الذكية. لرؤية هذه السلسلة فعليًا، اتصل بـ خادم MCP الخاص بـ Logto وجربه.
المصادر التقنية المذكورة في هذه المقالة: