MCP والأدوات المتصلة
اربط Nessie بخوادم MCP، واقترن بوكيل خارجي ليعمل داخل Nessie باسمك.
ما هو MCP
بروتوكول سياق النموذج (Model Context Protocol) اتفاقية صغيرة ومفتوحة لوصف الأدوات لنموذج لغوي واستدعائها. يعلن الخادم ما يستطيع فعله: قائمة بأدوات مسمّاة، ولكل منها مخطط JSON لوسائطها، ويكتشف العميل هذه القائمة ويستدعي الأدوات نيابةً عن النموذج. وهو بسيط عمدًا، فقيمته أن يعمل تكامل واحد يُكتب مرة واحدة مع كل نموذج وكل منتج يتحدث بهذا البروتوكول.
تقف Nessie على الجانبين
هذا يستحق الدقة، لأن الجانبين يسهل الخلط بينهما، وهما يعيشان على مسارين مختلفين عمدًا.
- صادر. Nessie هي عميل MCP. تربط خوادم يشغّلها غيرك، فتصبح الأدوات التي تكشفها متاحة لوكلائك. وواجهة الإدارة لهذا الجانب هي
/api/mcp/*. - وارد. Nessie هي أيضًا خادم MCP. يستطيع وكيل يعمل في مكان آخر، مثل Claude Code أو Codex على جهاز المطور، أن يصل إلى لوحاتك ومستنداتك. وهذه النقطة النهائية هي
POST /mcp، خارج/apiعمدًا، كي لا يفصل بين المعنيين المتعاكسين مقطع مسار واحد فقط.
ربط خادم MCP بـNessie
مُدخلات الكتالوج والمثيلات
هناك كائنان، والفرق بينهما مهم:
- مُدخل الكتالوج هو تعريف الخادم: اسمه، ونوع النقل فيه، وطريقة مصادقته. يُكتب مرة واحدة ويمكن مشاركته.
- المثيل هو ذلك المُدخل مُثبَّتًا على نطاق واحد، مع بيانات الاعتماد التي تصل إليه. وتثبيت المُدخل نفسه لفريقين مختلفين ينتج مثيلين.
معظم الناس لا يتعاملون مع أي منهما مباشرة. المدخل إلى لوحة الإدارة هو متجر التطبيقات على /admin/apps: يتصفح الكتالوج نفسه مع إخفاء تفاصيل الاتصال، وConnect على أي بطاقة ينشئ مثيلًا. أما المشغّلون الذين يريدون الكائنات الخام فيستخدمون /api/mcp/catalog و/api/mcp/instances.
إذا لم يكن الخادم موجودًا في الكتالوج بعد، فإن POST /api/mcp/discover يأخذ عنوان URL ويعيد ما يقوله الخادم عن نفسه، وPOST /api/mcp/library/import يسحب مُدخلًا من مكتبة الخوادم العامة. ويمكن أيضًا إنشاء اتصال أول مباشرة من عنوان URL عبر POST /api/apps/custom.
وسائل النقل
تتصل Nessie بالخوادم البعيدة عبر HTTP، ويعمل نوعان: HTTP القابل للبث (streamable HTTP)، وهو نقل MCP الحالي، والنقل الأقدم HTTP+SSE. اختر http ما لم يكن الخادم يعرض sse فقط.
نقل stdio مرفوض للموصّلات التي تكتبها أنت. يعني stdio أن خادم MCP عملية محلية يبدؤها المضيف، وتشغيل برامج عشوائية داخل خادم Nessie أمر لا يستطيع المشغّل مراجعته بجدية. والخوادم المنشورة كحزمة للتشغيل محليًا فقط تُستبعد من عمليات الاستيراد من المكتبة للسبب نفسه. وتوجد القيمة ws في حقل البروتوكول لكنها غير منفّذة، فالاتصال الذي يستخدمها يفشل عندما تحاول Nessie فتحه.
كيف تصادق Nessie على الخادم
يصرّح مُدخل الكتالوج بإحدى خمس طرق: none أو api_key أو bearer أو basic أو oauth2.
api_key هو حقن ترويسة، ويحدد المُدخل الترويسة والبادئة، فـAuthorization: Bearer … وX-API-Key: … وX-Auth-Token: Token … كلها الطريقة نفسها بإعدادات مختلفة. يُلصق المفتاح نفسه مرة واحدة عبر POST /api/mcp/instances/:instanceId/secret، ولا يمكن قراءته بعد ذلك أبدًا؛ ولا تحمل أي استجابة من مسارات المثيل مرجعًا لبيانات الاعتماد.
oauth2 يأتي بشكلين. الخادم ذو النقاط الثابتة تُخزَّن نقاطه في مُدخل الكتالوج الخاص به. أما الخادم الذي ينشر بيانات وصفية قياسية فلا يحتاج إلى أي إعداد: تقرأ Nessie وثيقتي المورد المحمي وخادم التفويض، وتنشئ لنفسها عميلًا عبر التسجيل الديناميكي للعميل، أو عبر وثيقة معرّف العميل التي تنشرها على مسارها الخاص well-known. وفي الحالتين يتكوّن التفاوض من POST /api/mcp/instances/:instanceId/oauth/start يليه إعادة التوجيه من المزوّد إلى GET /api/mcp/oauth/callback. ورمز الحالة يُستخدم مرة واحدة، ويُحفظ في قاعدة البيانات، وصلاحيته عشر دقائق، ويُستخدم PKCE دائمًا.
قاعدة واحدة تفاجئ الناس: حتى مالك المؤسسة لا يستطيع أن يربط رمزًا شخصيًا أو رمز OAuth بشخص آخر. ولا يمكن مشاركة بيانات الاعتماد إلا لمُدخل من نوع مفتاح API تم التحقق من أنه كذلك، وأي شيء آخر يُرفض. أما بيانات الاعتماد التي تنتمي إلى شخص فتبقى مرتبطة بذلك الشخص.
أين تُخزَّن بيانات الاعتماد
تُخزَّن أسرار الموصّلات وحزم رموز OAuth في قاعدة Postgres الخاصة بك، داخل أظرف AES-256-GCM مرتبطة بغرض محدد، تحت حلقة مفاتيح التشفير المستقلة والمُرقّمة في النشر، ولا يُشار إليها إلا بمراجع مُبهمة من نوع secret_*. وهي ليست في خزنة الأسرار الخارجية التي تحفظ أسرار Nessie الأخرى، وذلك عن قصد. ويرفض الإنتاج الذي لم يُضبط فيه المخزن المشفّر أن يبدأ التشغيل، بدل أن ينهي تفاوض OAuth ثم يُسقطه.
أين يصل الاتصال
يُثبَّت المثيل على واحد من ستة نطاقات: system أو organization أو project أو team أو channel أو user. والنطاق سقف صارم لتحديد أي عمليات تشغيل تستطيع استخدامه، والمنح لا تستطيع إلا أن تضيّقه، ولا توسّعه أبدًا؛ فموصّل ثبّته بحسابك الشخصي لا يمكن أن يصبح بهدوء على مستوى المؤسسة كلها.
من يحق له التثبيت أين يتبع الشكل نفسه: يدير مالكو المؤسسة ومسؤولوها التثبيت في أي نطاق؛ ويثبّت أي شخص آخر الموصّلات على نطاق user الخاص به، ويستطيع أن يرى التثبيتات المشتركة التي يحق له الوصول إليها.
منح وكيل أداة
ربط خادم لا يسلّم أدواته لأي أحد. فعند تثبيت المثيل تفحصه Nessie وتسجّل كل أداة يعلنها في سجل الأدوات، وهو ما تعرضه لوحة الإدارة على /admin/advanced/tools: الأدوات المدمجة، وأدوات MCP، وأدوات الحزم، وأدوات بيئة التنفيذ في قائمة واحدة، ولكل أداة مصدرها وحالتها.
للأداة المُسجَّلة إحدى ثلاث حالات: active أو pending_review أو disabled. تصل الأدوات من تثبيت على نطاق مشترك بحالة pending_review، ويجب الموافقة عليها في تلك الصفحة قبل أن يراها أي وكيل؛ أما أدوات تثبيتك على نطاق user فتصبح فعالة فورًا، لأن الشخص الوحيد المعرّض لها هو أنت. والمراجعة متكررة لا لمرة واحدة: إذا وجد فحص لاحق أن وصف الأداة أو مخططها تغيّر، تعود إلى pending_review وتتوقف عن العرض إلى أن ينظر أحدهم في التغيير.
يُحدَّد أي وكلاء يحق لهم استدعاء أداة فعالة بإحدى طريقتين:
- الاتصال الذي يُنشأ عبر متجر التطبيقات يتطلب منحة صريحة. لا يحصل الوكيل على الأداة إلا إذا سمّتها منحة، وتُفحص المنحة مقابل البصمة الحالية للأداة، فالأداة المتغيرة تحتاج إلى قرار جديد.
- وإلا فالأداة مفعّلة افتراضيًا للوكلاء الواقعين ضمن نطاقها، ويمكن إيقافها لكل وكيل على حدة من لوحة تفاصيل الأداة.
تسمّي المنحة جهة واحدة بالضبط، دورًا أو وكيلًا، لا الاثنين معًا، والرفض يتغلب على السماح. أما في اتصال على نطاق user فلا يُطرح السؤال أصلًا: يستطيع أي وكيل يتحدث معه ذلك الشخص أن يستخدمه، والتعطيل الصريح هو الشيء الوحيد الذي يحجبه.
شيء سهل أن يُبحث عنه في المكان الخطأ: /settings/accounts في لوحة الإدارة هو الحسابات المتصلة، أي Slack وصناديق البريد واشتراكات النماذج وروابط OAuth مع Linear وJira وGitHub وTrello التي تقف خلف اللوحات الخارجية. أما موصّلات MCP فتوجد على /admin/apps، والأدوات التي تنتجها على /admin/advanced/tools.
بوابات الموافقة على استدعاءات الأدوات
تتوقف بعض استدعاءات الأدوات وتنتظر شخصًا. وعندما يحدث ذلك لا تفشل العملية: يُجمَّد الاستدعاء، أي اسم الأداة وتجزئة وسائطها والحالة الكافية لاستئنافه، ويظهر طلب الموافقة في /api/approvals ليجيب عنه أحدهم. والاستئناف آمن للتكرار، فلا يمكن لموافقة مكررة أن تنفّذ الاستدعاء مرتين. ويرى الشخص الذي يقرر ملخصًا محدودًا لما يُطلب، أما الوسائط الدقيقة والعملية الأصلية فتبقى على الخادم.
توجد بوابتان مختلفتان، ولكل منهما إعداد مختلف.
- البوابات البنيوية خاصية لأدوات مدمجة معينة، ولا يمكن ضبطها. فإرسال البريد من صندوق بريد الوكيل أو من صندوق متصل، وإرسال مسودة Gmail، وفصل حساب بريد، وإنشاء حدث في التقويم أو تغييره أو إلغاؤه، وكذلك أي إجراء في المتصفح يكتب إلى موقع لم يسجّل المتصفح الدخول إليه، كلها خاضعة لهذه البوابة بالطريقة نفسها. ولها نافذة 24 ساعة للإجابة بدلًا من 30 دقيقة المعتادة.
- بوابات السياسة تأتي من قواعد السياسة على الزوج
tool/invoke. والقاعدة التي تسمح باستدعاء يمكن أن تحملrequiresApproval، ومن دون موافقة مُتحقَّق منها يعيد التقييمAPPROVAL_REQUIREDبدل أن يُنفَّذ. وتُقيَّم القواعد بمبدأ الرفض أولًا، ومرتبة حسب النطاق.
لم نتمكن من تأكيد الشاشة في لوحة الإدارة التي تكتب قاعدة السياسة requiresApproval لأداة معينة، فنموذج البيانات والتطبيق موجودان كلاهما، لكن الشاشة التي تكتب هذه القاعدة غير مؤكدة.
ربط وكيل خارجي بـNessie
الاتجاه الآخر. تشغّل Nessie خادم MCP خاصًا بها على POST /mcp، عبر HTTP القابل للبث، وهو عديم الحالة: كل استدعاء يحمل بيانات اعتماده ويحدد فاعله بنفسه، فلا توجد جلسة تُثبّت العميل على نسخة واحدة. ويستطيع ChatGPT وClaude وClaude Code وCodex، أو وكيل على حاسوب شخص ما، أن يعمل على لوحاتك ومستنداتك وعملائك من داخل الأداة التي يستخدمها ذلك الشخص أصلًا. والخطوات التفصيلية لكل تطبيق موجودة في ربط ChatGPT وClaude وتطبيقات الذكاء الاصطناعي الأخرى.
ما هي بيانات الاعتماد المقترَنة فعلًا
هذا الجزء يجب فهمه جيدًا، لأن النموذج الذهني الواضح، أي مفتاح API تُربط به الصلاحيات، هو النموذج الخاطئ.
بيانات الاعتماد المقترَنة ليست هوية أبدًا. إنها تسمّي إنسانًا، ويعمل كل استدعاء أداة باسم ذلك الإنسان، عبر الدوال نفسها التي تستدعيها مسارات HTTP. لذلك لا يستطيع الوكيل الوصول إلى أي شيء لا يستطيع الشخص الذي أعاره إياه الوصول إليه بالنقر. والنطاقات لا تضيّق هذا الوصول إلا، ولا يوجد نطاق يوسّعه.
تُعاد قراءة الصلاحية عند كل استدعاء منفرد، ولا تُقبل من الرمز نفسه: الإلغاء، والانتهاء، وإصدار رمز المستخدم، وعضويته في المؤسسة، ودوره الحالي. فالتخفيض، أو التعطيل، أو «تسجيل الخروج من كل مكان» يسري على الاستدعاء التالي للوكيل، لا عند انتهاء صلاحية بيانات الاعتماد.
الرمز مبهم، يبدأ بالبادئة nag1_، ويُخزَّن فقط كتجزئة SHA-256، ويعيش 90 يومًا. ويُرفض برمز 403 محدد على أي مسار غير نقطة نهاية MCP؛ فتقديمه في مكان آخر ليس نجاحًا جزئيًا يُعاد المحاولة به، وهذا ما يمنع أن تعني «أعرت وكيلًا لوحاتي» أنني «أعرته حسابي».
طريقتان للربط
التطبيق الذي يستطيع فتح متصفح، مثل ChatGPT وClaude وClaude Code وCodex، يستخدم ملف تعريف تفويض MCP: OAuth 2.1 مع PKCE (S256)، والتسجيل الديناميكي للعميل عند POST /mcp/oauth/register، ورموز التحديث ومؤشرات الموارد. يرسل التطبيق الشخص إلى /settings/security، فيختار ما يسمح به التطبيق وأي فرقه يصل إليها، ثم يعود المتصفح إلى التطبيق برمز. ويعيش رمز الوصول ساعة واحدة ويُجدَّد، ويستمر الاتصال 90 يومًا.
الوكيل الذي يعمل من سطر الأوامر لا يتحكم في متصفح، ولا يستطيع استضافة عنوان URL لإعادة الاتصال، لذلك يقترن عبر منحة تفويض الجهاز (RFC 8628).
- يستدعي الوكيل
POST /mcp/auth/deviceمعclientNameوscopesالتي يريدها. فيحصل علىdevice_code، وuser_codeقصيرًا، وverification_uri، وverification_uri_completeيحمل الرمز في الاستعلام نفسه، إضافة إلىintervalللاستطلاع وexpires_in. ويطبع عنوان URI. - يفتح الشخص ذلك العنوان وهو مسجّل الدخول، في
/settings/security. فيرى أي وكيل يطلب، وباسم أي حساب سيعمل، وإلى متى، وما الذي سيستطيع فعله بالضبط، ثم يختار السماح أو عدم السماح. - يستطلع الوكيل
POST /mcp/auth/tokenبـdeviceCode، مع مراعاةauthorization_pendingوslow_downوexpired_tokenوaccess_denied. وعند النجاح يحصل على{ access_token, token_type, scope, expires_at }.
في الحالتين توجد خطوة بشرية، لأن بيانات الاعتماد ترث صلاحيات الشخص، فيجب أن يختار الشخص أن يعيرها. ولا تُنشئ هذه الآلية وصولًا من لا شيء. ويمكن أيضًا إيقاف الربط لمؤسسة كاملة من /admin/security?tab=programs، وتُفحص تلك الإجابة عند سماح أحد بالاتصال، لا عندما يبدأ وكيل اتصالًا.
الاكتشاف
يردّ POST /mcp غير المصادَق عليه بالرمز 401 مع ترويسة WWW-Authenticate تشير إلى /.well-known/oauth-protected-resource (RFC 9728)، الذي يسمّي هذا الأصل خادم التفويض. وبياناته الوصفية عند /.well-known/oauth-authorization-server (RFC 8414) تسمّي نقاط التسجيل والتفويض والرمز والإلغاء. وهذه السلسلة كل ما يحتاجه العميل بعد أن يملك العنوان. ولإيجاد العنوان انطلاقًا من نطاق، يقرأ الوكيل /.well-known/ai-catalog.json، الذي يسمّي بطاقة الخادم عند /mcp/server-card (MCP Server Cards, SEP-2127). وتُدرج نقاط نهاية منحة الجهاز في وثيقة المورد المحمي تحت x-nessie-device-authorization.
يمكن لنشر أن يجيب أيضًا على عنوان ثانٍ أقصر: فـhttps://nessie.works/mcp الخاص بـNessie Cloud يُمرَّر إلى الـAPI، ويُعاد هذا العنوان للعميل الذي جاء بهذا الطريق بوصفه المورد، بينما يبقى تسجيل الدخول على الـAPI. ولا تكفي إعادة التوجيه، لأن العميل يرفض أي بيانات وصفية تسمّي عنوانًا غير العنوان الذي أُعطيه. ويسرد المشغّل هذه الأصول في NESSIE_MCP_ALIAS_ORIGINS.
النطاقات والأدوات
النطاقات عامة عمدًا، فالنطاق الذي لا يستطيع أحد شرحه لا يستطيع أحد ضبطه بشكل صحيح. ويسرد الاتصال الذي يصل إلى أكثر من فريق تلك الفرق عبر nessie_team_list، وبعد ذلك تسمّي كل أداة أخرى teamId الخاص بها.
| النطاق | يصل إلى |
|---|---|
boards_read | المشاريع واللوحات والتذاكر، مع تعليقاتها وملفاتها ووسومها وأنواعها وقوائمها المرجعية |
boards_write | إنشاء التذاكر وتعديلها ونقلها، وكل ما يتعلق بها |
documents_read | مساحات المعرفة والمستندات وجداول البيانات |
documents_write | صياغتها وتحريرها، وطلب نشر أحدها |
clients_read | صندوق وارد العملاء، وجهات الاتصال، وقوائم جهات الاتصال، والنشرات البريدية، ونماذج الاتصال |
clients_write | الملاحظات، والاستلام، والإسناد، وإغلاق المحادثات، وقوائم جهات الاتصال، وإعداد النشرات البريدية |
clients_send | أي شيء يتلقاه العميل: رد أو بريد أول أو رسالة نصية. لا يُفعَّل هذا النطاق أبدًا إلا إذا فعّله الشخص بنفسه |
website_tools | أدوات الصفحات في الموقع المسجَّل لفريقك، تعمل في متصفح مستضاف يمكنك التحكم فيه. لا تُفعَّل أبدًا إلا إذا فعّلها الشخص بنفسه |
الاستدعاء الذي يفتقر إلى النطاق اللازم يعود كنتيجة أداة تسمّي النطاق الذي يجب طلبه، لا كخطأ في النقل، فيستطيع النموذج أن يبلغ عن شيء مفيد بدل أن يعيد المحاولة ضد جدار.
لا توجد عائلة منفصلة من الأدوات للمتتبعات الخارجية. فاللوحة لوحة سواء نشأت مهامها في Nessie أو انعكست من Linear أو Jira أو GitHub أو Trello، لذلك تغطي مجموعة أدوات واحدة الحالتين، وكل مهمة تذكر مصدرها. ويختلف الأمر في الكتابة فقط: اللوحة المنعكسة من مصدر للقراءة فقط ترفض الكتابة بالكلمات، فتخبر الوكيل بأن النظام الآخر يملك التذكرة، وأن إعادة المحاولة لن تفيد.
نشر المستند موافقة، لا نطاق
يقترح الوكلاء، والشخص ينشر. وتفرض Nessie هذه القاعدة على وكلائها بأن ترفض أي فاعل من نوع وكيل رفضًا تامًا، لكن بيانات الاعتماد المقترنة تُحل بوصفها شخصًا، فلا يستطيع ذلك الرفض أن يلتقطها. لذلك يجب أن تكون البوابة في مكان آخر.
لذا فإن nessie_doc_publish لا ينشر، بل يفتح موافقة knowledge.page.publish، وهي الموافقة نفسها التي يفتحها وكيل Nessie، ويعيد { status: "awaiting_approval", approvalId }. والاستطلاع يعيد الطلب نفسه بدل أن يفتح طلبًا ثانيًا. ويُتخذ القرار بالطريقة نفسها التي تُتخذ بها كل قرارات النشر في Nessie: يتخذه شخص، بشأن ذلك المستند، في اللحظة التي يوجد فيها.
لا توجد عمدًا أي نطاق للنشر. كان هناك واحد، وهو علامة تُوضع عند الاقتران تقول إن هذا الوكيل يجوز له النشر، وقد أُلغي. فقد كان يقرر، مرة واحدة ولمدة تسعين يومًا، مسألة يسألها المنتج في كل مستند في أي مكان آخر، وكان يقررها قبل أن يوجد المستند، فلم يكن الشخص الذي يضع العلامة يعرف ما الذي يوافق على نشره. ويحتاج nessie_doc_publish إلى documents_write، لأن الطلب ليس بلا ثمن، فهو يقرأ الصفحة ويضع قرارًا أمام أحدهم، لكن ذلك النطاق لا يمنح أي شيء بشأن النشر.
يُسجَّل هويتان على الطلب، والفرق بينهما حاسم. الطالب هو بيانات الاعتماد، وليس الإنسان الذي تعمل نيابةً عنه. المُوافِق المطلوب هو ذلك الإنسان، ولا يستطيع الرد غيره. ولو سُمّي الشخص طالبًا للطلب، لاستُبعد الشخص الوحيد المخوّل بالقرار بسبب القاعدة التي تمنع أي أحد من الموافقة على طلبه بنفسه.
رؤية ما تم اقترانه وإلغاؤه
تُعرض وكلاء الشخص المقترنون في /settings/security، مع تسمية وزر إلغاء لكل منهم. ويرى المالك أو مسؤول المؤسسة كل بيانات الاعتماد في المؤسسة في /admin/security?tab=programs: اسم كل منها، وما الذي يحق له فعله، وهل هو فعّال، وباسم أي حساب يعمل، ويستطيع إلغاء أي منها. وتبقى القائمة الشخصية خاصة بصاحبها، فقائمة بالبيانات الفعالة هي قائمة بنقاط ارتكاز، لا قراءة عامة.
الكتابات التي تُجرى عبر بيانات الاعتماد تُنسب إلى الإنسان الذي استعارها، وتحمل معرّف بيانات الاعتماد في بيانات سجل التدقيق، فيستطيع السجل أن يميّز تعديل الشخص لنفسه عن تعديل قام به وكيله نيابةً عنه.
ما هو غير متاح بعد
نذكره صراحة، لأن الفجوة بين قدرات بروتوكول معين وقدرات خادم بعينه هي المكان الذي تكذب فيه الوثائق عادةً:
- الدردشة والقنوات والعمليات وإدارة الوكلاء غير متاحة عبر MCP.
- يُعدّ البرنامج النشرة البريدية ويرسلها شخص: لا شيء يرسل حملة أو يجدولها أو يحذفها، ويُكتب البريد نفسه في المصمّم.
- ربط جهات الاتصال ودمجها، وتغييرات مخطط CRM، والاستيراد، وإعداد القنوات، تبقى مع شخص يعمل في المتصفح.
- مفتاح الربط إعداد على مستوى المؤسسة. ولا يستطيع فريق أو شخص ضبط تجاوزات خاصة به على مستوى الفريق أو على المستوى الشخصي اليوم.