Skip to main content

تطبيقات connector-native: خادم MCP بعيد عميله ذكاء اصطناعي

14 مفهوماً · قراءة من 90 إلى 120 دقيقة تقريباً · يوم مركّز للبناء (4-6 ساعات إن كنت مطوّراً قوياً) · من قاعدة صغيرة إلى connector حي يمكن لأي ذكاء اصطناعي التقاطه واستخدامه مجاناً

طوال ثلاثين عاماً بنينا البرمجيات للبشر. شاشات ينظرون إليها، وأزرار يضغطونها، ونماذج يملؤونها. كان العميل خلف الزجاج دائماً إنساناً.

لم يعد ذلك هو العميل الوحيد في الغرفة. في هذه الدورة تبني منتجاً مستخدمه ذكاء اصطناعي.

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

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

ستبني منتجاً حقيقياً واحداً من البداية إلى النهاية:

  • خادم MCP بعيد: تلك المنضدة الأمامية، موضوعة عند عنوان ويب عام (وهذا معنى "بعيد") حتى يصل إليها أي ذكاء اصطناعي على الإنترنت. يحتوي خادمك على ثلاث مجموعات أدوات.
  • ذاكرة من جدولين، أي قائمتان صغيرتان يحتفظ بهما تطبيقك، حتى يتذكر الذكاء الاصطناعي الشخص من محادثة إلى التالية بدلاً من أن يبدأ فارغاً كل مرة.
  • تسجيل دخول حقيقي (OAuth)، حتى يعرف خادمك بيانات من يحمل من تسجيل الدخول نفسه، دون أن يطلب من الذكاء الاصطناعي أن يضمن ذلك.
  • عقد جلسة: أداة واحدة يستدعيها الذكاء الاصطناعي أولاً، تعطيه قواعد تطبيقك، ثم تقفل كل أداة أخرى خلف مفتاح لا يصدره إلا ذلك الاستدعاء الأول.
  • كل ذلك يضاف برابط واحد ملصوق ونقرة واحدة، ويعمل على النموذج المجاني الخاص بالشخص، فلا يكلّفك خدمته شيئاً.

تشحن كل هذا قبل أن تكتب حلقة وكيل واحدة. هذه هي فائدة وضعه أولاً: تتعلم بناء الشيء الذي يستدعيه الوكيل قبل أن تبني الوكيل نفسه.

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

يبقى أربعة أمور غير قابلة للتفاوض. الدورة كلها تبنيها:

  1. بوابة واحدة. يلتقي الذكاء الاصطناعي بك عند connector واحد، وخلفه أدوات مجمّعة بالاسم: باب أمامي واحد، وقائمة واحدة يقرأها. (الحساب المجاني يستطيع إضافة connector مخصص واحد فقط، لذلك «واحد» حدّ قاسٍ لا تفضيل.)
  2. أدوات فقط. تتحدث إلى الذكاء الاصطناعي عبر أدوات قابلة للاستدعاء، أي دوال يستدعيها وسط استدلاله، لا عبر resources أو prompts يحتاج إنسان إلى اختيارها باليد.
  3. أثبت ولا تثق. عميلك عقل قد يعطيك هوية الشخص الخطأ بلا نية ضرر. لذلك تأتي الهوية من تسجيل دخول موثّق، لا من شيء يخبرك به الذكاء الاصطناعي، كما يسلّمك مكتب الفندق بريدك بناءً على جواز السفر الذي عرضته عند الدخول، لا بناءً على كلام شخص عن الغرفة التي تخصه.
  4. افشل مغلقاً. عندما يكون خادمك غائباً أو معطلاً، لا يسكت الذكاء الاصطناعي. بل يرتجل، فيخترع إجابة ويختلق بيانات الشخص المحفوظة. على خادمك أن يجعله يتوقف ويقول ذلك، كما يعرض الصرّاف الآلي الذي لا يصل إلى البنك عبارة غير متاح مؤقتاً بدلاً من تخمين رصيدك وصرف المال.

الثوابت الأربعة لتطبيق connector-native: اثنان يصفان شكل التطبيق، بوابة واحدة وأدوات فقط، واثنان هما مهمتان يجب أن يؤديهما الخادم لأن الذكاء الاصطناعي لا يؤتمن عليهما: إثبات الهوية من تسجيل دخول موثّق، والفشل المغلق بدلاً من الارتجال. اقرأ كل مفهوم بوصفه الخادم وهو يثبت واحداً من هذه الأربعة.

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

note

المتطلبات السابقة. تفترض هذه الصفحة أربعة أشياء.

  1. تستطيع قراءة Python مكتوباً بأنواع، مباشرةً أو بلصق مقطع كود لوكيل البرمجة لديك ليشرحه بلغة واضحة. إن لم يكن أي منهما صحيحاً بعد، فابدأ ب Python في عصر الذكاء الاصطناعي.
  2. أنجزت الدورة المكثفة في البرمجة الوكيلة. أنت تقود Claude Code أو OpenCode في نمط التخطيط مع ملف قواعد. هنا نبني من خلال ذلك المنضد بدلاً من إعادة شرحه.
  3. استخدمت connector من الخارج، في دورة المهارات والموصلات. فعّلت واحداً وشاهدت ذكاءك الاصطناعي يصل إلى Drive لديك. هذه الدورة تقلبك إلى الداخل: الآن أنت الشيء الذي يصل إليه الذكاء الاصطناعي.
  4. لا تحتاج إلى Build AI Agents أولاً. ما تبنيه هنا هو الخادم الذي يستدعيه وكيل، لا الوكيل نفسه. تلك الدورة تأتي لاحقاً في المسار، وهذه الدورة هي السبب الذي سيجعلك تريدها.

لا تحتاج إلى مفتاح API خاص بك: الشخص يأتي بالنموذج. الحسابات التي تحتاجها كلها بطبقة مجانية ولا تُفتح إلا عند الحاجة: قاعدة بيانات Neon عندما تخزّن الحالة أول مرة (المفهوم 5، بلا بطاقة). ثم يشغّل المفهوم 12 connector لديك حياً في claude.ai عبر tunnel مجاني، بلا مضيف ولا بطاقة ولا حساب تسجيل دخول. نصف تسجيل الدخول يعمل على mock محلي مرفق طوال الطريق، لذلك لا تنشئ حساب تسجيل دخول لمجرد البناء أو الاختبار أو العرض التجريبي.

note

أين يقع هذا؟ أول دورة بناء في Mode 2. من هنا يسير مسار Manufacturing هكذا: هذه الدورة → Plugins for AI AgentsAI IdentityBuild AI Agents. هذا هو تطبيق ما قبل الحلقة: أدوات وحالة وهوية وتشغيل حي في claude.ai، مع نموذج المستدعي وهو يقوم بالتفكير. لاحقاً في المسار، Build AI Agents هو المكان الذي تملك فيه الحلقة.

📚 وسيلة تعليمية

افتح العرض التقديمي الكامل

شاهد العرض التقديمي الكامل — تطبيقات connector-native


كيف تبني في هذه الدورة

أنت لا تكتب هذا الخادم بيدك. مثل كل دورة في مسار Manufacturing، وكيل البرمجة لديك يكتب الكود؛ أما عملك فهو المواصفة الداخلة والتحقق الخارج. أنت تخطط، وتراجع، وتشغّل، وتفحص. هذه الحلقة ليست راحة هنا. إنها المفهوم 1.

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

جهّز القاعدة (بضع دقائق)

  1. نزّل القاعدة (connector-native-apps-base.zip)، وفك ضغطها، ثم انتقل إلى المجلد ب cd.
  2. افتح Claude Code أو OpenCode داخل ذلك المجلد. يحمّل AGENTS.md تلقائياً: brief يثبت وكيلك على الثوابت الأربعة ويخبره كيف يجهّز المشروع.

ما الموجود في الصندوق. هذه قاعدة صغيرة، لا تطبيق منتهياً. يشحن القلب الأمني الحرج وحده كاملاً، لأن الوكيل قد يكتب كود تفويض يبدو صحيحاً لكنه خاطئ بصمت؛ لذلك تقرأ ذلك الجزء ولا تولّده. كل شيء آخر تبنيه عبر الدورة.

connector-native-apps/
AGENTS.md the agent's brief: base prep, the four invariants, the build order
CLAUDE.md one line, @AGENTS.md, so Claude Code loads that same brief
.mcp.json opencode.json Neon + Context7 MCP servers, pre-declared (authorize once in browser)
pyproject.toml a uv project; only the deps the given code needs (your agent adds the rest)
.env.example copy to .env; the user brings the model, so no API key of your own
src/connector_app/
auth.py GIVEN, complete: the security check that proves who is signed in (you read it in Concept 7, never rewrite it)
session.py GIVEN, complete: the lock the rest of your tools sit behind (you wire it in Concept 10)
mock_auth/server.py GIVEN: a local sign-in service, so you can test the whole flow without creating any account
seed/articles.json a tiny catalog for your domain
tests/test_starter.py five offline smoke tests over the security core

الملفان الموسومان GIVEN، وهما auth.py وsession.py، تقرؤهما وتوصلهما ولا تعيد كتابتهما أبداً. أما الباقي، أي البوابة (server.py) ومخزن الجدولين (db.py) وقواعدك وشخصيتك (config_store.py)، فيبنيه وكيلك معك مفهوماً بعد مفهوم.

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

