في هذا المقال، سنستعرض كيف نفّذنا خادم MCP (Model Context Protocol) من الدرجة الأولى و OAuth gateway لمنصتنا العقارية المدعومة بالذكاء الاصطناعي. الهدف هو تمكين عملاء LLM من استدعاء أدوات النطاق بأمان (Kadaster، تصنيفات الطاقة، تحليل الموقع، تقييمات المستخدمين) بعقود واضحة وجلسات عديمة الحالة ومصادقة على مستوى المؤسسات، دون المساس بسرعة التطوير.
إليك ما نركز عليه: سنستعرض معمارية MCP العامة، ثم نتعمق في المصادقة وتكاملنا مع Azure AD B2C، وهو الجانب الأكثر تعقيدًا والأكثر أهمية حين تتعامل الأدوات مع بيانات خاصة بالمستخدم. إذا أردت التخطي إلى الأمام، انظر قسم تدفق المصادقة (Sequence) ونقاط نهاية OAuth Proxy وتعيينها على Azure AD B2C.
رحلة المستخدم
- يفتح المستخدم عميل MCP مدعومًا (مثل Claude.ai أو ChatGPT أو طرفية Claude Code مخصصة) ويتصل بخادم MCP الخاص بنا.
- يُوجَّه العميل عبر OAuth gateway الذي يعمل كوسيط لـ Azure AD B2C لتسجيل الدخول.
- عند النجاح، يُصدر MCP gateway رمز وصول موقَّعًا ويُدرج user_id في سياق الطلب.
- بعد المصادقة، يسرد العميل الأدوات المتاحة وسكيمات المدخلات الخاصة بها.
الأدوات العامة تشمل:
- Get_Addresses_for_Postcode
- Analyze_Property_Location
- Get_Property_Energy_Label
- Get_Property_Data
- Quick_Assess_Property
- Get_Assessed_Properties
- Get_Property_Assessments
- عند استدعاء الأداة من عميل MCP بتوجيه من LLM، تعمل الأداة من جانب الخادم، وتستعلم من تكامل Kadaster والخدمات الأخرى، وتُعيد مخرجات JSON منظمة.
- يعرض العميل النتائج في المحادثة، ويمكنه ربطها بأدوات أخرى عند الحاجة.
يُبقي هذا التصميم تجربة LLM بسيطة مع تطبيق قواعد الوصول إلى البيانات وإنتاج مخرجات متسقة وصديقة للأدوات.
معمارية الحل
نظرة عامة
نظرة عامة على معمارية MCP Gateway
المكونات التقنية الفعلية
- تطبيق ASGI (Starlette + Uvicorn) مع نواة خادم MCP.
- StreamableHTTPSessionManager في الوضع عديم الحالة لتقديم MCP عبر HTTP.
- نقاط نهاية OAuth تُقدَّم من نفس التطبيق:
/.well-known/oauth-authorization-serverو/oauth/authorizeو/oauth/tokenو/oauth/callbackو/oauth/jwks، بالإضافة إلى.well-known/oauth-protected-resourceلاكتشاف الموارد. - عقود الأدوات مُعرَّفة مركزيًا في ملف
all_tools_schema.jsonومسجَّلة ديناميكيًا عبرlist_tools(). - تُوزّع
call_tool()حسب الاسم إلى تطبيقات مُحكمة النوع وتستدعي الأداة المقابلة.
المصادقة: OAuth Gateway يعمل كوسيط لـ Azure AD B2C
إذا سبق لك العمل مع Azure AD B2C، فأنت تعرف أن إدارة redirect URI يمكن أن تُبطئك. احتجنا إلى تأهيل ديناميكي للعملاء وعدم تغيير البوابة عند الاختبار مع عملاء MCP جدد. لهذا السبب طبّقنا نمط الـ gateway.
- نعرض بيانات تعريف الموارد المحمية على
/.well-known/oauth-protected-resourceليتمكن العملاء من اكتشاف النطاقات وخوادم التفويض. - ندعم نقطة نهاية DCR (Dynamic Client Registration) بسيطة تُعيد بيانات اعتماد العميل الثابتة لتبسيط التطوير.
- في Azure AD B2C، نسجّل رابط callback واحدًا يُعيد التوجيه إلى خادم مصادقة MCP بعد نجاح المصادقة.
- في نقطة نهاية الـ callback، نُشفّر redirect URI الأصلي للعميل (والسياق) في OAuth
state. - عند الـ callback، نتبادل الكود مع B2C، ونستخرج هوية المستخدم، ثم نُصدر رمز الوصول الخاص بنا (JWT) مرتبطًا بـ audience لعنوان URL لمورد MCP.
يحافظ هذا على نقاط قوة Azure AD B2C (المصادقة والسياسات) مع منحنا المرونة لتأهيل عملاء MCP جدد فورًا.
لماذا Gateway: التطور والمبررات
قصة موجزة عن سبب وضعنا وسيطًا أمام Azure AD B2C.
المقاربة الأولية: تكامل مباشر مع Azure AD B2C
- نقاط نهاية OAuth (authorize, token, callback, JWKS) تُشير مباشرةً إلى Azure AD B2C.
- تُسجَّل العملاء في Azure AD B2C بـ redirect URIs ثابتة.
- يعمل خادم MCP فقط كخادم موارد، يتحقق من الرموز الصادرة عن Azure عبر JWKS الخاص بـ Azure.
المزايا
- أمان قوي وامتثال للمعايير من البداية.
- تتولى Azure إدارة طبقة الهوية وتوسيعها.
العيوب
- إدارة redirect URI لكل عميل/بيئة أبطأتنا.
- التأهيل الديناميكي للعملاء والتدفقات المخصصة كانت محرجة أو استلزمت تغييرات في البوابة.
المشكلة: صرامة redirect URI
احتياجات العمل:
- تأهيل عملاء وبيئات جديدة بسرعة، كثيرًا ما تكون بـ redirect URIs فريدة.
- دعم سيناريوهات متعددة المستأجرين والنماذج الأولية السريعة دون إرهاق البوابة.
التحدي التقني:
- يتحقق Azure AD B2C بصرامة من redirect URIs؛ أي شيء غير مسجّل مسبقًا يُرفض.
الحل: OAuth proxy/gateway
- يعرض MCP gateway سطح OAuth للعملاء ويعمل كوسيط لـ Azure AD B2C باستخدام callback واحد مسجّل مسبقًا.
- نُشفّر redirect URI الأصلي للعميل والسياق في OAuth state.
- عند الـ callback، نتبادل الكود مع Azure، ونستخرج معلومات المستخدم، ثم نُصدر رموز الوصول الخاصة بنا لمورد MCP.
- نستضيف نقطة نهاية JWKS (انتقل إلى المفاتيح غير المتماثلة للإنتاج) للتحقق من الرموز.
لماذا التغيير؟
- فضّلنا التكامل المباشر مع Azure للبساطة، لكن متطلبات العمل وتعدد المستأجرين استلزمت المرونة.
- نمط الـ gateway كان الطريقة العملية للحفاظ على Azure AD B2C للمصادقة مع منح MCP المرونة للتطور.
نقاط نهاية OAuth Proxy وتعيينها على Azure AD B2C
فكّر في هذه النقاط باعتبارها "الباب الأمامي" الذي يعرضه MCP gateway لأي عميل قادر على OAuth. تُمكّن معًا من ثلاث لحظات: الاكتشاف وتسجيل دخول المستخدم وإصدار الرمز (بالإضافة إلى اكتشاف المفاتيح للتحقق). فيما يلي نصف كل نقطة نهاية بلغة بسيطة، ثم نُظهر كيف تتوافق مع Azure AD B2C كمزود هوية.
1) GET /.well-known/oauth-protected-resource
- ما هي: وثيقة بيانات تعريف الموارد (RFC 9728) تخبر العملاء بالـ "resource" الذي يحاولون الوصول إليه، وأي خوادم تفويض يمكنها إصدار رموز له، وما هي النطاقات الموجودة.
- لماذا تهم: تتيح لعميل MCP اكتشاف آلية الأمان دون ترميز النقاط الثابتة. يمكن للعميل معرفة "من يمكنه منحي رمزًا لهذا الخادم وما النطاقات المتاحة؟"
- الحقول النموذجية: معرّف المورد (URL)، قائمة خوادم التفويض، رابط مستندات اختياري والنطاقات.
- في gateway الخاص بنا: المورد هو عنوان URL الأساسي لخادم MCP؛ قائمة خوادم التفويض تحتوي على issuer الـ gateway العام. تعكس النطاقات قدرات الأدوات الواسعة.
2) GET /.well-known/oauth-authorization-server
- ما هي: اكتشاف OAuth/OIDC القياسي (فهرس قابل للقراءة آليًا لنقاط نهاية المصادقة والميزات).
- لماذا تهم: تتعلم العملاء برمجيًا أين يرسلون المتصفح للتفويض، وأين يُرسلون POST لتبادل الكود، وطرق code challenge (PKCE) المدعومة، وأين تُجلب مفاتيح التوقيع (JWKS).
- في gateway الخاص بنا: الـ issuer هو نطاقنا العام؛ نقاط نهاية التفويض والرمز هي
/oauth/authorizeو/oauth/tokenالخاصة بالـ gateway؛ JWKS URI يُشير إلى/oauth/jwksالخاص بنا.
تدفق المصادقة (Sequence)
تسلسل مصادقة MCP OAuth
فيما يلي التسلسل الدقيق الذي يتبعه النظام عندما يحتاج عميل MCP للوصول إلى الأدوات المحمية:
- يكتشف العميل نقاط نهاية OAuth
- يقرأ عميل MCP
/.well-known/oauth-protected-resourceعلى MCP gateway لاكتشاف النطاقات المدعومة وخادم التفويض. - يقرأ أيضًا
/.well-known/oauth-authorization-serverللتعرف على authorization_endpoint ونقطة نهاية الرمز وjwks_uri.
- يقرأ عميل MCP
- طلب التفويض (وسيط لـ Azure AD B2C)
- يستدعي العميل
/oauth/authorizeفي MCP gateway مع:client_idوredirect_uri(الخاص بالعميل) وstateوcode_challengeالاختياري وscope. - يُشفّر الـ gateway حالة JSON تحتوي على
stateوredirect_uriوclient_idوscopeوcode_challenge. - يُعيد الـ gateway توجيه المتصفح إلى نقطة نهاية
authorizeفي Azure AD B2C، باستخدامredirect_uriواحد مسجَّل مسبقًا يُشير إلى MCP gateway.
- يستدعي العميل
- يُصادق المستخدم مع Azure AD B2C
- يُكمل المستخدم تسجيل الدخول والسياسات على Azure AD B2C.
- يستدعي Azure AD B2C MCP gateway على
/oauth/callback?code=...&state=.... - يفكّ الـ gateway تشفير الحالة، ويتبادل
codeمع نقطة نهاية رمز Azure للحصول على الرموز (بما فيهاid_token). - يستخرج الـ gateway
sub(subject) للمستخدم منid_token، يخزّن كود تفويض وسيط للعميل الأصلي، ويُعيد توجيه المتصفح إلىredirect_uriالأصلي للعميل مع?code=...&state=....
- يتبادل العميل الكود مع MCP gateway
- يستدعي عميل MCP
/oauth/tokenفي الـ gateway معgrant_type=authorization_codeوالكود المُستلَم وclient_idوcode_verifierالاختياري. - يتحقق الـ gateway من الكود (وPKCE إن وُجد)، يُعلّمه مستخدَمًا، ويُصدر رمز وصول MCP عبر
create_access_token(). يتضمن الرمز:aud=MCP_SERVER_URL(مرتبط بالـ audience)scp= مصفوفة النطاقاتsub= subject المستخدم (إن وُجد) أو معرّف العميل (client credentials)
- يستدعي عميل MCP
- استدعاء أدوات MCP المحمية
- يرسل العميل الطلبات مع
Authorization: Bearer <access_token>إلى جذر خادم MCP حيث تُركَّب نقاط نهاية MCP. - تتحقق برمجية التفويض الوسيطة من الرمز (الـ issuer والـ audience)، وتُدرج
user_idفي نطاق ASGI، وتُعيّنcurrent_user_idفيcontextvars.ContextVarلوظائف الأدوات التالية. - تقرأ وظائف الأدوات مثل
Get_Assessed_PropertiesوGet_Property_Assessmentsمعرّف المستخدم الحالي عبرget_current_user_id()وتُطبّق وصول البيانات لكل مستخدم.
- يرسل العميل الطلبات مع
تفاصيل Azure AD B2C التي يجب تهيئتها:
- تسجيل التطبيق مع
AZURE_B2C_CLIENT_IDوالسر؛ اضبطAZURE_B2C_REDIRECT_URIعلى عنوان URL لـ callback الوسيط. - اسم تدفق/سياسة المستخدم (
AZURE_B2C_POLICY) المستخدم في نقاط نهاية authorize/token. - تأكد من أن نطاق الوسيط (OAUTH_DOMAIN) قابل للوصول ومتسق (يُستخدم كـ
issفي رموز MCP ومدرج في البيانات التعريفية).
الخلاصة
جعل MCP الأمر بسيطًا لعرض قدراتنا في النطاق العقاري بطريقة يستطيع LLMs فهمها وتنسيقها. مع OAuth gateway أمام Azure AD B2C، نستوفي متطلبات الأمان على مستوى المؤسسات دون إعاقة سرعة المطوّرين. النتيجة هي مسار سريع وآمن وقابل للتوسع نحو سير عمل وكيل جاهز للإنتاج.