دليل عملي: بناء أوّل خادم MCP بلغة Python في أقلّ من 30 دقيقة
دليل عملي خطوة بخطوة لبناء أوّل خادم MCP بلغة Python باستخدام FastMCP: من تهيئة البيئة إلى الأدوات والموارد واختبار المعاينة والتوصيل بـ Claude Desktop، بكود حقيقي.
تخيّل أنك تريد أن يقرأ Claude أو Cursor ملفّاتك المحلّية، أو يستعلم من قاعدة بياناتك، أو ينفّذ دالّة في نظامك — لا عبر لصق النصّ يدويًّا، بل بأن «يكتشف» النموذج أدواتك ويستدعيها وحده وقت الحاجة. هذا بالضبط ما يتيحه بروتوكول سياق النموذج (Model Context Protocol)، أو MCP، الذي أطلقته Anthropic أواخر 2024 وتحوّل خلال أشهر إلى معيار فعلي لربط وكلاء الذكاء الاصطناعي بالعالم الحقيقي. وفي هذا الدليل سنبني أوّل خادم MCP بلغة Python في أقلّ من نصف ساعة، خطوةً بخطوة، بكود حقيقي.
ما خادم MCP أصلًا؟
قبل الكود، لنرسّخ الصورة الذهنية الصحيحة. خادم MCP برنامج صغير «يعرض» (Exposes) ثلاثة أنواع من القدرات لأيّ عميل ذكاء اصطناعي متوافق: الأدوات (Tools) وهي دوالّ ينفّذها النموذج كأنها نقاط POST، والموارد (Resources) وهي بيانات للقراءة فقط أشبه بنقاط GET، والقوالب (Prompts) وهي صياغات جاهزة لمهامّ متكرّرة. والاتجاه مهمّ: أنت لا تستدعي النموذج من داخل الخادم؛ بل العميل (مثل Claude Desktop) هو من يتّصل بخادمك، يسأله «ما الأدوات لديك؟»، ثم يستدعيها حين يقرّر النموذج أنها مفيدة. خادمك طرف سلبيّ ينتظر ويستجيب، لا أكثر.
لماذا FastMCP؟
يمكنك التعامل مع بروتوكول MCP عبر حزمة Anthropic الرسمية مباشرةً، لكن ذلك يعني كتابة مخطّطات الأدوات يدويًّا والتعامل مع تفاصيل JSON-RPC. هنا يأتي إطار FastMCP، الذي صار يشغّل نحو 70% من خوادم MCP بكل اللغات، ويُختصر معه كل هذا التعقيد في مُزخرِف (Decorator) واحد. تكتب دالّة Python عادية بتلميحات أنواع (Type Hints) ووصف، تضع فوقها سطرًا واحدًا، فيولّد FastMCP المخطّط ويتحقّق من المدخلات ويوصّل الوصف للنموذج تلقائيًّا. ملاحظة: FastMCP 1.0 مدمج أصلًا في الحزمة الرسمية، بينما تتطوّر النسخ الأحدث (3.x في 2026) كمشروع مستقلّ بميزات إضافية.
الخطوة 1: تهيئة البيئة
سنستخدم أداة uv الحديثة لإدارة المشروع، فهي أسرع وأنظف. أنشئ المشروع وفعّل البيئة وثبّت الحزمة:
uv init weather-mcp
cd weather-mcp
uv venv
source .venv/bin/activate
uv add "mcp[cli]" httpxالحزمة mcp هي SDK الرسمي (وتتضمّن FastMCP)، وhttpx لاستدعاءات الشبكة، وإضافة cli تجلب أداة المعاينة (Inspector) للاختبار. أنشئ ملفًّا باسم server.py وابدأ.
الخطوة 2: أوّل أداة
إليك خادمًا كاملًا يعمل، بأداة واحدة تجمع رقمين. لاحظ بساطة المُزخرِف:
from mcp.server.fastmcp import FastMCP
# إنشاء الخادم
mcp = FastMCP("weather")
@mcp.tool()
def add(a: int, b: int) -> int:
"""تجمع رقمين صحيحين وتعيد الناتج."""
return a + b
if __name__ == "__main__":
mcp.run()هذا كل شيء لخادم يعمل فعلًا. الوصف بين علامتي التنصيص الثلاثية (Docstring) ليس تجميلًا؛ النموذج يقرؤه ليعرف متى يستدعي الأداة، فاكتبه بعناية. وتلميحات الأنواع (int) تتحوّل تلقائيًّا إلى قواعد تحقّق من المدخلات.
الخطوة 3: أداة حقيقية تستدعي واجهة خارجية
الجمع تمرين تعليمي؛ لنبنِ أداة مفيدة تجلب الطقس من واجهة برمجية حقيقية. لاحظ استخدام async للعمليات الشبكية، ومعالجة الأخطاء كي لا ينهار الخادم عند فشل الطلب:
import httpx
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("weather")
NWS_API = "https://api.weather.gov"
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""تجلب توقّعات الطقس لإحداثيات معيّنة (خطّ العرض والطول)."""
url = f"{NWS_API}/points/{latitude},{longitude}"
async with httpx.AsyncClient() as client:
try:
resp = await client.get(url, timeout=10.0)
resp.raise_for_status()
data = resp.json()
return f"بيانات المنطقة: {data['properties']['forecast']}"
except Exception as e:
return f"تعذّر جلب الطقس: {e}"
if __name__ == "__main__":
mcp.run()مبدأ مهمّ: غلّف كل استدعاء خارجيّ بمعالجة أخطاء تعيد رسالة واضحة بدل أن ترمي استثناءً يُسقط الخادم بأكمله. النموذج يتعامل مع الرسالة كنتيجة، فيخبر المستخدم بلطف أنّ العملية فشلت.
الخطوة 4: إضافة مورد (Resource)
الموارد للقراءة فقط، وتُعرَّف بنمط رابط (URI). مثال يعرض إعدادات التطبيق:
import json
@mcp.resource("config://app/settings")
def app_settings() -> str:
"""إعدادات التطبيق الحالية بصيغة JSON."""
return json.dumps({
"version": "1.0.0",
"language": "ar",
"max_results": 50,
})يمكن أيضًا جعل المورد ديناميكيًّا بمعاملات داخل الرابط، مثل user://{user_id}/profile، فيستقبل user_id ويعيد بياناته. الفرق الجوهري عن الأداة: المورد يحمّل معلومة في سياق النموذج، ولا يُحدِث أثرًا جانبيًّا.
الخطوة 5: اختبار الخادم قبل التوصيل
لا توصّل خادمًا لم تختبره. أداة المعاينة (MCP Inspector) تمنحك واجهة ويب لتجربة أدواتك ومواردك يدويًّا. شغّلها بأمر واحد:
uv run mcp dev server.pyستفتح واجهة محلّية ترى فيها قائمة أدواتك، وتستطيع استدعاء كلٍّ منها بمدخلات تجريبية ومراقبة الاستجابة. هذه الخطوة تكشف معظم الأخطاء قبل أن تصل إلى العميل الفعليّ.
الخطوة 6: التوصيل بـ Claude Desktop
لربط خادمك بـ Claude Desktop، حرّر ملفّ الإعداد الخاصّ به وأضف خادمك تحت مفتاح mcpServers، مع المسار المطلق لمجلّد مشروعك:
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/weather-mcp",
"run",
"server.py"
]
}
}
}احصل على المسار المطلق بأمر pwd، وعلى مسار uv بأمر which uv إن لزم. أعد تشغيل Claude Desktop، وستظهر أدواتك جاهزة للاستدعاء.
تحذير شائع يُسقط الخوادم
إن كان خادمك يعمل عبر النقل القياسي (stdio)، فلا تطبع أبدًا إلى المخرج القياسي (stdout) عبر print العادية، لأن ذلك يفسد رسائل JSON-RPC ويعطّل الخادم بصمت. استخدم التسجيل إلى المخرج القياسي للأخطاء (stderr) بدلًا منه. هذا الخطأ من أكثر ما يحيّر المبتدئين، لأن الخادم «يعمل» ظاهريًّا لكنه يفشل في التواصل.
إلى أين بعد ذلك؟
بنيت الآن خادمًا يعرض أدوات وموارد، اختبرته، ووصّلته بعميل حقيقي — كل ذلك في عشرات الأسطر. الخطوة التالية الطبيعية هي نقله من نموذج محلّي إلى خدمة عبر النقل بـ Streamable HTTP حين يحتاجه أكثر من وكيل، وإضافة مصادقة OAuth إن تعاملت مع بيانات حسّاسة. لكن النصيحة العملية الأهمّ: لا تُفرط في البناء من اليوم الأول. ابدأ بأداة واحدة محكمة عبر stdio، تحقّق منها في المعاينة، ثمّ رقِّها إلى خدمة مصادَق عليها فقط حين تحتاجها فعلًا. أغلب الفرق تبني أكثر مما تحتاج في خادمها الأول.
هل وجدت هذا المقال مفيدًا؟