1. اعرف ما يعرفه (وهذا يفحص أيضاً أنه قرأ brief عند الفتح):

What can you do for me?

الإجابة الجيدة تصف هذا المشروع: تطبيق connector-native، وثوابته الأربعة، وكيف سيساعدك في بنائه مفهوماً بعد مفهوم. إذا أجاب بإجابة عامة من نوع "أنا مساعد برمجة"، فهذا يعني أنه لم يحمّل AGENTS.md؛ تأكد أنك فتحت الوكيل داخل مجلد القاعدة.

2. اضبط البيئة:

Set up my base environment for this project, and install anything that's missing, including Python and uv.

انتبه إلى: يؤكد الوكيل أنك على Python 3.14+ وuv، ويثبت أيهما إن كان ناقصاً، ويثبت dependencies ومهارتي mcp-builder وneon-postgres، وينشئ .env مع SESSION_SIGNING_SECRET مولّد. Context7 بلا مفاتيح ويتصل وحده؛ أما Neon فيشغّل /mcp ويطلب منك نقرة Authorize واحدة في المتصفح (مجاني في neon.com، بلا مفتاح API ولا بطاقة؛ أنشئ الحساب من تلك الشاشة إن احتجت). ثم يطلب منك إعادة تشغيله حتى تتحمل المهارات الجديدة، ويؤكد بعد عودته أنه يرى أدوات Neon.

3. افهمه، وافحص أنه سليم (بعد إعادة التشغيل):

Explain this project to me before I continue the crash course, then run its tests and share their status.

تم عندما: يشرح لك الوكيل القاعدة بلغة واضحة، وتنجح اختبارات القلب الأمني الخمسة، وتظهر أدوات Neon بعد إعادة التشغيل، ويكون ملف .env موجوداً. إن لم تظهر أدوات Neon، فلم يتم التفويض بعد: أعد نقرة التفويض في المتصفح، أو اكتب /mcp واختر Neon. الآن تبني.

note

مساران، تختار أحدهما. يستخدم مسار المبتدئ خدمة mock_auth/ المرفقة: تسجيل دخول محلي يصدر tokens حقيقية، لذلك لا يحتاج نصف تسجيل الدخول إلى أي حساب إطلاقاً (ما زالت بياناتك المحفوظة تعيش في قاعدة Neon مجانية). أما المسار القياسي فيستبدلها بخدمة تسجيل دخول حقيقية مستضافة، وهو طريق الإنتاج الذي توصله في دورة AI Identity. ابنِ كل شيء على مسار المبتدئ أولاً، ثم بدّل بتغيير ثلاث قيم في .env. لا تختار الخدمة الآن؛ المفهوم 8 يسمّي الخيارات عندما يصبح الاختيار مهماً فعلاً.


Part 1: الشكل

هذه المفاهيم الأربعة هي النموذج الذهني الذي تبني عليه بقية الصفحة. الثلاثة الأولى للقراءة فقط؛ في المفهوم 4 تخطط البناء كله وتضع هيكل البوابة.

المفهوم 1: أنت توجّهه، ولا تكتب بيدك

لن تكتب هذا الخادم بيدك. ستخبر وكيل برمجة بما تريد، فيكتب الكود، ويكون عملك أن تقرأه وتشغله وتفحصه. إن أتيت من Python in the AI Era فأنت تعرف الإيقاع: أنت توجّه، والوكيل يكتب، وأنت تتحقق.

الفحص هو المهارة الحقيقية، وموضع واحد يحتاجها أكثر من غيره: كود تسجيل الدخول في المفهوم 8. سيكتب الوكيل كود تسجيل دخول يبدو صحيحاً لكنه خاطئ بصمت، وتعلّم رؤية الفرق هو بالضبط ما تبنيه هذه الدورة فيك. ضغطات المفاتيح عمل الوكيل؛ والحكم عملك أنت.

هناك التفاتة واحدة تستحق أن تحملها معك، لأن هذه الدورة هي الوحيدة التي ترى فيها نوعي البرامج في الوقت نفسه. تخيّل مكنستين. المكنسة الروبوتية تعمل وحدها: تستيقظ، وتتجول في البيت، وتقرر كل حركة، ويمكنك حتى ضبطها لتنظف في 2 صباحاً. المكنسة اليدوية لا تعمل إلا ما دمت تضغط الزناد؛ اتركه فتتوقف. وكيل البرمجة الذي يبني هذا لك هو المكنسة الروبوتية: يستمر من تلقاء نفسه. والconnector الذي تبنيه هو المكنسة اليدوية: يبقى ساكناً حتى يمد المستخدم يده. لهذه القدرة على العمل الذاتي اسم تعود إليه الدورة مراراً، امتلاك الحلقة: المكنسة الروبوتية تملك حلقتها، وconnector لديك لا يملكها أبداً. أنت تقود برنامجاً يملك الحلقة ليبني تطبيقاً لا يملكها.

شكلان للتطبيق، يفصل بينهما سؤال واحد: هل تملك الحلقة؟ في اليسار تطبيق connector-native السابق للحلقة الذي تبنيه هذه الدورة: تشحن خادماً، أدوات وحالة وهوية ونشر، ويأتي تطبيق المحادثة المضيف بالنموذج والحلقة، لذلك لا يعمل إلا عندما يكتب المستخدم. في اليمين وكيل يملك الحلقة تبنيه دورة لاحقة، Build AI Agents: تكتب الحلقة بنفسك فيستيقظ ويخطط ويستدعي الأدوات وينهي عملاً وحده. الالتفاتة: أنت توجّه وكيل برمجة يملك حلقة ليبني التطبيق عديم الحلقة في اليسار.

المفهوم 2: شكل التطبيق الجديد

استخدمت connector من الخارج، كشخص يصل إلى تطبيقاته. الآن اقلبه: أنت الخادم، والمستدعي هو الذكاء الاصطناعي. يتصل Claude بك من سحابته. تنشأ عن ذلك ثلاث حقائق، وهي التي تقود كل قرار لاحق.

تطبيق المحادثة هو runtime، أي المحرك الذي يشغّل كل شيء فعلياً، وهو يعيش في السحابة. عندما يضيف مستخدم connector لديك، يصل Claude إلى خادمك من سحابة Anthropic، لا من حاسوب المستخدم المحمول. لذلك يجب أن يكون خادمك على الإنترنت العام عبر HTTPS، أي بروتوكول الويب الآمن. يصل Claude إليك من بعيد، ولذلك يجب أن تكون منضدتك على شارع عام بعنوان حقيقي: عنوان ويب عام. الخادم على حاسوبك المحمول هو المنضدة نفسها لكن داخل بيت مقفل، حقيقية تماماً لكن بلا باب إلى الشارع، فلا يستطيع أحد خارج البيت الوصول إليها. لهذا يضعها Part 5 على الإنترنت العام عبر tunnel سريع، لا كفكرة لاحقة.

المستخدم يأتي بالنموذج. أنت لا تدفع ثمن الذكاء؛ طبقة Claude المجانية لدى المستخدم توفره. تكاليفك الوحيدة خادم صغير وقاعدة بيانات. تلك هي الحيلة الاقتصادية كلها وراء «مجاني لأي شخص».

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

تدفق من اليسار إلى اليمين: المستخدم يكتب في Claude؛ وClaude، النموذج والحلقة، يعمل في سحابة Anthropic؛ وحدّ ثقة متقطع يبيّن أين يعبر رابط connector إلى بوابتك عبر HTTPS العام؛ وتحول بوابتك token إلى sub وتقرأ الحالة من Postgres. ملاحظتان: الحلقة تعيش في Claude لا في خادمك؛ والهوية تأتي من sub في token، لا من النموذج أبداً.

المفهوم 3: أدوات فقط، لا resources ولا prompts

يمكن لخادم MCP أن يقدّم للنموذج ثلاثة أشياء: أدوات، وهي دوال يستدعيها النموذج بمدخلات ومخرجات؛ وresources، وهي بيانات للقراءة فقط يشير إليها المستخدم؛ وprompts، وهي قوالب جاهزة يختارها المستخدم. كلها أسطح MCP صحيحة. لكن لشكل المنتج في هذه الدورة نعرض عمداً الأدوات فقط. هذا قرار تصميم لهذا النوع من التطبيقات، لا قاعدة تقول إن resources وprompts خطأ عموماً.

لماذا تلائم الأدوات هذا الشكل؟ لأن تطبيقك يجب أن يقرر بنفسه ماذا يجلب أو يفعل بعد ذلك: يبحث، يسحب سجلاً، يحفظ نتيجة. تخيّل ورشة. الأداة هي المثقاب اللاسلكي في حزام العامل: يلتقطه وسط العمل بلا سؤال. أما resource فهو دليل مقفل في خزانة، لا يفيد حتى يمشي شخص ويسلّمه. وprompt نموذج يجب على العامل أن يتوقف ليختاره من الرف. وحده المثقاب يبقي العمل جارياً بلا إنسان داخل الحلقة، ولذلك هذا التطبيق tools-only: وحدها الأداة يمكن استدعاؤها آلياً داخل استدلال النموذج، بينما resources خاملة والمستخدم يجب أن يشير إليها، وprompts يجب أن تُختار باليد. كما أن الأدوات هي السطح الذي تدعمه كل تطبيقات المحادثة جيداً، فيبقيك البناء عليها قابلاً للنقل.

