مقدمة
أصبح بروتوكول Model Context Protocol (MCP) المعيارَ الرئيسي الذي يربط المساعدات الذكية بالأدوات الخارجية ومصادر البيانات والخدمات المختلفة. وقد باتت مكتبة FastMCP — في إصدارها الثالث — تشغّل نحو 70% من خوادم MCP في بيئات الإنتاج حول العالم.
إذا كنت تريد كشف قاعدة بيانات أو API داخلي أو نظام ملفات لأي من Claude Desktop أو Claude Code أو Cursor أو Cline، فإن FastMCP هي أسرع طريق. واجهتها القائمة على المزخرِفات (decorators) مشابهة لـ Flask وFastAPI، مما يتيح لمطوري Python تشغيل الخادم في دقائق.
في هذا الدليل، ستبني خادم MCP متكامل يضم الأدوات والموارد والقوالب وحقن التبعيات والمصادقة بالرمز المميز والنشر عبر Docker.
المتطلبات المسبقة
- Python 3.10 أو أعلى (يُنصح بـ 3.12 للأداء الأمثل)
- مدير الحزم UV (أو pip)
- إصدار حديث من Claude Desktop أو Cursor أو Cline للاختبار المحلي
- إلمام أساسي بـ Python غير المتزامن (async)
ما ستبنيه
خادم ذكاء المشاريع — خادم MCP يمنح أي مساعد ذكي صلاحية الوصول إلى:
- أداة
search_projectsللبحث في قاعدة بيانات مشاريع داخلية - أداة
get_project_statusلاسترجاع بيانات المشروع الحية - مورد
projects://listلعرض لقطة ثابتة من جميع المشاريع - قالب
status_reportلإرشاد المساعد على صياغة ملخصات - نقل HTTP مع مصادقة Bearer Token للبيئة الإنتاجية
الخطوة 1: إعداد المشروع
أنشئ مشروعاً جديداً مع UV وثبّت FastMCP:
uv init project-mcp-server
cd project-mcp-server
uv add fastmcpأو باستخدام pip:
mkdir project-mcp-server && cd project-mcp-server
python -m venv .venv && source .venv/bin/activate
pip install fastmcpتحقق من التثبيت:
fastmcp version
# FastMCP 3.2.4أنشئ ملف الخادم الرئيسي:
touch server.pyالخطوة 2: تهيئة الخادم
افتح server.py وأعدّ نسخة FastMCP:
from fastmcp import FastMCP, Context
mcp = FastMCP(
name="Project Intelligence Server",
instructions=(
"لديك صلاحية الوصول إلى قاعدة بيانات المشاريع. "
"استخدم search_projects للبحث بالكلمات المفتاحية، "
"وget_project_status لاسترجاع البيانات الحية."
),
)يُرسَل الوصف instructions للمساعد الذكي في بداية كل جلسة ليعرف كيف يستخدم قدرات خادمك.
الخطوة 3: تعريف الأدوات
الأدوات هي أكثر عناصر MCP استخداماً — وهي دوال قابلة للاستدعاء يطلبها المساعد الذكي للتصرف أو استرجاع البيانات المحسوبة.
يستنتج FastMCP مخطط المدخلات تلقائياً من تلميحات النوع والتوثيق:
PROJECTS = [
{"id": "p1", "name": "منصة نقطة", "status": "active", "lang": "TypeScript"},
{"id": "p2", "name": "API الفواتير", "status": "active", "lang": "Python"},
{"id": "p3", "name": "تطبيق الجوال", "status": "paused", "lang": "React Native"},
{"id": "p4", "name": "مسار البيانات", "status": "archived", "lang": "Python"},
]
@mcp.tool
def search_projects(keyword: str, status: str = "all") -> list[dict]:
"""
البحث في المشاريع بكلمة مفتاحية وفلتر اختياري للحالة.
Args:
keyword: مصطلح البحث يُطابق اسم المشروع واللغة.
status: تصفية حسب الحالة: active أو paused أو archived أو all.
"""
results = PROJECTS
if status != "all":
results = [p for p in results if p["status"] == status]
keyword = keyword.lower()
return [p for p in results if keyword in p["name"].lower() or keyword in p["lang"].lower()]
@mcp.tool
async def get_project_status(project_id: str, ctx: Context) -> dict:
"""
استرجاع الحالة التفصيلية لمشروع محدد برقمه التعريفي.
Args:
project_id: المعرّف الفريد للمشروع (مثلاً p1 أو p2).
"""
await ctx.info(f"جارٍ جلب بيانات المشروع {project_id}")
project = next((p for p in PROJECTS if p["id"] == project_id), None)
if project is None:
raise ValueError(f"المشروع '{project_id}' غير موجود")
return {
**project,
"last_commit": "2026-06-24",
"open_issues": 3,
"coverage": "87%",
}ملاحظات أساسية:
- الدوال المتزامنة مناسبة للعمليات الحسابية؛
async defضروري لانتظار I/O. - المعامل
ctx: Contextيُحقن تلقائياً ولا يمرره المساعد يدوياً. ctx.info()وctx.debug()وctx.warning()تُصدر رسائل سجل يعرضها العميل.- رمي استثناء Python عادي يظهر رسالة خطأ واضحة للمساعد.
الخطوة 4: تعريف الموارد
الموارد تكشف بيانات للقراءة لا للحساب، وتُعنوَن بـ URI. مثالية للإعدادات والتوثيق والبيانات الثابتة:
import json
@mcp.resource("projects://list")
def list_all_projects() -> str:
"""لقطة من جميع المشاريع في النظام."""
return json.dumps(PROJECTS, ensure_ascii=False, indent=2)
@mcp.resource("projects://{project_id}/details")
def project_details(project_id: str) -> str:
"""عرض تفصيلي لمشروع واحد عبر معرّفه."""
project = next((p for p in PROJECTS if p["id"] == project_id), None)
if project is None:
return json.dumps({"error": f"المشروع {project_id} غير موجود"}, ensure_ascii=False)
return json.dumps(project, ensure_ascii=False, indent=2)قوالب URI التي تحتوي على {placeholder} تُعيَّن تلقائياً لمعاملات الدالة.
الخطوة 5: تعريف قوالب المطالبات
القوالب هي تعليمات معاد استخدامها لتوجيه تفكير المساعد، وتظهر في واجهات العملاء كقوالب قابلة للاختيار:
@mcp.prompt
def status_report(project_id: str, audience: str = "engineering") -> str:
"""
إنشاء قالب تقرير حالة لمشروع محدد وجمهور مستهدف.
Args:
project_id: معرّف المشروع المستهدف.
audience: الجمهور المستهدف: engineering أو management أو client.
"""
tone = {
"engineering": "تقني، يركّز على المقاييس والعوائق",
"management": "موجز، يركّز على الجدول الزمني والمخاطر",
"client": "غير تقني، إيجابي، يركّز على القيمة المُسلَّمة",
}.get(audience, "متوازن")
return (
f"باستخدام بيانات المشروع '{project_id}'، اكتب تقرير حالة {tone}. "
"اشمل: الحالة الحالية، التقدم الأخير، المشكلات المفتوحة، والمعالم القادمة. "
"لا يتجاوز 300 كلمة."
)الخطوة 6: حقن التبعيات بـ Depends
عندما تحتاج عدة أدوات لمورد مشترك — اتصال بقاعدة بيانات، عميل HTTP، ذاكرة تخزين مؤقت — استخدم Depends لتهيئته مرة واحدة لكل طلب:
from contextlib import asynccontextmanager
from fastmcp.dependencies import Depends
async def get_db():
"""محاكاة عميل قاعدة البيانات. في الإنتاج، استبدله باتصال حقيقي."""
class FakeDB:
async def query(self, sql: str) -> list:
return [{"result": f"نُفِّذ: {sql}"}]
db = FakeDB()
yield db
@mcp.tool
async def run_query(sql: str, db=Depends(get_db)) -> list:
"""
تنفيذ استعلام SQL للقراءة فقط على قاعدة بيانات المشاريع.
Args:
sql: جملة SELECT للتنفيذ.
"""
return await db.query(sql)الخطوة 7: إدارة الحالة على مستوى الخادم
للحالة التي يجب أن تبقى طوال عمر الخادم (مجموعة اتصالات، نموذج مُحمَّل)، استخدم واجهة lifespan:
from fastmcp.server.lifespan import lifespan
@lifespan
async def app_lifespan(server):
"""تهيئة وتنظيف الموارد على مستوى الخادم."""
print("الخادم يبدأ — جارٍ بناء فهرس المشاريع...")
index = {p["id"]: p for p in PROJECTS}
yield {"index": index}
print("الخادم يُغلَق — تحرير الفهرس.")
mcp_with_lifespan = FastMCP(
name="Project Intelligence Server",
lifespan=app_lifespan,
)
@mcp_with_lifespan.tool
def fast_lookup(project_id: str, ctx: Context) -> dict:
"""بحث فوري باستخدام الفهرس المُبنى مسبقاً."""
index = ctx.lifespan_context["index"]
return index.get(project_id, {"error": "غير موجود"})الخطوة 8: الاختبار بـ MCP Inspector
يأتي FastMCP مع دعم مدمج لأداة MCP Inspector — واجهة اختبار تعمل في المتصفح:
fastmcp dev inspector server.pyتُطلق أمراً خادماً محلياً مع إعادة تحميل تلقائية وتفتح Inspector على http://localhost:6274. يمكنك:
- استعراض الأدوات والموارد والقوالب المسجَّلة
- استدعاء الأدوات مباشرة بمعاملات مخصصة
- فحص دورة الطلب والاستجابة الكاملة
الخطوة 9: الربط بعملاء الذكاء الاصطناعي
Claude Desktop
أضف خادمك إلى ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) أو %APPDATA%\Claude\claude_desktop_config.json (Windows):
{
"mcpServers": {
"project-intelligence": {
"command": "fastmcp",
"args": ["run", "/المسار/الكامل/إلى/server.py"]
}
}
}أعد تشغيل Claude Desktop. ستظهر أدواتك في قائمة الأدوات المتاحة.
Claude Code
claude mcp add project-intelligence fastmcp run /المسار/الكامل/إلى/server.pyCursor / Cline
في إعدادات Cursor تحت MCP Servers، أضف:
{
"name": "project-intelligence",
"command": "fastmcp run /المسار/الكامل/إلى/server.py"
}الخطوة 10: نقل HTTP مع المصادقة
للنشر البعيد أو الخوادم المشتركة بين الفريق، انتقل إلى نقل HTTP مع مصادقة Bearer Token:
from fastmcp.server.auth import StaticTokenVerifier
import os
auth = StaticTokenVerifier(
tokens={
os.environ["MCP_TOKEN_PROD"]: {"client_id": "prod", "scopes": ["read", "write"]},
os.environ["MCP_TOKEN_READONLY"]: {"client_id": "viewer", "scopes": ["read"]},
},
required_scopes=["read"],
)
secured_mcp = FastMCP(
name="Project Intelligence Server",
auth=auth,
)
if __name__ == "__main__":
secured_mcp.run(transport="http", host="0.0.0.0", port=8000)شغّل الخادم المؤمَّن:
MCP_TOKEN_PROD=your-secret-token \
MCP_TOKEN_READONLY=your-readonly-token \
python server.pyالخطوة 11: النشر عبر Docker
أنشئ Dockerfile:
FROM python:3.12-slim
WORKDIR /app
RUN pip install uv
COPY pyproject.toml uv.lock* ./
RUN uv sync --frozen --no-dev
COPY server.py .
EXPOSE 8000
CMD ["uv", "run", "fastmcp", "run", "server.py", \
"--transport", "http", "--host", "0.0.0.0", "--port", "8000"]ابنِ الصورة وشغّلها:
docker build -t project-mcp-server .
docker run -p 8000:8000 \
-e MCP_TOKEN_PROD=your-secret-token \
project-mcp-serverالخطوة 12: التتبع بـ OpenTelemetry
يتضمن FastMCP 3.x دعماً مدمجاً لـ OpenTelemetry:
from fastmcp.telemetry import get_tracer
@mcp.tool
async def search_projects_traced(keyword: str, ctx: Context) -> list[dict]:
"""بحث في المشاريع مع تتبع موزّع."""
tracer = get_tracer()
with tracer.start_as_current_span("search.filter") as span:
span.set_attribute("search.keyword", keyword)
results = [p for p in PROJECTS if keyword.lower() in p["name"].lower()]
span.set_attribute("search.result_count", len(results))
await ctx.info(f"وُجد {len(results)} مشروع للكلمة '{keyword}'")
return resultsأرسل التتبعات لـ Grafana أو Jaeger أو Datadog عبر متغيرات البيئة:
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317 \
OTEL_SERVICE_NAME=project-mcp-server \
python server.pyاستكشاف الأخطاء وإصلاحها
الأداة لا تظهر في Claude Desktop
- تأكد أن المسار في
claude_desktop_config.jsonمطلق لا نسبي. - تحقق من وجود
fastmcpفي PATH المستخدم من Claude Desktop. - أعد تشغيل Claude Desktop بالكامل بعد التعديل.
TypeError: cannot unpack non-iterable NoneType object
هذا يعني عادةً أن مولّد التبعية أعاد None بدلاً من استخدام yield. تأكد من استخدام yield في دالة Depends.
أخطاء المصادقة على نقل HTTP
- تحقق من وجود ترويسة
Authorization: Bearer <token>بالكتابة الصحيحة. - راجع أن
required_scopesتتطابق مع النطاقات المعيَّنة للرمز فيStaticTokenVerifier.
الخطوات التالية
- استكشف تكامل FastMCP مع OpenAPI لتوليد خادم MCP تلقائياً من مواصفة REST موجودة.
- أضف تحديد المعدل باستخدام عداد Redis داخل تبعية
Depends. - اربط خادمك بـ LangGraph أو PydanticAI عبر
FastMCPToolsetلسير عمل متعددة الوكلاء. - راجع درس بناء خادم MCP بـ TypeScript للنسخة المكافئة.
الخلاصة
يمنح FastMCP 3.x مطوري Python مساراً نظيفاً وجاهزاً للإنتاج نحو منظومة MCP. بمزخرفات الأدوات والموارد والقوالب، وحقن التبعيات، ومصادقة Bearer Token، ونقل HTTP جاهز لـ Docker، يمكنك إطلاق خادم MCP حقيقي في غضون ساعات. يتصل الخادم نفسه بـ Claude Desktop وClaude Code وCursor وCline دون أي كود خاص بالعميل — تنفيذ واحد لكل المساعدات الذكية.