Gemini 4 Carbon is now live on CometAPI →

مدونة

مدونة CometAPI

واجهة برمجة تطبيقات واحدة. كل نموذج ذكاء اصطناعي رائد.

تحديثات النماذج، وأدلة واجهة برمجة التطبيقات، والمعايير، والرؤى العملية للبناء بشكل أسرع مع CometAPI.

MCP مقابل استدعاء الدوال: كيفية ربط الأدوات بوكلاء الذكاء الاصطناعي
Guide

MCP مقابل استدعاء الدوال: كيفية ربط الأدوات بوكلاء الذكاء الاصطناعي

- مقارنة موجزة: MCP مقابل Function Calling - البنية والربط: - Function Calling: يربط النموذج مباشرة بمهام/دوال محلية لديك (داخل نفس العملية عادة). مناسب لأدوات قليلة وسريعة الدمج، لكنه يقيّدك بعملية التنفيذ الواحدة ولغة/بيئة محددة. - MCP (Model Context Protocol): بروتوكول عمومي لأدوات وخدمات خارج العملية عبر JSON-RPC (stdio/شبكي). يمكّن فصل الأدوات في خادم مستقل يمكن إعادة استخدامه من أدوات/وكلاء متعددة وبيئات مختلفة، مع توصيف أدوات قياسي واكتشاف/إدارة أفضل على المدى الطويل. - التوسّع والصيانة: - Function Calling: سريع البدء، لكن نمو عدد الأدوات يضاعف صعوبة الحوكمة وإعادة الاستخدام بين تطبيقات/عملاء مختلفين. - MCP: يفرض فصلًا واضحًا بين العميل/الوكيل والخادم/الأدوات، ما يسهل الحوكمة، مراقبة الإصدارات، والاختبار المستقل، وإعادة الاستخدام عبر محررات وواجهات متعددة. - الموثوقية والأمان: - Function Calling: الدالة تعمل ضمن نفس الثقة/الامتيازات التي يعمل بها عميلك. - MCP: يمكن تشغيل الخادم بصلاحيات معزولة، وتطبيق سياسات وصول، وتسجيل، وخنق (throttling) على مستوى الخادم. - الاعتمادية والتشغيل: - Function Calling: لا يتطلب وسيط نقل أو اكتشاف أدوات؛ الاتصال مباشر. - MCP: يتطلب خادم MCP وتشغيله ونقل البيانات عبر stdio/شبكة، لكنه يتيح تشارك الأدوات بين عدة عملاء بسهولة. - افتراضات للكود التالي - سنفترض وجود CometAPI بواجهة REST: - GET {COMET_API_BASE_URL}/orders/{order_id} - مصادقة عبر رأس Authorization: Bearer - إعداد البيئة: - Python 3.10+ - تثبيت الحزم: pip install requests pydantic mcp - متغيرات البيئة: - COMET_API_BASE_URL - COMET_API_KEY - وحدة مشتركة لاستدعاء CometAPI مباشرة (استخدمها في جميع الأمثلة) ```python # comet_api.py # ملاحظة: تُترجم التعليقات/النصوص الظاهرة للمستخدم فقط. لا تُترجم المعرفات أو المنطق. import os import requests from typing import Any, Dict BASE_URL = os.environ.get("COMET_API_BASE_URL", "").rstrip("/") API_KEY = os.environ.get("COMET_API_KEY", "") class CometAPIError(Exception): """خطأ عام عند استدعاء CometAPI.""" def _auth_headers() -> Dict[str, str]: if not API_KEY: raise CometAPIError("لم يتم ضبط COMET_API_KEY في متغيرات البيئة.") return { "Authorization": f"Bearer {API_KEY}", "Accept": "application/json", "User-Agent": "comet-demo/1.0", } def get_order(order_id: str) -> Dict[str, Any]: """استعلام عن طلبية من CometAPI عبر رقم الطلب.""" if not BASE_URL: raise CometAPIError("لم يتم ضبط COMET_API_BASE_URL في متغيرات البيئة.") if not order_id: raise ValueError("معرّف الطلب مطلوب.") url = f"{BASE_URL}/orders/{order_id}" resp = requests.get(url, headers=_auth_headers(), timeout=20) try: resp.raise_for_status() except requests.HTTPError as e: # محاولة إرجاع رسالة مفيدة من الجسم إن وُجدت try: data = resp.json() except Exception: data = {"message": resp.text} raise CometAPIError(f"فشل طلب CometAPI: {resp.status_code} - {data}") from e try: return resp.json() except ValueError as e: raise CometAPIError("استجابة غير صالحة (ليست JSON).") from e ``` - تشغيل مباشر (بدون MCP): نفس الاستعلام مباشرة ضد CometAPI ```python # run_direct.py import sys import json from comet_api import get_order, CometAPIError def main() -> None: if len(sys.argv) ") sys.exit(1) order_id = sys.argv[1] try: data = get_order(order_id) print(json.dumps(data, ensure_ascii=False, indent=2)) except CometAPIError as e: print(f"خطأ CometAPI: {e}") sys.exit(2) except Exception as e: print(f"خطأ غير متوقع: {e}") sys.exit(3) if __name__ == "__main__": main() ``` - خادم MCP يغلّف نفس الأداة (lookup_order) فوق CometAPI ```python # mcp_server.py # خادم MCP يُعرّف أداة lookup_order ويعيد النتيجة من CometAPI. import json from typing import Any, Dict from pydantic import BaseModel, Field from comet_api import get_order, CometAPIError # حزمة mcp (من Anthropic) — تأكد من تثبيتها: pip install mcp from mcp.server import Server from mcp.server.stdio import run as run_stdio server = Server("comet-mcp-server") class LookupOrderArgs(BaseModel): order_id: str = Field(..., description="معرّف الطلب المطلوب الاستعلام عنه") @server.tool( name="lookup_order", description="البحث عن طلبية عبر CometAPI باستخدام رقم الطلب.", args=LookupOrderArgs, ) async def lookup_order(args: LookupOrderArgs) -> Dict[str, Any]: """أداة MCP: تُنادي CometAPI وتعيد JSON كقاموس.""" try: data = get_order(args.order_id) # يمكن إعادة dict مباشرة؛ عميل MCP سيعجنه كـ JSON/Text حسب دعمه. return data except CometAPIError as e: # من الأفضل إرجاع رسالة خطأ واضحة ضمن نتيجة الأداة return {"error": str(e)} if __name__ == "__main__": # تشغيل الخادم عبر stdio (يُناسب الربط مع عملاء MCP). run_stdio(server) ``` - عميل Python يستدعي نفس الأداة عبر MCP (يشغل الخادم ثم يستدعي الأداة) ```python # run_via_mcp.py # يشغّل خادم MCP (mcp_server.py) عبر stdio ويستدعي أداة lookup_order بالـ order_id نفسه. import sys import json import asyncio # واجهات عميل MCP — قد تختلف الأسماء البسيطة بحسب إصدار الحزمة. from mcp.client.stdio import stdio_transport from mcp.client.session import ClientSession async def main_async(order_id: str) -> int: # يشغّل mcp_server.py كعملية فرعية عبر stdio transport = stdio_transport( sys.executable, [ "mcp_server.py" ], env=None, # يمكن تمرير بيئة مخصّصة إن لزم ) async with transport: session = ClientSession(transport) # تهيئة بروتوكول MCP (تبادل القدرات، إلخ) await session.initialize() # اختيار/تحقق من وجود الأداة tools = await session.list_tools() if not any(t.name == "lookup_order" for t in tools): print("لم يُعثر على الأداة lookup_order في خادم MCP.") return 2 # استدعاء الأداة وتمرير الوسائط result = await session.call_tool("lookup_order", {"order_id": order_id}) # result.content عادة قائمة محتويات (نص/JSON). نحاول طباعة JSON إن وجد. payload = None for c in getattr(result, "content", []): if hasattr(c, "type") and c.type == "json": payload = c.data break if hasattr(c, "type") and c.type == "text": # قد يعيد الخادم نصًا JSONيًا try: payload = json.loads(c.text) except Exception: payload = c.text break if payload is None: # قد يكون الاسترجاع المباشر لقيمة إرجاع الأداة payload = getattr(result, "result", None) print(json.dumps(payload, ensure_ascii=False, indent=2)) return 0 def main() -> None: if len(sys.argv) ") sys.exit(1) order_id = sys.argv[1] code = asyncio.run(main_async(order_id)) sys.exit(code) if __name__ == "__main__": main() ``` - تشغيل نفس استعلام الطلب مباشرة وعبر MCP - إعداد البيئة مرة واحدة: - export COMET_API_BASE_URL="https://api.example.com" - export COMET_API_KEY="YOUR_COMET_API_KEY" - تشغيل مباشر: - python run_direct.py 123456789 - التشغيل عبر MCP: - python run_via_mcp.py 123456789 - ملاحظات - استبدل قيم البيئة بنقاط نهاية CometAPI الفعلية. - يعتمد شكل الكائن المعاد من CometAPI على الخدمة؛ اطبع المخرجات للتحقق من البنية. - إذا اختلفت واجهات mcp.client بحسب الإصدار، راجع توثيق الحزمة mcp للإصدار المثبت وعدّل أسماء الوحدات/الدوال التالية عند الحاجة: - mcp.client.stdio.stdio_transport - mcp.client.session.ClientSession.initialize / list_tools / call_tool - يمكنك إضافة أمان/إعادة محاولات/سجلّات وفق احتياجك في comet_api.py دون تغيير واجهة الأداة.

D
Deon Goodwin