سطح MCPمن يفعّلههل يمكن استدعاؤه آلياً وسط الاستدلال؟هل نستخدمه هنا؟
Toolالنموذج من تلقاء نفسهنعمنعم، كل شيء
Resourceالمستخدم يشير إليهلالا
Promptالمستخدم يختارهلالا

المفهوم 4: بوابة واحدة، وثلاث مجموعات خلفها (خططها، ثم ضع هيكلها)

هذا المفهوم يحدد شكل كل ما ستبنيه، لذلك يستحق أن تبطئ قليلاً. ابدأ بالفوضى التي يمنعها.

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

لتطبيق connector-native دائماً أنواع العمل الثلاثة نفسها، وستراها كلها تخرج من Reading Room الذي ستبنيه:

  • domain_* هو ما يفعله التطبيق فعلاً. في Reading Room هذا يعني الكتب: البحث في المجموعة وجلب مقال. هذا سبب وجود التطبيق. وجّه التطبيق لاحقاً إلى موضوعك الخاص وهذا هو الجزء الذي يتغير: طلبات متجر أو تذاكر دعم.
  • user_* هو من الموجود هنا، وما الذي تتذكره عنه. بطاقة مكتبة القارئ والرف الذي حفظه في الزيارة السابقة. هذا ما يمنع التطبيق من أن يكون سمكة ذهبية تنساك لحظة تغادر.
  • config_* هو كيف يجب أن يتصرف التطبيق. قواعد أمينة المكتبة وصوتها: ما الذي ستفعله أو لن تفعله، وكيف تتحدث. شخصية تعليمية نوع من config؛ وسياسة نبرة وتصعيد لمساعد دعم نوع آخر. معظم التطبيقات تحتاج بعض القواعد، وقليل منها يحتاج شخصية كاملة.

إذن domain هو العمل، وuser هو الشخص، وconfig هو السلوك: ثلاثة أسئلة مختلفة، وثلاث مجموعات. السابقة _ في كل اسم (domain_search وuser_save_state) تجعل هذا التقسيم مرئياً، فتقرأ قائمة الذكاء الاصطناعي كأقسام واضحة بدلاً من قائمة طويلة واحدة. لا يسمح اسم الأداة إلا بالحروف والأرقام و_ و-، ولا يسمح بالنقطة، لذلك السابقة بشرطة سفلية هي مساحة الاسم.

لماذا خادم واحد إذاً، لا ثلاثة؟ الطريقة المدرسية لشحن ثلاثة اهتمامات منفصلة هي ثلاثة خوادم منفصلة. لا تستطيع ذلك هنا (الثابت 1): في خطة Claude Free يستطيع المستخدم إضافة connector مخصص واحد بالضبط. اطلب من مبتدئ إضافة ثلاثة، وقد دفعته بصمت من منتج مجاني إلى خطة مدفوعة. لذلك تُبقي المجموعات الثلاث داخل خادم واحد، خلف رابط واحد: بوابة واحدة. باب أمامي واحد، وقائمة واحدة فيها ثلاثة أقسام، كما يبقي المطعم الإفطار والغداء والعشاء في بطاقة واحدة بدلاً من أن يسلمك ثلاث بطاقات. الأسماء أدناه لك؛ هذا هو الشكل فقط:

domain_search      domain_get_item      domain_do_action
user_get_profile user_save_state
config_get_rules config_get_persona

كلمة ستراها في prompts القادمة: في إطار MCP الخاص ب Python، أي FastMCP، الأداة ليست إلا دالة مزيّنة. الدالة فعل مسمّى يؤدي عملاً واحداً؛ و_تزيينها_ يثبت عليها بطاقة اسم حتى تدرجها قائمة الذكاء الاصطناعي. وكيلك يكتب هذه؛ أنت تحتاج فقط إلى معرفة الكلمة.

Prompt 1: اجعل الوكيل يخطط لكل شيء قبل أي سطر كود. هذه أهم حركة في الدورة كلها، وليست كتابة كود. تطلب من الوكيل أن يعرض التصميم الكامل أولاً بالكلمات، حتى تفحصه على الثوابت الأربعة قبل أن يُبنى أي شيء. اكتشاف "الهوية تأتي من وسيط أداة" في خطة يكلف جملة واحدة؛ اكتشافه بعد وجود الكود يكلف ظهيرة كاملة.

ادخل plan mode (Shift+Tab في Claude Code، وTab في OpenCode) حتى يقترح الوكيل بدلاً من أن يبني، وانتقل إلى نموذج قوي حتى تكون الخطة حادة، ثم الصق:

I want to build the Reading Room connector on this base. Read AGENTS.md and use the mcp-builder skill for tool naming and schemas, then propose the architecture for me: the one gateway, the three tool groups (domain, user, config), how it remembers a person, and how it proves who is signed in. Show me the complete plan and the tool list before you write any code, and for each piece tell me which of the four invariants it serves and flag anything you are unsure about or that the base has not already decided.

ما يفعله هذا prompt: يسلّم الوكيل brief (AGENTS.md) ومهارة التسمية، ثم يطلب منه اقتراح البنية وقائمة الأدوات الكاملة، وتبرير كل قطعة بثابت من الثوابت، بلا كتابة أي كود. أنت لا تملي التصميم؛ أنت تطلب تصميماً قابلاً للمراجعة.

ثم اقرأ الخطة كمفتش (هذه المراجعة هي المهارة التي تعلمها الدورة). افحصها على الثوابت الأربعة:

  • بوابة واحدة، لا ثلاث؟
  • أدوات فقط، بلا resources أو prompts تحمل منطق التطبيق؟
  • الهوية من تسجيل الدخول الموثّق، لا من وسيط أداة أبداً؟
  • قاعدة fail-closed موجودة في config؟

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

Prompt 2: ضع الهيكل الفارغ، وأثبت أنه يقف. Scaffolding هو إقامة الهيكل العاري قبل الجدران الحقيقية: خادم واحد يعمل، وفيه ما يكفي لإثبات أن الشكل سليم. تبدأ شبه فارغ عمداً، بأداة health-check واحدة وplaceholder واحد، حتى إذا كانت التوصيلات خاطئة تكتشفها الآن على أداتين تافهتين، لا لاحقاً تحت منطق حقيقي.

عد إلى نموذج أرخص لهذه الخطوة الروتينية؛ التفكير حدث في الخطة. في prompt عبارة حاملة للمعنى: stateless streamable HTTP. Streamable HTTP هو شكل السلك الذي يصل به مضيف بعيد مثل Claude إلى خادمك؛ و_stateless_ تعني أن خادمك لا يحتفظ بذاكرة اتصال واحد، حتى يستطيع أي خادم من Anthropic التعامل مع أي استدعاء. هذا هو شكل الإنتاج، ووكيلك يضبطه هنا مرة واحدة. الصق:

Looks right. With the mcp-builder skill's guidance, scaffold the gateway: one FastMCP server on stateless streamable HTTP transport, with a health tool and a domain_get_item stub. Add whatever dependencies you need. Run it and show me a local client listing both tools, with no auth and no real data yet.

ما الذي ستراه، وما الذي تتحقق منه

خادم يعمل، وعميل صغير يتصل بخادمك ويسأل عن الأدوات التي يقدمها، فيعرض أداتين. أداة domain_get_item ما زالت stub، أي placeholder لا يعيد شيئاً حقيقياً بعد، وهذا صحيح: لا auth ولا بيانات حقيقية في هذه الخطوة. لقد أثبت الحقيقة الوحيدة التي يدور حولها هذا المفهوم: خادم واحد، وأدوات مجمّعة بالاسم، على transport يستطيع مضيف بعيد الوصول إليه، ويمكن للعميل اكتشافه. الهوية والبوابة تأتيان لاحقاً؛ لا تضفهما الآن. إن كان port 8000 مستخدماً عندك، سيربط الوكيل port آخر ويحافظ على RESOURCE_URL متسقاً معه؛ هذا متوقع، لا خطأ.

Checkpoint: الشكل في مكانه. خططت connector كله، وراجعته على الثوابت، وأقمت بوابة واحدة على transport الصحيح. كل مفهوم لاحق يضيف قطعة حقيقية إلى هذا الخادم.


Part 2: الحالة والمجال

المفهوم 5: الحالة، بما يكفي لتذكّر شخص

ينساك chatbot عام عندما تغلق التبويب. لا يجوز أن يفعل تطبيقك ذلك؛ تذكّر المستخدم عبر الجلسات هو معظم ما يجعل التطبيق منتجاً لا لعبة.

أبقِ v1 صغيراً: قاعدة بيانات Postgres، وهي قاعدة علائقية قياسية تبدأ مجاناً، بجدولين. تخيّل سجلي مكتب الاستقبال، مربوطين برقم ولائك: سجل ضيوف يضم من يكون كل شخص، وسجل إقامة يضم ما يفعله مؤخراً. من أنت يتغير بالكاد؛ وما تفعله يتغير في كل زيارة، لذلك يعيشان منفصلين.

