عندما تطلب من مساعد ذكاء صنعي أن يلخص ملفاً في مستنداتك، أو يقرأ خطأ من سجلات قاعدة بيانات، أو ينشئ مهمة في أداة إدارة المشاريع. كل طلب من هذه الطلبات يعني أن التطبيق يجب أن يكون ملماً بكيفية التحدث مع تلك الخدمة تحديداً: ما عنوانها، وكيف يصادق لديها، وما صيغة البيانات التي تفهمها. وإن كررت هذا مع كل تطبيق ذكاء صنعي وكل خدمة تستخدمها، ينتهي الأمر بعشرات التكاملات المكررة، يبني كل فريق نسخته الخاصة منها ويصونها وحده.
MCP اختصار Model Context Protocol، أي بروتوكول سياق النموذج. هو معيار مفتوح قدمته Anthropic في نوفمبر 2024، ويحدد طريقة موحدة تربط تطبيقات الذكاء الصنعي بالأنظمة الخارجية: مصادر البيانات مثل الملفات وقواعد البيانات، والأدوات مثل محركات البحث، وسير العمل مثل القوالب الجاهزة. التشبيه الرسمي الشائع هو منفذ USB-C: كما يوفر USB-C طريقة قياسية لوصل الأجهزة الإلكترونية، يوفر MCP طريقة قياسية لوصل تطبيقات الذكاء الصنعي بالأنظمة الخارجية. واليوم تدعمه تطبيقات مثل Claude وChatGPT وVS Code وCursor، وغيرها كثير.
| العربية | English |
|---|---|
| بروتوكول سياق النموذج | Model Context Protocol (MCP) |
| المضيف | Host |
| العميل | Client |
| المخدم | Server |
| أداة | Tool |
| مورد | Resource |
| قالب أوامر | Prompt |
| طلب توليد من النموذج (موقوف) | Sampling |
| الجذور (موقوفة) | Roots |
| طلب معلومات من المستخدم | Elicitation |
| قناة النقل | Transport |
| امتداد | Extension |
المشكلة الأساسية
لنفترض أن لدينا تطبيقين للذكاء الصنعي وخدمتين، مثل GitHub وقاعدة بيانات، ونريد ربط التطبيقين بالخدمتين. بدون معيار مشترك يحتاج كل تطبيق إلى تكامل خاص مع كل خدمة، فيصبح لدينا أربعة تكاملات مختلفة. وإن أضفنا تطبيقاً ثالثاً أو خدمة ثالثة يرتفع العدد سريعاً، والصيغة العامة هي M×N، حيث M عدد التطبيقات وN عدد الخدمات.
flowchart TB
A1["تطبيق ذكاء صنعي أول"] --- B1["GitHub"]
A1 --- B2["قاعدة البيانات"]
A2["تطبيق ذكاء صنعي ثاني"] --- B1
A2 --- B2
مع MCP يبني كل تطبيق تكاملاً واحداً مع البروتوكول، وتبني كل خدمة تكاملاً واحداً أيضاً، فيصبح العدد M+N بدل M×N. وتظهر الفائدة الحقيقية كلما كبرت المنظومة: المخدم الذي تكتبه مرة واحدة يعمل مع كل مضيف يدعم البروتوكول، والتطبيق الذي تبنيه يستفيد من كل المخدمات الجاهزة التي ينشرها الآخرون.
flowchart TB
A3["تطبيق ذكاء صنعي أول"] --- P["بروتوكول MCP"]
A4["تطبيق ذكاء صنعي ثاني"] --- P
P --- B3["GitHub"]
P --- B4["قاعدة البيانات"]
كيف يعمل؟
يعتمد البروتوكول على ثلاثة أدوار:
- المضيف (Host): تطبيق الذكاء الصنعي نفسه، مثل Claude Desktop أو VS Code. هو الذي يدير النموذج اللغوي ويبدأ الاتصالات ويطلب موافقة المستخدم قبل الإجراءات.
- العميل (Client): مكوّن داخل المضيف يمسك اتصالاً مع مخدم واحد. إن ربط المضيف بثلاثة مخدمات يقوم بتشغيل ثلاثة عملاء، لكل مخدم عميل خاص به.
- المخدم (Server): برنامج يقدم قدرات للمضيف: أدوات تنفذ العمليات، وموارد توفر البيانات، وقوالب جاهزة. قد يكون عملية محلية على جهازك أو خدمة بعيدة على الإنترنت.
flowchart TB
U["المستخدم"] --> Host
subgraph Host["المضيف: تطبيق الذكاء الصنعي"]
L["النموذج اللغوي"]
C1["عميل أول"]
C2["عميل ثان"]
end
S1["مخدم الملفات (محلي)"]
S2["مخدم قاعدة البيانات (بعيد)"]
L <--> C1
L <--> C2
C1 <-->|"stdio"| S1
C2 <-->|"Streamable HTTP"| S2
الرسائل بين العميل والمخدم هي رسائل JSON-RPC 2.0: طلب له معرف، واستجابة تحمل النتيجة أو الخطأ، و إشعار لا ينتظر رداً. أما قناة النقل (Transport) فتحدد كيف تصل هذه الرسائل، والقناتان القياسيتان في المواصفة هما:
- stdio: يشغل العميل المخدم كعملية فرعية محلية، ويتبادل معه رسائل JSON مفصولة بأسطر جديدة عبر قنوات الإدخال والإخراج القياسية. مناسب للمخدمات المحلية ولا يحتاج شبكة.
- Streamable HTTP: ترسل كل رسالة بطلب HTTP POST إلى نقطة واحدة على المخدم، وتصل الاستجابة إما كائن JSON عادياً أو بث SSE خاصاً بالطلب. مناسب للمخدمات البعيدة.
دورة الحياة والمراجعات
تطور البروتوكول عبر مراجعات متتالية، والمراجعة الحالية للمواصفة هي 2026-07-28، وتعتمد نموذجاً بلا حالة: لا توجد جلسة تهيئة، بل يحمل كل طلب في حقول _meta إصدار البروتوكول وقدرات المرسل، ويتعامل المخدم مع كل طلب باستقلالية.
أما المراجعات السابقة حتى 2025-11-25 فتعتمد جلسة اتصال تبدأ بمصافحة initialize، وهو الأسلوب الذي ما تزال غالبية التطبيقات والمخدمات المنتشرة اليوم تعمل به، وهو ما سنستخدمه في المثال العملي.
وتحدد المواصفة قواعد التوافق بين الجيلين: التنفيذ الذي يدعم الجيلين يعمل مع الطرفين، فالعميل المزدوج يجرب النمط الجديد فإن لم يستجب المخدم عاد إلى مصافحة initialize، والمخدم المزدوج يميز النمط من شكل الطلب الأول ويتصرف وفقه.
أما الطرفان الخالصان من جيلين مختلفين فلا يعملان معاً: عميل حديث بحت مع مخدم قديم بحت يفشل، وعميل قديم بحت مع مخدم حديث بحت يفشل أيضاً، إذ لا تملك المواصفة آلية يتم بها تحديث العميل القديم إلى النمط الجديد.
ماذا يقدم المخدم؟
تقدم مخدمات MCP قدراتها عبر ثلاث آليات أساسية:
- الأدوات (Tools): دوال ينفذها النموذج اللغوي: أداة تجمع رقمين، أو تقرأ ملفاً، أو ترسل استعلاماً إلى قاعدة بيانات. تعلن كل أداة عن اسمها ووصفها ومخطط JSON Schema يحدد مدخلاتها، ولهذا يستطيع النموذج اختيار الأداة المناسبة وتمرير معاملات صحيحة لها.
- الموارد (Resources): بيانات وسياقات يعرف كل منها بمعرف URI، مثل محتوى ملف أو سجل في قاعدة بيانات. يقرر التطبيق عادة أي مورد يقرأ ومتى، ويمكن تمرير المحتوى إلى النموذج.
- قوالب الأوامر (Prompts): قوالب رسائل وسير عمل يختارها المستخدم بنفسه، مثل أمر جاهز يراجع النص البرمجي وفق خطوات محددة.
وتساند هذه الآليات قدرتان ملحقتان: الإكمال (Completions) الذي يقترح قيم المعاملات أثناء كتابتها، والسجلات (Logging) التي تبث رسائل تشخيص، وهذه الأخيرة موقوفة في المراجعة الحالية.
وفي الاتجاه المقابل يحتاج المخدم أحياناً إلى معلومات من جهة العميل، لكنه في المراجعة الحالية لا يبتدئ طلبا مستقلا نحوه.
الآلية المعتمدة هي أن يرد المخدم على الطلب الذي وصله باستجابة InputRequiredResult تحمل في inputRequests ما يحتاجه من معلومات، فيجمعها العميل ويعيد إرسال الطلب نفسه مع إجابات المستخدم في inputResponses.
يسمى هذا النمط الطلبات متعددة الجولات (Multi Round-Trip Requests)، وأبرز قدرات العميل في المراجعة الحالية:
- طلب المعلومات من المستخدم (Elicitation): يطلب المخدم من المستخدم، عبر العميل، معلومات إضافية يحتاجها لإكمال الطلب، مثل تأكيد إجراء حساس أو إدخال قيمة ناقصة.
وتضاف إلى ذلك امتدادات اختيارية (Extensions) لا تعمل إلا إذا أعلن الطرفان دعمها في القدرات، ولكل امتداد معرف ضمن نطاق اسمي، مثل io.modelcontextprotocol/tasks. من أبرز هذه الامتدادات: Tasks لتنفيذ العمليات الطويلة بشكل غير متزامن، وSkills over MCP الذي يتيح للمخدمات تقديم مهارات جاهزة، وMCP Apps لعرض عناصر واجهة تفاعلية داخل المحادثة.
مثال عملي
سنشغّل مخدماً مرجعياً رسمياً اسمه server-everything من مستودع المخدمات الرسمي، وهو مخصص لاختبار العملاء لأنه يقدم عينات من كل قدرات البروتوكول.
سنرسل له أربع رسائل عبر stdio: مصافحة التهيئة، وإشعاراً بجاهزية العميل، وطلب قائمة الأدوات، وطلب استدعاء أداة الجمع.
من سطر الأوامر نشغل الأمر التالي:
$ printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"demo-client","version":"1.0.0"}}}' \
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"get-sum","arguments":{"a":2,"b":3}}}' \
| npx -y @modelcontextprotocol/server-everything 2>/dev/null \
| jq .
يكتب printf أربع رسائل JSON مفصولة بأسطر جديدة إلى مدخل المخدم، ونوجه رسائل المخدم الجانبية على stderr إلى العدم حتى لا تختلط بالنتائج، ثم نمرر المخرجات إلى jq لتنسيقها حتى نستطيع قراءتها.
وعندما ينتهي printf ويُغلق مجرى الإدخال، ينهي المخدم نفسه تلقائياً ويعود سطر الأوامر إليك.
الرسالة الأولى هي الأهم، وهي مصافحة initialize: يعرّف العميل بنفسه في clientInfo ويعلن إصدار البروتوكول الذي يتحدثه والقدرات التي يدعمها، ويسأل المخدم عن الشيء نفسه.
الرسالة الثانية إشعار بأن العميل أصبح جاهزاً، والإشعارات لا تحتاج رداً.
الرسالة الثالثة تطلب قائمة الأدوات عبر tools/list، وهي الطريقة التي يكتشف بها العميل ما يقدمه المخدم.
وقد تختلف أسماء الأدوات بين إصدارات المخدم، فالمرجع ما تظهره tools/list.
الرسالة الرابعة تستدعي الأداة get-sum بالمعاملين a=2 وb=3.
وهذه هي الاستجابة التي حصلت عليها، مع حذف محتوى الحقل instructions اختصاراً لأنه نص توجيهي طويل يرسله المخدم للمضيف، ومع إبقاء أداة واحدة فقط من قائمة الأدوات.
المخرجات تيار من كائنات JSON متتالية، كائن لكل رسالة، وهذا ما يقرؤه jq:
{
"method": "notifications/tools/list_changed",
"jsonrpc": "2.0"
}
{
"result": {
"protocolVersion": "2025-11-25",
"capabilities": {
"tools": {
"listChanged": true
},
"prompts": {
"listChanged": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"logging": {},
"tasks": {
"list": {},
"cancel": {},
"requests": {
"tools": {
"call": {}
}
}
},
"completions": {}
},
"serverInfo": {
"name": "mcp-servers/everything",
"title": "Everything Reference Server",
"version": "2.0.0"
},
"instructions": "..."
},
"jsonrpc": "2.0",
"id": 1
}
{
"result": {
"tools": [
"...",
{
"name": "get-sum",
"title": "Get Sum Tool",
"description": "Returns the sum of two numbers",
"inputSchema": {
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"a": {
"type": "number",
"description": "First number"
},
"b": {
"type": "number",
"description": "Second number"
}
},
"required": [
"a",
"b"
]
}
},
"..."
]
},
"jsonrpc": "2.0",
"id": 2
}
{
"result": {
"content": [
{
"type": "text",
"text": "The sum of 2 and 3 is 5."
}
]
},
"jsonrpc": "2.0",
"id": 3
}
لنقرأ ما حدث:
- السطر الأول إشعار
notifications/tools/list_changedأرسله المخدم من دون أن يطلبه أحد، فالإشعارات تسير في الاتجاهين. وصل الإشعار قبل اكتمال المصافحة، ولذا يجوز للعميل تجاهله، أما في مراجعة2026-07-28عبر Streamable HTTP فلا تصل إشعارات التغير تلقائياً، بل عبر بث يفتحه العميل بطلبsubscriptions/listen. - في الرد الأول أكد المخدم أنه يتحدث الإصدار
2025-11-25نفسه، وأعلن قدراته: أدوات وقوالب وموارد مع دعم إشعارات التغير، إضافة إلى السجلات والإكمال والمهام ضمن امتداد Tasks، وعرف بنفسه فيserverInfo. - في الرد الثاني ظهرت قائمة الأدوات: كل أداة باسمها وعنوانها ووصفها ومخطط
inputSchemaالذي يحدد معاملاتها، وقد أبقينا من القائمة أداةget-sumوحدها وحذفنا البقية اختصاراً. - في الرد الثالث أعادت الأداة
get-sumالنتيجة: مجموع 2 و3 هو 5.
هذه هي الدورة كاملة: تعريف متبادل بالقدرات، ثم اكتشاف الأدوات، ثم استدعاء أداة واستلام النتيجة.
في الاستخدام الحقيقي يؤدي النموذج اللغوي داخل المضيف الجزء الأوسط: يقرأ قائمة الأدوات عبر tools/list ويقرر بنفسه متى يستدعي أي أداة وبأي معاملات.
الأمان والثقة
يمنح MCP قدرات قوية: مخدم يستطيع قراءة ملفاتك أو تنفيذ عمليات نيابة عنك، ونموذج ينفذ ما يصل إليه من بيانات وأوصاف. ولهذا تركز المواصفة على مبادئ صريحة: موافقة المستخدم الواضحة على كل وصول للبيانات وكل عملية، وتحكمه فيما يشارك وما ينفذ، والتعامل مع الأدوات على أنها تنفيذ لشيفرة عشوائية غير معروفة مسبقاً (arbitrary code execution) يستحق الحذر المناسب. ومن ذلك أن المضيف ملزم بالحصول على موافقة المستخدم الصريحة قبل كشف بياناته لأي مخدم، وممنوع من نقل بيانات الموارد إلى جهة أخرى دون موافقة. كما تنص على أن أوصاف الأدوات وغيرها من البيانات القادمة من المخدم تعامل على أنها غير موثوقة ما لم تأت من مخدم تثق به. وفي قناة النقل هامش أمان إضافي: stdio لا يمر بالشبكة أصلاً فهو الأسلم، أما المخدمات المحلية التي تستمع عبر HTTP فهي معرضة لهجمات إعادة ربط DNS (DNS rebinding) على localhost، فإن احتجت إليها فاشترط رمز مصادقة وأبق المخدم محلياً.
متى تستخدم MCP ومتى لا تحتاجه؟
يستخدم MCP عندما:
- تبني تطبيقاً يعتمد على نموذج لغوي وتريد وصله بعدد متزايد من المصادر والأدوات دون بناء كل تكامل من الصفر.
- تملك خدمة أو بيانات وتريد إتاحتها مرة واحدة لكل العملاء الذين يدعمون البروتوكول.
ولا تحتاجه عندما:
- يكون التكامل بين نظامين تملكهما ومستهلك واحد محدد: واجهة برمجية مباشرة أبسط وأخف.
- تكفي طريقة أبسط مثل قراءة ملف أو تصدير بيانات.
القاعدة: تظهر قيمة MCP عندما يوجد كثير من التطبيقات وكثير من الخدمات، أما عند وجود مستهلك واحد ومزود واحد فلا تحتاج إلى بروتوكول وسيط.
مصطلحات ذات صلة
- ما هو LLM؟: النموذج الذي يعمل داخل المضيف ويستهلك نتائج الأدوات والموارد.
- ما هو API؟: MCP لا يحل محل الواجهات البرمجية، بل ينظم اكتشافها واستخدامها، وكثير من المخدمات تلتف حول واجهة برمجية قائمة.
- ما هو RAG؟: تستطيع موارد المخدم أن تكون مسار الاسترجاع الذي يغذي النموذج بالأدلة قبل الإجابة.