بناء خادم MCP ببايثون
درس 2 من 2
2بناء خادم MCP ببايثون
الصورة الكبيرةفي الدرس السابق ربطت الأدوات بوكيلك يدويًا. MCP يجعل الربط معيارًا: خادمك يعلن «هذه أدواتي»، وأي تطبيق يدعم البروتوكول يكتشفها ويستدعيها، مثل منفذ USB للذكاء الاصطناعي.
ماذا تشاهد في الرسم: محادثة عميل وخادم MCP: مصافحة، ثم اكتشاف الأدوات، ثم الاستدعاء. كلها رسائل JSON-RPC.
خارطة هذا الجزء
المفاهيم بالترتيب، اضغط أيًّا منها للقفز إليه:
طريقان إلى نفس الفكرة
قبل USB كان لكل جهاز سلك خاص. اليوم أي فأرة تعمل في أي حاسوب. MCP يفعل هذا للأدوات: تبني «جهازك» (خادم يعرف قائمة المقهى مثلًا) مرة، فيعمل في Claude Desktop وفي المحررات وفي أي وكيل يدعم المعيار.
MCP مبني على JSON-RPC 2.0 عبر stdio (عملية محلية) أو HTTP قابل للبث (خادم بعيد). الخادم يعرض ثلاثة أنواع: tools (دوال بمخطط مدخلات يستدعيها النموذج)، resources (بيانات للقراءة بمعرّف URI)، prompts (قوالب جاهزة يختارها المستخدم). دورة الحياة: initialize لتبادل الإمكانات، ثم tools/list وtools/call. حزمة mcp الرسمية فيها الصنف MCPServer الذي يولّد المخطط من تلميحات الأنواع ونص التوثيق. اختبر بـ MCP Inspector قبل الربط بعميل. الأمان: الخادم يعمل بصلاحياتك، فقيّد المسارات والأفعال.
قبل أن تبدأ
🤖بناء وكيل
الدرس السابق: حلقة الأدوات.
🧾JSON
تقرأ وتكتب JSON.
الفكرة الجوهرية
1الرسائل تحت الغطاء
قبل المكتبة، انظر للبروتوكول نفسه. هذا خادم مصغّر يعالج ثلاث رسائل JSON-RPC كما يرسلها العميل:
import json
MENU = {"latte": 14, "mocha": 16}
TOOLS = [{
"name": "get_price",
"description": "Price in riyals of one café menu item.",
"inputSchema": {"type": "object", "properties": {"item": {"type": "string"}},
"required": ["item"]},
}]
def handle(request):
method, rid = request["method"], request["id"]
if method == "initialize":
result = {"protocolVersion": "2025-06-18", "capabilities": {"tools": {}},
"serverInfo": {"name": "cafe", "version": "1.0"}}
elif method == "tools/list":
result = {"tools": TOOLS}
elif method == "tools/call":
item = request["params"]["arguments"]["item"]
text = f"{item}: {MENU[item]} SAR" if item in MENU else f"no item {item}"
result = {"content": [{"type": "text", "text": text}], "isError": item not in MENU}
else:
return {"jsonrpc": "2.0", "id": rid, "error": {"code": -32601, "message": "unknown method"}}
return {"jsonrpc": "2.0", "id": rid, "result": result}
for req in [{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}},
{"jsonrpc": "2.0", "id": 2, "method": "tools/list"},
{"jsonrpc": "2.0", "id": 3, "method": "tools/call",
"params": {"name": "get_price", "arguments": {"item": "mocha"}}}]:
print(json.dumps(handle(req))[:110])2MCPServer: الخادم الحقيقي
المكتبة الرسمية تكتب كل ما سبق عنك. تلميحات الأنواع تصبح مخطط المدخلات، ونص التوثيق يصبح الوصف:
from mcp.server import MCPServer
mcp = MCPServer("cafe")
MENU = {"latte": 14, "mocha": 16, "tea": 6}
@mcp.tool()
def get_price(item: str) -> str:
"""Price in riyals of one café menu item, e.g. 'latte'."""
if item not in MENU:
return f"No item called {item}. Available: {', '.join(MENU)}"
return f"{item}: {MENU[item]} SAR"
@mcp.resource("menu://today")
def today_menu() -> str:
"""Today's full menu as plain text."""
return "\n".join(f"{k}: {v} SAR" for k, v in MENU.items())
# run it under the inspector: uv run mcp dev server.py
# or over HTTP: uv run mcp run server.py --transport streamable-http3الاختبار والربط
شغّل uv run mcp dev server.py لترى الأدوات وتجربها بلا نموذج. ثم أضف الخادم لإعدادات العميل (مثلًا ملف إعداد Claude Desktop) بأمر التشغيل نفسه.
read_file(path) بلا قيود تعطي النموذج كل ملفاتك، بما فيها المفاتيح. قيّد المسار بمجلد محدد وارفض ...مثال محلول
المسألة: النموذج لا يستخدم أداتك أبدًا. التحليل: الوصف «gets data» غامض، واسمها tool1. الحل: اسم search_orders ووصف «Search the café's orders by customer phone or date. Returns up to 20 orders, newest first.». بعد التعديل يختارها النموذج في الأسئلة الصحيحة.
خرافة مقابل حقيقة
| الخرافة | الحقيقة |
|---|---|
| MCP خاص بشركة واحدة. | معيار مفتوح بمواصفة منشورة وتطبيقات عديدة تدعمه. |
| الخادم يحتاج إنترنت. | خادم stdio يعمل محليًا كعملية على جهازك. |
أين تقابله في العمل
🗂️الوصول لبياناتك
قاعدة بيانات أو ملفات أو نظام داخلي متاح للنموذج بأمان.
🔁إعادة الاستخدام
نفس الخادم في المحرّر وتطبيق المحادثة والوكلاء.
اختبر فهمك
على أي بروتوكول رسائل يقوم MCP؟
كل رسالة فيها jsonrpc وid وmethod وparams.
ما الفرق بين tool وresource؟
الأدوات تفعل، والموارد تُقرأ بمعرّف URI.
من أين يأخذ MCPServer وصف الأداة؟
ونوع المدخلات من تلميحات الأنواع.
بطاقات مراجعة سريعة
تحقق من فهمك
لماذا نبني خادم MCP بدل ربط الأدوات بالوكيل مباشرة؟
ليعمل نفس الخادم مع أي عميل يدعم المعيار دون إعادة كتابة.
ماذا يحدث في initialize؟
يتبادل العميل والخادم الإصدار والإمكانات قبل أي استدعاء.
كيف تحمي أداة قراءة ملفات؟
بحصرها في مجلد واحد ورفض المسارات الخارجة عنه.
مصادر هذا الدرس
مرتّبة بالنوع. ابدأ بالتوثيق الرسمي إذا تبي المرجع الدقيق، وبالمقال أو الفيديو إذا تبي الشرح أولًا.
خلّصت الدرس؟
سجّل الدخول ليُحفظ تقدّمك.