إليك الجدولين مكتوبين بلغة SQL، وهي اللغة القياسية لإنشاء قاعدة بيانات وقراءتها. لا تحتاج إلى قراءة SQL لتتبع الفكرة: مرّ بعينيك على التعليق الإنجليزي الواضح في كل سطر، فهو سبب عرضها كله. وكيلك يكتب هذا؛ أنت تراجعه فقط.

-- users: one row per person
create table users (
id text primary key, -- one person's verified sign-in id, the 'sub' (Concepts 7-8)
email text
);

-- user_state: one row per person, whatever you carry between sessions
create table user_state (
user_id text references users(id),
state jsonb -- a last position, a few saved values
);

الـ id الذي يربط الجدولين، أي "رقم الولاء" من صورة مكتب الاستقبال، هو في التطبيق الحقيقي id تسجيل الدخول الموثّق للشخص. اسمه في الكود sub، اختصاراً لكلمة subject، أي قطعة الهوية الوحيدة التي تستطيع الوثوق بها. لا تملك sign-ins حقيقية بعد، لذلك يشرح المفهومان 7 و8 من أين يأتي ذلك id فعلاً؛ الآن يكفي أن تعرف أن الجدولين مربوطان به.

هذه هي ذاكرة v1 كلها: خزّن صفاً، اقرأ صفاً. (jsonb عمود مرن واحد يحمل حزمة صغيرة من القيم المحفوظة كبيانات منظمة، بلا مجموعة أعمدة ثابتة تعلنها مسبقاً.) النسخة الجادة، سجل تدقيق لكل تفاعل ونموذج موافقة وسجل يمكنك الوثوق به والتقرير عنه، هي تخصصها الخاص، وهي بالضبط ما تعلّمه Building a Digital FTE. لا تبنِها هنا.

أنت لا تضبط قاعدة البيانات هذه أو تشغّلها بيدك. كما في كل دورة Manufacturing، يقود وكيل البرمجة Neon، أي Postgres مستضافاً لا تشغّله أو تصونه أنت، عبر خادم MCP الخاص بNeon: ينشئ المشروع، ويصنع branch، ويشغّل SQL بينما تراجع أنت. تبنيه في خطوتين قصيرتين، لكن يجب أن يصح شيء واحد أولاً.

تأكد أن Neon مستيقظ (10 ثوانٍ). كل ما يلي يعتمد على أن الوكيل يصل فعلاً إلى Neon، الذي وصلته أثناء setup. اسأله: "Can you see the Neon tools right now?" إن قال نعم، تابع. إن قال لا، لم يتم تفويض Neon: اكتب /mcp، واختر Neon، وانقر Authorize في المتصفح الذي يفتح (مجاني، بلا بطاقة)، ثم اسأل ثانية. لا تلصق prompt التالي حتى يؤكد الوكيل أنه يرى Neon، وإلا سيفشل لأنه لا يملك ما يعمل عليه.

Prompt 1: اجعل الوكيل ينشئ المخزن. الصق:

Using the Neon MCP server, create the two-table store (users, user_state) on a dev branch, and save the branch's DATABASE_URL to .env (never print it).

ما يفعله ذلك: يستخدم الوكيل MCP الخاص بNeon ليجهّز مشروعاً وbranch باسم dev، وهي نسخة sandbox خاصة من قاعدة البيانات حتى يبقى ما تفعله أثناء التعلم بعيداً عن البيانات الحقيقية، ثم ينشئ الجدولين اللذين قرأتهما للتو ويكتب عنوان قاعدة البيانات في ملف .env كـ DATABASE_URL حتى يجدها الكود. أنت تراجع؛ وهو يشغّل SQL.

تم عندما: تطلب من الوكيل أن يسرد الجدولين اللذين أنشأهما وأن يؤكد أن .env صار فيه سطر DATABASE_URL. إن أراك users وuser_state فالمخزن موجود. لا تفتح أداة قاعدة بيانات ولا تقرأ SQL بنفسك؛ الوكيل يريك.

Prompt 2: اجعل الوكيل يكتب كود القراءة والحفظ. اعرف شيئاً واحداً أولاً حتى لا يربكك: لا تملك sign-in حقيقياً بعد، فهذا يأتي في المفهومين 7 و8، لذلك في هذا الاختبار يستخدم الوكيل id بديلاً في المكان الذي سيأتي فيه sub الحقيقي لاحقاً. ما زال الكود مكتوباً على أساس sub؛ أنت فقط تطعمه placeholder حتى تصل الهوية الموثّقة. الصق:

Write db.py: read and save a user's state, keyed by the verified sub (never an id from a tool argument). Show me a value saving and reading back on a fresh connection. Then explain in one line why you keyed it on the verified sub and refused a tool-supplied id; we will see the full reason in the next part.

ما يفعله ذلك: يكتب الوكيل دالتين صغيرتين، save وread، تخزنان قيم الشخص المحفوظة تحت sub. ثم يثبت أن البيانات استمرت فعلاً بفتح اتصال جديد، أي رابط جديد تماماً بقاعدة البيانات، حتى تعرف أن القيمة محفوظة في Neon لا في ذاكرة العملية فقط، ويقرأ القيمة نفسها مرة أخرى.

تم عندما: تدور قيمة ذهاباً وإياباً. تحفظ شيئاً، وعلى اتصال جديد تقرأ الشيء نفسه بالضبط، keyed by stand-in id. هذه ذاكرة حقيقية: القيمة تعيش بعد الاتصال الذي كتبها. تعمل الحالة قبل أن تعمل الهوية.

المفهوم 6: المجال، بالمرجع الآن وبالمعنى لاحقاً

مجالك هو ببساطة الشيء الذي يدور حوله تطبيقك فعلاً: مقالاته أو عناصره أو سجلاته، لا عنوان ويب. عندما يريد المستخدم شيئاً محدداً، يجلبه v1 بالطريقة البسيطة: لكل سجل id، وتعيد domain_get_item(id) ذلك السجل. يعمل النموذج بما يعود.

ما لا يفعله v1 عمداً بعد هو البحث الدلالي: أن يجيب عن "الجزء المتعلق بالاسترداد" بالمعنى لا بال id الدقيق. الفرق مكتبة: الجلب بال id هو طلب كتاب برقم الرف الدقيق، ورقم واحد خطأ يعني لا شيء؛ أما البحث الدلالي فهو أن تقول لأمينة المكتبة "أريد كتاب الحوت الحزين" فتجده. v1 مكتب أرقام الرف؛ أمينة المكتبة هي الترقية، وهي موضوع دورة RAG كلها (Give Your AI Searchable Context). توصيله الآن سينفخ أول شحنة لك. ابنِ نسخة المرجع الآن:

Make domain_get_item(id) return a real article from seed/articles.json instead of the stub. Show me it returning a1 by id.

تم عندما: تعود مقالة بال id. اجلب بالمرجع الآن؛ وارفع إلى البحث لاحقاً.

اختياري: شاهد وكيلاً حقيقياً يستدعي أداتك

حتى الآن أثبتّ الخادم بسكربت صغير يعدد الأدوات. افعل هذا مرة واحدة مع ذلك، حتى تشعر بما صُمم connector من أجله فعلاً: وكيل يصل إلى أداتك ويستدعيها من تلقاء نفسه. أسرع طريقة لرؤية ذلك اليوم هي استعارة وكيل البرمجة نفسه الذي تبني به ليكون client مؤقتاً.

أبقِ الخادم يعمل (وكيلك شغّله لاختبار المفهوم 6؛ إن توقف فاطلب منه تشغيله مجدداً وتدوين الرابط الذي يطبعه، مثل http://localhost:8000/mcp). في terminal ثانٍ، وجّه وكيلك إلى ذلك الرابط:

claude mcp add --transport http reading-room http://localhost:8000/mcp --scope project

يكتب flag --scope project إدخال reading-room في ملف .mcp.json الخاص بالمشروع، إلى جانب Neon وcontext7؛ بدونه يهبط الخادم في scope آخر ولن يلتقطه وكيلك هنا. افحصه عبر claude mcp list؛ وأعد الاتصال وسط الجلسة عبر /mcp.

أضف إدخال reading-room إلى block mcp في opencode.json، إلى جانب إدخالي Neon وcontext7 الموجودين هناك، لا تستبدلهما:

"reading-room": {
"type": "remote",
"url": "http://localhost:8000/mcp",
"enabled": true
}

ثم اسأل في prompt عادي:

Use the reading-room domain_get_item tool to fetch article a1, and show me what came back.

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

ملاحظتان صادقتان حتى لا يضللك هذا:

  • هذه نظرة وقت التطوير، لا التسليم الحقيقي. عميلك الفعلي هو تطبيق المحادثة (claude.ai)، الذي توصله في المفهوم 13. هنا تستعير وكيل البرمجة بوصفه MCP client جاهزاً، لأنها أسرع طريقة لرؤية وكيل يقود أدواتك قبل وجود أي sign-in.
  • هذا يعمل فقط لأن auth غير موجود بعد. في المفهوم 8 تضيف القفل، ويبدأ الاستدعاء غير الموثّق بإعادة 401. لذلك أزل تسجيل التطوير هذا عندما تصل إلى المفهوم 8 (claude mcp remove reading-room يمسح إدخال .mcp.json؛ وفي OpenCode احذف block reading-room)، وإلا فسيبدأ بالفشل، وهذا هو عمل القفل.

Part 3: أثبت، هوية لا يستطيع النموذج تزييفها

هذا هو النصف الأول من "الخادم يفعل ما لا يستطيع النموذج فعله". يخدم المفهومان هنا الثابت 3.

المفهوم 7: الهوية من subject الموثّق، لا من النموذج أبداً

المشكلة هنا. يجب أن يكتب جدول user_state في صف الشخص الصحيح. لكن النموذج هو من يتحدث مع المستخدم، ويجب ألا تدع النموذج يقرر أبداً بيانات من يقرأ أو يكتب. تخيّل الذكاء الاصطناعي كconcierge في فندق ينجز مشاوير ضيف. عندما يقول للمنضدة الأمامية "الغرفة 412 تريد بريدها"، لا يجوز للمنضدة تسليمه بناءً على قوله: concierge مرتبك أو مخدوع قد يذكر غرفة خاطئة ويفضح بريد غريب. لو استطاع Claude أن يمرر لك user_id، فهذا هو الخطر نفسه، وسيرى مستخدم بيانات آخر. هذا هو bug الثقة المدرسي في تطبيق connector-native.

القاعدة: النموذج لا يزوّد الهوية أبداً. عندما فوّض المستخدم connector لديك، سجّل الدخول عبر خدمة موثوقة، وتلك الخدمة تعطي خادمك token موقّعاً يحمل id المستخدم الموثّق، أي subject أو sub. ذلك token هو جواز سفر الضيف: تقرأ المنضدة من الجواز نفسه من يكون، وهو ما لا يستطيع concierge تزويره، لا من أي شيء يقوله. يقرأ خادمك sub مباشرةً من token ويستخدم ذلك كمفتاح قاعدة البيانات. لذلك إن أخذت أداة ما وسيط user_id وملأه النموذج ب id شخص آخر، يتجاهله خادمك: الهوية تأتي من sub في token، لا من وسيط أداة.

هذه هي القاعدة التي يفرضها ملف given باسم auth.py، ولهذا يشحن كاملاً ولا تعيد كتابته أبداً. في سطر واحد: يأخذ id الموثّق (sub) مباشرة من token الموقّع ويسلّم ذلك إلى قاعدة بياناتك، فيكون الشخص الذي تلمس بياناته محدداً بتسجيل الدخول، لا بأي شيء كتبه النموذج. ستوصل هذا الملف في المفهوم التالي؛ هنا احمل القاعدة فقط. أفضل طريقة لترسيخها أن تجعل الوكيل يريكها في الكود الذي كتبته فعلاً.

اربطها بملف db.py لديك. الصق هذا:

Read auth.py back to me in plain English, then open the db.py you wrote in Concept 5 and show me where the sub comes from now. Tell me what would break if a tool argument could set it instead, and tie it back to the concierge and the passport.

الجزء الجميل: لا يكلّف المستخدم شيئاً إضافياً. نقرة Authorize الوحيدة التي تشغّل connector هي نفسها تسجيل الدخول. فعل واحد، مهمتان.

المفهوم 8: إثبات من هناك (تسجيل الدخول بلغة واضحة)

الآلة هنا هي OAuth، نفس "Sign in with Google" التي نقرت عليها مئة مرة. هذا هو المفهوم الذي تبطئ عنده، لا لأنه ضخم، بل لأن نمط الفشل مخادع: كود auth قد يبدو صحيحاً ويكون خاطئاً بصمت. الخبر الجيد أنك تحتاج إلى شيئين فقط: الأفكار وكيف تفحص النتيجة. وكيلك يكتب التوصيل الفعلي.

tip

الفكرة كلها في خمسة أسطر، والباقي في هذا المفهوم هو التفصيل تحتها. يسجل المستخدم الدخول في مكان آخر. تصدر تلك الخدمة token موقّعاً. يتحقق خادمك من token. يقرأ خادمك sub منه. لا يزوّد النموذج الهوية أبداً.

الأمر كله ينقسم إلى عملين، وأنت لا تفعل إلا واحداً منهما. تسجيل الناس عمل صعب ومسؤولية، لأنك ستحتفظ بكلمات مرور. لذلك لا تفعله: مختص خارجي يشغّل login ويعطي خادمك token، ورقة غير قابلة للعبث تقول: "هذا هو الشخص الذي سجّل الدخول الآن". عمل خادمك الوحيد هو فحص الورقة. بالتفصيل الكامل، هناك أربعة أطراف:

PartyWho it isYou build it?
The userThe person whose data it is
Claude's MCP clientRuns in Anthropic's cloud, asks on the user's behalfNo
The sign-in service (authorization server)An outside specialist — hosted (Clerk, Auth0, Stytch) or a framework you self-host (Better Auth) — that checks the login and issues tokensNo — you rent or self-host it
Your gateway (resource server)Your server; it only checks tokens and serves dataYes

بموجب مواصفة MCP الحالية، خادمك resource server فقط؛ ليس في عمل كلمات المرور إطلاقاً. أياً كان issuer الذي تختاره، مستأجراً أو ذاتياً، فأنت هنا تتحقق من tokens فقط؛ إصدارها هو دورة AI Identity. التدفق:

  1. Discovery. استدعاء أداة بلا token يحصل على 401، وهو رفض "لست مسجلاً الدخول" العام؛ يطلق تسجيل الدخول وليس خطأً تصلحه. يجد Claude ملاحظة خادمك العامة عند /.well-known/oauth-protected-resource، التي تقول "خدمة تسجيل الدخول لدي هناك"، ويتبعها إلى login.
  2. Sign-in. يرى المستخدم شاشة موافقة: "MyApp wants to read your saved items and remember your place"، ويسجل الدخول ب Google أو كود بريد، ويوافق. لا تلمس كلمة مرور Claude أو خادمك أبداً.
  3. Token. تصدر خدمة تسجيل الدخول token قصير العمر يحمل sub الموثّق و_audience_ مختومة لخادمك وحده.
  4. كل استدعاء بعد ذلك يحمل token؛ يفحصه خادمك ويقرأ sub.

تدفق OAuth كأربعة أطراف وأربع خطوات. الأطراف: المستخدم؛ وعميل Claude في سحابة Anthropic، وليس أنت؛ وخدمة تسجيل الدخول التي تستأجرها؛ وبوابتك التي تبنيها. الخطوة 1 discovery: استدعاء بلا token يحصل على 401 ويقرأ Claude مستند well-known ليجد خدمة تسجيل الدخول. الخطوة 2 sign-in: يسجل المستخدم الدخول ويوافق؛ لا تلمس كلمة مرور Claude أو خادمك. الخطوة 3 token: تصدر خدمة تسجيل الدخول token قصير العمر مع sub موثّق وaudience مختومة لخادمك. الخطوة 4، مميزة: كل استدعاء بعد ذلك، تفحص بوابتك التوقيع وال issuer وال audience والانتهاء، ثم تقرأ sub؛ وهذا هو الجزء الذي تتحقق منه.

ما يبنيه وكيلك هنا هو التوصيل، لا الفحص. فحص token نفسه يشحن كاملاً في auth.py، ولا تكتبه أبداً. ما يضيفه وكيلك هو الطبقة الرقيقة التي تضع ذلك الفحص على الباب: تجعل الاستدعاء بلا token يرتد كـ 401 وتوجه Claude إلى تسجيل الدخول. هذه الطبقة هي القطعة التي تتغير مع نسخة FastMCP، لذلك يبنيها وكيلك على الوثائق الحالية لا من الذاكرة.

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

The checkThe question it asksIf your server skipped it
Genuine?A real token signed by the issuer, not a forgery?Anyone could forge a token with any name and walk straight in.
Trusted issuer?Did it come from our sign-in service, not some other?A token from a service you never trusted would be accepted.
Stamped for us?Minted for this exact server, not a different app?The most dangerous one: a token meant for another app gets replayed against yours.
Still in date?Has it expired?A stolen token would keep working forever.

فوق هذه الأربعة قاعدة واحدة من المفهوم 7: تُقرأ الهوية من sub في token، لا من وسيط أداة أبداً. إن تخطيت تلك القاعدة قرأ شخص بيانات شخص آخر.

هذا الجدول هو قائمة التحقق كلها. لا تحتاج إلى قراءة أي cryptography لاستخدامه. تفحص السلوك، وهذا بالضبط ما يفعله promptان أدناه: token جيد يدخل، وtoken خاطئ يُرفض.

للفضوليين: تلك الأسئلة الأربعة ككود فعلي

هذا هو auth.py المعطى. لا تعدله أبداً؛ هو هنا فقط إن أردت رؤية الأسئلة الأربعة ككود. كل سطر معلق هو أحد الأسئلة أعلاه.

# auth.py — the token check (ships complete in the base)
from jose import jwt
from jose.exceptions import JWTError

def verified_claims(token: str) -> dict:
key = _key_for(token) # pick the matching public key (by the token's `kid`)
try:
claims = jwt.decode(
token,
key, # Genuine? signature checked against the issuer's public key
algorithms=["RS256"],
audience=RESOURCE_URL, # Stamped for us? must be THIS server (never omit)
issuer=AUTH_ISSUER, # Trusted issuer? must be the service we trust
options={"require": ["exp", "sub", "aud", "iss"]}, # Still in date? + require the facts we rely on
)
except JWTError as e:
raise AuthError(f"token rejected: {e}") from e
return claims # claims["sub"] is the user; nothing came from the model

بضع كلمات ستراها هناك: kid هو أي مفتاح توقيع استُخدم، وRS256 طريقة التوقيع، و**sub/aud/iss/exp** هي حقائق token: subject وaudience وissuer وexpiry، وهي الأربعة التي يتطلبها الفحص.

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

Prompt 1: ضع القفل على الباب. 401 جرس باب لا crash: يجب أن يُرفض استدعاء بلا token بالطريقة المحددة التي تقول لClaude "أرسل المستخدم إلى تسجيل الدخول". الصق:

Wire the OAuth layer around the given auth.py, and don't rewrite auth.py. Check the current FastMCP via Context7 first, then wire the JWTVerifier / RemoteAuthProvider and the /.well-known/oauth-protected-resource route so an unauthenticated tool call returns HTTP 401. Start the bundled mock_auth service (.env already points at it). Show me an unauthenticated call returning 401.

تم عندما: يعيد استدعاء بلا token 401، لا tool error ولا 200. هذا 401 هو ما يطلق تسجيل الدخول في Claude.

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

Mint a token from the mock and show me it resolves its sub through auth.verified_claims. Then, before you mint a token for a different audience, tell me which of the four checks should reject it. Mint it, show me it's rejected, and walk me through where each of auth.py's four checks runs.

تم عندما: يحل token جيد إلى sub، ويُرفض token بجمهور خاطئ، وتكون قد شاهدت كل فحص من الفحوص الأربعة يعمل.

ما الذي ستراه، وكيف تقرأ الإخفاقات

401 على استدعاء غير موثّق، وtoken يحل إلى sub حقيقي، وtoken بجمهور خاطئ يُرفض. أكد الفحوص الأربعة: التوقيع، وissuer، وaudience = خادمك، والانتهاء. فقدان audience هو أكثر المخرجات الخاطئة التي تبدو صحيحة شيوعاً. ثلاثة إخفاقات تستحق أن تميزها الآن:

  • لا يظهر prompt تسجيل الدخول، وستشعر بهذا عندما تضيفه إلى Claude في المفهوم 13: 401 أو route /.well-known مفقود، فلا تبدأ discovery. يجب أن يأتي 401 من طبقة auth، لا من أداة ترمي خطأً؛ فالtoken الذي يُفحص فقط داخل أداة يعيد 200.
  • Authorize يدور أو يخطئ: issuer أو audience في .env لا يطابق ما يحمله token.
  • تم تسجيل الدخول، لكن كل أداة تعيد 401: request accessor يقرأ header من المكان الخاطئ (get_http_headers() يزيل authorization؛ اقرأه من request object).

هذا هو المفهوم الذي تبطئ عنده.

أبقِ شيئاً واحداً واضحاً: لقد درّبت التدفق، ولم تصبح جزءاً منه. في مسار المبتدئ لعبت كل الأدوار حتى تثبت القفل بلا حسابات: mock_auth المرفق مثّل خدمة تسجيل الدخول، وأنت، عبر وكيلك، سككت tokens اختبارية وسلمتها. هذا مرّن مسار auth.py نفسه. لكنه قد يترك انطباعاً خاطئاً أن أنت أو وكيل البرمجة تسكّ tokens في الواقع. لا أنت تفعل ذلك ولا Claude. هذه هي الأدوار الفعلية:

StepOn your laptop now (rehearsal)In production (the real thing)
Who signs innobody; you stand inthe end user, at the Authorize click
Who mints the tokenthe local mock_auth, when you trigger ita real sign-in service (Clerk, Auth0, …)
Who carries it to your serveryour test scriptClaude's cloud, on every call
What your server does with itthe four checksthe same four checks, unchanged

بيت القصيد هو السطر الأخير: بوابتك وauth.py لا يتغيران بين العمودين. يفحصان tokens أي جهة بالأسئلة الأربعة نفسها. لذلك النسخة الحقيقية متعددة المستخدمين غالباً تبديل واحد: وجّه قيم AUTH_* / RESOURCE_URL إلى خدمة تسجيل دخول حقيقية بدلاً من mock، وهذا هو مسار AI Identity. منذ ذلك الحين يسكّ token تسجيل دخول المستخدم نفسه، لا أنت ولا وكيلك ولا Claude. أما Part 5 في هذه الدورة فيتجاوز حتى ذلك، فيطفئ auth لعرض شخصي سريع.

تفصيلان إنتاجيان يكملان الصورة، وفي مسار المبتدئ يضبطهما وكيلك وmock بشكل صحيح، فلا تضبطهما يدوياً الآن: PKCE، وهي مصافحة تمنع إعادة استخدام كود دخول مسروق، وطريقة حديثة لتسجيل clients. تصبح مسؤوليتك فقط عندما تشغّل خادم تسجيل دخولك الخاص، وهذا بالضبط ما تدرّسه دورة AI Identity بعمق. عندما تنشر على المسار القياسي، تتولى خدمة مستضافة حديثة مثل Clerk أو Auth0 أو Stytch ذلك عنك.

tip

تعمّق: هذه الدورة تتحقق من tokens؛ وAI Identity يصدرها. هنا بوابتك لا تفعل إلا التحقق من tokens، فهي resource server وتعتمد على خدمة تسجيل دخول يشغّلها غيرك. إقامة ذلك issuer بنفسك، أي خادم OAuth/OIDC لتسجيل الدخول، هي دورة AI Identity المخصصة، المبنية على Better Auth. وفي كلتا الحالتين لا تتغير بوابتك: تظل تتحقق من tokens بالطريقة نفسها مهما كان من يوقّعها.

Checkpoint: الخادم يعرف من هناك. تأتي الهوية من token لا من النموذج أبداً، والبيانات آمنة. والآن اجعل النموذج يتصرف.


Part 4: وجّه، اجعل النموذج يتصرف

هذا هو النصف الثاني من "الخادم يفعل ما لا يستطيع النموذج فعله". تخدم المفاهيم الثلاثة هنا الثابت 4 وسلوك تطبيقك.

المفهوم 9: أين تعيش قواعد التطبيق: Skill أم connector؟

هذا قرار حقيقي، لأن لقواعد تطبيقك بيتين: كيف يتصرف وصوته وحواجزه. والاختيار يحدد عدد الخطوات التي يقوم بها المستخدم قبل أول طلب. تخيّل مطعماً. Skill هو مفرش على الطاولة مطبوع عليه القواعد، أمام الزبون طوال الوجبة: لا ينجرف لأنه دائماً مرئي. أما connector فهو النادل الذي يخبرك بالقواعد عندما تجلس ويذكّرك بها عند كل طبق: يعمل، لكن عليك أن تعيد تسليمها. المفرش يفرض بشكل أقوى، لكن أنت يجب أن تضعه قبل الجلوس؛ النادل لا يحتاج منك شيئاً.

الخيار A، Skill مرفوع (SKILL.md). ملف يضيفه المستخدم؛ يُحمّل تلقائياً عندما يطابق الطلب، ويبقى جسمه في السياق، لذلك هو الأقوى في فرض "تصرف هكذا دائماً". الكلفة هي الإعداد. تعمل ميزة Skills في بيئة تنفيذ الكود لدى Claude، لذلك لا تعمل إلا مع code execution enabled، وذلك لأي Skill، حتى لو كان نثرياً فقط، لا تلك التي تحتوي سكربتات فحسب. لذلك على المستخدم أن يفعّل تنفيذ الكود، ويرفع ZIP، ويشغّل Skill، ثلاث خطوات فوق connector. وSkills المخصصة خاصة بالحساب الذي يرفعها، فلا طريقة نظيفة لتسليم Skill واحد لآلاف الغرباء في الطبقة المجانية؛ كل شخص يرفعه بنفسه.

الخيار B، داخل connector (الموصى به). تعاد القواعد و"من هذا المستخدم" من أداة session-init يستدعيها النموذج أولاً (المفهوم 10)، وتتعزز أثناء عمل الخادم. الفائدة حاسمة لجمهور عام في الطبقة المجانية: بلا Skill لا يوجد مفتاح تنفيذ كود ولا ZIP؛ ينهار الإعداد إلى إضافة connector واحد ونقرة Authorize واحدة.

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

Skill (SKILL.md)Connector (الموصى به)
قوة الفرضأقوى، لأنه دائماً في السياقألين قليلاً، ويخفف ذلك أدناه
خطوات الإعداد للمستخدمأربع: connector + code-exec + ZIP + toggleواحدة: connector
تسليمه لغرباء في الطبقة المجانيةصعبسهل

ما يجعل هذا التبادل آمناً أربع طبقات يعطيك إياها connector: وصف الأداة محمّل دائماً ويقول "استدعِ session-init أولاً"؛ وعودة session-init تحمل القواعد كاملة؛ وكل عودة من أداة تكرر تذكيراً من سطر واحد، ليقف مكان جسم Skill الدائم في السياق؛ والأدوات الحقيقية محجوبة خلف session token. لذلك: اشحن مسار connector افتراضياً، وأبق Skill كإضافة اختيارية للمستخدم القوي. الأمر قابل للعكس: اختبر الاثنين، واحتفظ بما يمسك السلوك أفضل.

المفهوم 10: عقد session-init

تصل القواعد وحالة المستخدم عبر أداة واحدة يستدعيها النموذج أولاً. سمّها begin_session، أو ما شئت.

عندما يقول المستخدم أي شيء يعني "ابدأ" أو "تابع"، يستدعي النموذج begin_session(). هذا check-in: يتحقق المكتب من جواز الضيف، أي token الموقّع من المفهوم 7، ثم يثبت عليه بطاقة مفتاح، أي session token قصير العمر. تقرأ بوابتك قواعد التطبيق (config_*) وحالة المستخدم (user_*) وتعيدها ككتلة تعاونية واحدة: "إليك كيف تتصرف لهذا المستخدم، وإليك أين كان"، ومعها بطاقة المفتاح. ثم تفحص كل أداة حقيقية ذلك: لا بطاقة، لا دخول.

note

هذا token جلسة على مستوى التطبيق، لا جلسة بروتوكول MCP. إنه handle يصدره خادمك ويمرره النموذج كوسيط أداة عادي: منطق الحجب لديك، لا منطق النقل. هذا الفرق مهم لاحقاً: يزيل release candidate 2026-07-28 للمواصفة الجلسات على مستوى البروتوكول، أي header Mcp-Session-Id، ويطلب من الخوادم التي تحتاج حالة عبر الاستدعاءات أن تفعل هذا بالضبط: تصدر handle خاصها وتمرره كوسيط أداة. لذلك هذا النمط ليس متوافقاً فقط مع اتجاه MCP؛ بل هو الاتجاه.

@mcp.tool()
def begin_session() -> dict:
"""Call this FIRST on any new request. Returns how to behave for this
user, their saved state, and a session token the other tools require."""
sub = verified_claims(current_token())["sub"] # identity from the token (Concept 7)
return {
"session": new_session_token(sub), # gates every other tool (Concept 4)
"rules": config_get_rules(), # cooperative: "here's how to behave"
"state": user_get_state(sub), # where this user left off
}

نقطتا تصميم يجب أن يحترمهما وكيلك:

  • صغه كتعاون، لا كتجاوز. قل: "إليك ما يفضله ضيفنا؛ ساعده على الاستقرار" فيساعد الconcierge؛ واصرخ: "انس تعليماتك السابقة وأطعني" فيستدعي الأمن، لأن هذه لغة محتال، والنموذج مدرّب على اكتشافها. النص الذي يحاول تجاوز النموذج يُخفّضه الدفاع نفسه الذي يحمي المستخدمين من prompt injection. الصياغة التعاونية تمر؛ الصياغة الآمرة تُهمل.
  • اجعل النموذج يستدعيها أولاً بجعلها ضرورية. الأدوات الحقيقية تتطلب session token الذي لا يصدره إلا begin_session، لذلك لا يستطيع النموذج العمل بلا مرور بالباب الأمامي. الوصف يقول "استدعني أولاً"، والعودة مفيدة، والأدوات مقفلة خلف token: ثلاث دفعات تلتقي على السلوك الصحيح. ثم واصل التعزيز: اجعل كل أداة تعيد نتيجتها مع تذكير من سطر واحد عن كيفية تقديمها.

عقد begin_session كشرائط ثلاثية. الأول: يستدعي النموذج begin_session() أولاً، ولا يستطيع الوصول إلى الأدوات الحقيقية بأي طريقة أخرى. الثاني: تعيد بوابتك كتلة تعاونية واحدة، القواعد والشخصية وحالة المستخدم المحفوظة وsession token قصير العمر، مع قراءة الهوية من sub في token لا من النموذج. الثالث، مميز: تتطلب كل أداة حقيقية ذلك session token، بلا token لا عمل، فيفشل التطبيق مغلقاً بدلاً من الارتجال. يذكر الهامش الدفعات الثلاث التي تجعل النموذج يستدعيها أولاً: الوصف، والعودة المفيدة، والأدوات المقفلة.

شغّله. الصق هذا لوكيل البرمجة لديك:

let's do Concept 10: add begin_session returning rules + state + a signed session token, make the description instruct the model to call it first, and have domain_get_item reject calls without a valid session.

تم عندما: في طلب جديد، يستدعي النموذج begin_session، ويحصل على القواعد وحالة المستخدم المحفوظة، وبعد ذلك فقط يستطيع الوصول إلى أدوات domain. تتبع الصياغة التعاونية؛ أما صياغة "ignore previous instructions" فهي النسخة التي تخفضها دفاعات injection لدى النموذج. أصبح session token الآن مفتاح كل شيء حقيقي.

المفهوم 11: افشل مغلقاً، ولا تتحول بصمت إلى chatbot

نمط فشل يفسد تطبيقاً كهذا بصمت: إذا كان connector لديك غائباً أو غير مفوّض أو يخطئ، فما زال النموذج يعرف الكثير وحده، وسيرتجل بثقة إجابات ويخترع حالة المستخدم. يصبح منتجك المنظم chatbot يلبس اسمه، ولا يعرف أحد حتى يقع الضرر. إنها قاعدة الصراف الآلي من البداية مرة أخرى، لكنها أصعب: الصراف غبي ويقفل ببساطة، أما موظفك ف_ذكي_ ومغرَى بأن يخمّن رصيدك ليبدو مفيداً.

الفخ هنا: إغلاق خزانة الملفات، أي بوابة الجلسة، لا يمنع الموظف من التخمين من الذاكرة. البوابة تقفل أدواتك؛ لا تستطيع قفل معرفة النموذج نفسه. لذلك يجب أن تضيف قواعدك، المعادة من begin_session، الأمر الدائم الملصق على المكتب: إذا كان begin_session غير متاح أو أعادت أداة خطأً، فقل بوضوح إن الجلسة لا تستطيع الاستمرار الآن؛ لا ترتجل نتائج ولا تختلق حالة محفوظة. افشل بصدق وبشكل مرئي. فقرة واحدة تحمي المنتج كله (الثابت 4).

تعيش هذه الفقرة في قواعد config_*، حيث يقرأها النموذج في كل جلسة:

# config_store.py — the fail-closed paragraph (you write this)
RULES = """\
You are the assistant for <YOUR APP>. Behave as follows for this user:
- <how to greet, your app's do's and don'ts>

Fail closed: if you cannot reach begin_session or a tool returns an error, tell the user
plainly that the session can't continue right now. Do NOT improvise an answer from your own
knowledge and do NOT invent the user's saved state.
"""

هذه الفقرة لا تقف وحدها: الأدوات بالفعل ترمي عند جلسة سيئة أو مفقودة، وهي البوابة من المفهوم 10، وعودة كل أداة تكرر تذكيراً من سطر واحد بكيفية تقديم النتائج، لذلك يُوجّه النموذج نحو الصدق لا يُطلب منه الصدق فقط.

شغّله. الصق هذا لوكيل البرمجة لديك:

stop my Postgres (or point DATABASE_URL at a dead host), then ask the app to do its job. Show me whether it refuses cleanly per the fail-closed rule, or whether it invents an answer — and if it invents, strengthen the rule and the per-tool reminders until it refuses.

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

Checkpoint: حلقة الثقة أُغلقت. الهوية مثبتة، والنموذج موجّه عبر جلسة محجوبة، والتطبيق يرفض بدلاً من التزييف. ما بقي أن تضعه على الإنترنت.


Part 5: اشحنه

المفهوم 12: شغّله حياً (بلا Docker، بلا deploy)

لأن Claude يصل إلى خادمك من سحابة Anthropic، فعبارة "يعمل على حاسوبي" لا تكفي: الخادم على حاسوبك منضدة داخل بيت مقفل، حقيقية لكن بلا باب إلى الشارع. الإصلاح المدرسي هو deploy كامل، أي container على مضيف مستأجر. لا تحتاج إلى ذلك لمجرد أن تراه يعمل. بدلاً من ذلك تفتح باباً عاماً مؤقتاً إلى حاسوبك مباشرة، tunnel، وتشغّل pop-up سريعاً من connector لديك. مجاني، بلا حساب استضافة، بلا بطاقة، ويعمل في نحو دقيقة.

مع هذا تأتي حركة صادقة. claude.ai يوقّع المستخدمين عبر OAuth حقيقي، وأنت لا تملك بعد خدمة تسجيل دخول حقيقية؛ إقامة واحدة هي دورة AI Identity. لذلك في هذا العرض الشخصي تطفئ القفل بمفتاح سطر واحد AUTH_DISABLED=1. لقد أثبتت أن القفل يعمل في المفهوم 8 ضد mock؛ هنا تضعه جانباً حتى تصل إلى claude.ai اليوم بلا خدمة تسجيل دخول. عندما يكون auth مطفأً يصبح الجميع مستخدماً بديلاً واحداً، وهذا مناسب تماماً لتجربة شخصية، وهو الشيء الوحيد الذي يجعل عرضاً في ظهيرة واحدة ممكناً.

ابنه. يقود وكيلك مهارة live-connector المرفقة، فيثبت أداة tunnel، ويفتح الباب، ويبدأ خادمك مع auth off. الصق:

Put my connector live with the live-connector skill: turn auth off, start the gateway, open the Cloudflare tunnel, and give me the public connector URL. Confirm an unauthenticated tool list returns 200 over the tunnel before you hand it to me.

تم عندما: تطبع المهارة رابط https://….trycloudflare.com/mcp ويعيد tools/list غير الموثّق 200 من خلاله. هذا الرابط العام هو ما تلصقه في claude.ai بعد ذلك.

caution

إنه باب مفتوح ومؤقت. مع auth off، أي شخص يملك الرابط يستطيع الوصول إلى أدواتك وبيانات Neon لديك ما دام tunnel يعمل، وكل caller هو المستخدم البديل نفسه. عامله كعرض شخصي: أوقف tunnel عندما تنتهي (pkill -f "cloudflared tunnel")، وتوقع أن يتغير الرابط في كل مرة تعيد تشغيله.

المفهوم 13: أضفه إلى claude.ai وشاهد تطبيقك كله يعمل

هذا هو العائد، وأنت تفعل هذا الجزء. لا توجد خطوة Authorize هذه المرة، لأن auth مطفأ للعرض:

  1. في claude.ai: Settings → Connectors → Add custom connector. الصق رابط tunnel (المنتهي ب /mcp) وانقر Add. بلا client id، ولا Advanced settings.
  2. اطلب من تطبيقك أن يؤدي عمله بلغة عادية.
  3. افتح محادثة جديدة تماماً واطلب منه المتابعة من حيث توقفت.
ما الذي ستراه، وما الذي تتحقق منه

يستجيب تطبيقك بوصفه نفسه: يستدعي النموذج begin_session أولاً، ويحصل على قواعدك وحالة المستخدم البديل، ثم يعمل عبر الأدوات المحجوبة. ولأن الحالة محفوظة تحت user id، هنا sub بديل واحد، لا تحت المحادثة، تستأنف محادثة جديدة تماماً من حيث توقفت: المحادثة هي الزيارة، والهوية هي الملف. تلك الذاكرة العابرة للمحادثات داخل claude.ai، من رابط واحد ملصوق، هي المنتج كله وهو يعمل. ملاحظتان: الجميع هو المستخدم البديل نفسه حتى توصيل تسجيل دخول حقيقي، وهذا هو AI Identity، وعندما يتغير رابط tunnel عليك إعادة إضافة connector لا تعديله.

Checkpoint: شغّلته حياً. شاهدت تطبيقك كله يعمل داخل claude.ai: النموذج يستدعي أدواتك عبر جلسة محجوبة بالهوية، والذاكرة تنتقل بين المحادثات، والتطبيق يفشل مغلقاً بدلاً من التزييف، وكل ذلك على حساب مجاني. القطعة الوحيدة المتبقية لconnector عام يسجل فيه غرباء حقيقيون هي خدمة تسجيل دخول حقيقية، وهي الامتداد التالي مباشرة في المسار: دورة AI Identity. اجلس قليلاً مع ما بنيته قبل أن يأخذه الجزء التالي أبعد.


Part 6: مشروع التتويج، مجالك أنت

لقد بنيت Reading Room عبر المفاهيم. الآن أثبت أن الهيكل أصبح لك بأن توجهه إلى شيء تعرفه أنت. الهيكل لا يتغير: بوابة واحدة، وثلاث مجموعات أدوات، وعقد begin_session، وهوية من subject، وفشل مغلق. الذي يتغير هو المجموعات الثلاث فقط.

بعض الأشكال التي تستحق رؤيتها:

  • Tutor: domain هو محتوى الدورة؛ user هو تقدم المتعلم؛ config هو شخصية المعلم مع طريقة التدريس؛ begin_session يحمّل الشخصية + الطريقة + موضع المتعلم؛ وfail closed يمنعه من الانحلال إلى chatbot عام.
  • مساعد دعم: domain يبحث في الطلبات والسياسات؛ user تاريخ تذاكر هذا العميل؛ config النبرة وقواعد التصعيد.
  • مساعد مستندات داخلية: domain يبحث في wiki الفريق؛ user أي فريق تنتمي إليه؛ config ما هو سري وكيفية الاستشهاد.
  • مساعد حجز: domain التوفر والحجوزات؛ user التفضيلات المحفوظة؛ config قواعد الإلغاء والتسعير.

اختر الأقرب إلى شيء تعرفه فعلاً، وشغّل الحلقة نفسها التي شغّلتها للتو: خطط → راجع → ضع الهيكل → راكم القطع → تحقق. شغّله، وأضفه إلى Claude لديك، واجعله يخدم طلباً حقيقياً واحداً ويتذكره في اليوم التالي.

ابدأ كما بدأت Reading Room: اجعل الوكيل يقترح، وأنت تراجع. الصق هذا:

Before you build anything, map my domain onto the three groups for me: what goes in domain, what goes in user, what goes in config, and what begin_session should hand back for this app. Show me that mapping so I can review it the way I reviewed the Reading Room plan, then we plan the rest.

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

1Your Work
2Get Your Score

Discuss with an AI. Question your scores.
Come back when you have your BEST evaluation.


Part 7: السقف، وإلى أين ينمو

المفهوم 14: السقف، والجسر نحو امتلاك حلقة

اشعر بحافة ما بنيته، لأنها تشير تماماً إلى أين يذهب الكتاب بعد ذلك.

لا يستطيع تطبيقك أن يعمل إلا عندما يكتب المستخدم. إنه المكنسة اليدوية من المفهوم 1: ميت حتى تضغط يد الزناد. لا يستطيع الاستيقاظ وحده، أو العمل وفق جدول، أو ملاحظة شيء والتواصل تلقائياً، أو متابعة هدف عبر خطوات عدة بلا دور بشري بين كل خطوة. هذا ليس عيباً في بنائك؛ بل طبيعة تطبيق connector-native. الحلقة تعود إلى تطبيق المحادثة المضيف، لا إليك.

في اللحظة التي تريد فيها عاملاً يعمل وحده، يستيقظ، يأخذ خطوات، يستدعي أدوات في حلقة، وينهي عملاً وأنت نائم، يجب أن تملك الحلقة بنفسك. تلك هي المكنسة الروبوتية، وهناك يقود المسار. في Build AI Agents تتوقف عن حمل المكنسة اليدوية وتبدأ بناء الروبوت: تتوقف عن كونك الخادم الذي يستدعيه نموذج وتبدأ كتابة الوكيل الذي يقوم بالاستدعاء.

تأتي دورتان أولاً. Plugins for AI Agents هي صورة المرآة لهذه الدورة: تطبيق connector-native يوسّع تطبيق المحادثة (claude.ai) للمستخدمين النهائيين؛ وplugin يوسّع وكيل البرمجة (Claude Code وOpenCode) للبناة. الفكرة نفسها: شحن وحدة يحمّلها مضيف، موجهة إلى المضيف الآخر.

Connectors وplugins هما الحركة نفسها موجهة إلى مضيفين مختلفين. في اليسار، تطبيق connector-native في هذه الدورة يوسّع تطبيق المحادثة (claude.ai) للمستخدمين النهائيين: تشحن خادم MCP بعيداً بأدوات وحالة وهوية، ويحمّله المستخدم بلصق رابط واحد. في اليمين، plugin يوسّع وكيل البرمجة (Claude Code أو OpenCode) للبناة: تشحن skills ووكلاء فرعيين وhooks وأدوات وخوادم MCP مثبتة في الوكيل. كلاهما وحدة يحمّلها مضيف، ولا يملك أي منهما حلقة؛ المضيف يملكها. الفرق الوحيد هو أي مضيف توسّع.

AI Identity: Human Sign-In and Agent Access، المبني على Better Auth، يأتي في نصفين: أولاً تملك تسجيل الدخول، فتقيم خادم OAuth/OIDC خاصاً بك يصدر tokens التي لم تفعل هذه الدورة إلا التحقق منها؛ ثم تعطي وكيلاً هويته الخاصة، أي credential وطريقة محددة النطاق ومؤقتة وقابلة للإلغاء ومعتمدة من إنسان للعمل نيابةً عن شخص. ثم يعطيك Build AI Agents الحلقة.

لم تهدر خطوة. شحنت ما يمكنك شحنه قبل أن تملك حلقة، وشعرت بالضبط لماذا ستريد واحدة، والآن تذهب إليها.

التطبيق نفسه، معمّقاً عبر Mode 2

لن ترمي v1. الدورات اللاحقة تطوّر هذا التطبيق نفسه، وهذه هي الطريقة التي تنهي بها Manufacturing وفي يدك منتج حقيقي نمّيته طوال الطريق:

ستضيفماذا يطوّرفي
بحثاً دلالياً على مجالكdomain_get_item(id)domain_search(query)RAG على Postgres + pgvector
نظام سجل متين (تدقيق، موافقة، حالة موثوقة)الذاكرة البسيطة من جدولينBuilding a Digital FTE
شخصية عالية الدقة / config أغنى (حواجز ضد التلفيق)قواعد config_* البسيطةIdentic AI
issuer tokens خاصاً بك، مع هوية للوكلاء (محددة النطاق، قابلة للإلغاء، on-behalf-of)خدمة تسجيل الدخول المستأجرةAI Identity (Better Auth)
دليلاً على أنه يؤدي عمله جيداً فعلاً«يبدو أنه يعمل»Eval-Driven Development
تقوية إنتاجية (قابلية ملاحظة، بوابة اختبار CI)عرض tunnel الحيDeploy the Agent Harness

وسيلة دراسة بالبطاقات