Model Context Protocol (MCP)

غلبه بر مقیاس‌پذیری: پیاده‌سازی کشف و ثبت پویای ابزار در سرورهای MCP

با بلوغ اکوسیستم اطراف پروتکل زمینه مدل (MCP)، نیاز به معماری‌های سرور قوی و مقیاس‌پذیر بیش از پیش احساس می‌شود. در حالی که تعریف ابزارهای استاتیک برای موارد استفاده ساده کار می‌کند، برنامه‌های سازمانی به قابلیت ثبت ابزارها در زمان اجرا نیاز دارند. این رویکرد که به عنوان کشف و ثبت پویای ابزار شناخته می‌شود، به سرورهای MCP اجازه می‌دهد تا بدون نیاز به راه‌اندازی مجدد سرور، با تغییر منابع داده، مجوزهای کاربر یا نصب پلاگین‌ها سازگار شوند.

در این پست، نحوه پیاده‌سازی یک ثبت‌کننده ابزار پویا در یک سرور MCP با استفاده از پایتون را بررسی خواهیم کرد. ما فراتر از پیکربندی استاتیک حرکت کرده و سیستمی انعطاف‌پذیر ایجاد می‌کنیم که در آن ابزارها می‌توانند به صورت برنامه‌نویسی اضافه، حذف و کشف شوند.

چالش تعاریف استاتیک

پیاده‌سازی‌های سنتی MCP اغلب به مجموعه‌ای ثابت از ابزارها تکیه دارند که در مرحله راه‌اندازی اولیه سرور تعریف می‌شوند. اگرچه این روش پیاده‌سازی آسانی دارد، اما محدودیت‌های متعددی ایجاد می‌کند:

  • عدم انعطاف‌پذیری: شما نمی‌توانید قابلیت‌های جدیدی بدون استقرار مجدد سرور اضافه کنید.
  • هدر رفت منابع: تمام ابزارها، حتی آن‌هایی که هرگز استفاده نمی‌شوند، در حافظه بارگذاری می‌شوند.
  • پیچیدگی: مدیریت لیست رو به رشدی از تعاریف ابزارهای سخت‌افزاری (hardcoded) دشوار و نامرتب می‌شود.

ثبت پویا با جدا کردن تعریف ابزار از راه‌اندازی اولیه سرور، این مشکلات را حل می‌کند. به جای فهرست کردن تمام ابزارهای ممکن از ابتدا، ما ثبت‌کننده‌ای ایجاد می‌کنیم که می‌تواند کلاس‌ها یا توابع ابزار جدید را در هر زمان بپذیرد.

معماری ثبت‌کننده پویا

برای پیاده‌سازی کشف پویا، به سه جزء اصلی نیاز داریم:

  1. ثبت‌کننده (Registry): یک ذخیره‌سازی مرکزی (معمولاً یک دیکشنری یا لیست) که متادیتا و پیاده‌سازی‌ها را برای تمام ابزارهای موجود نگه می‌دارد.
  2. مکانیزم کشف: فرآیندی که به دنبال ابزارهای جدید می‌گردد، چه از پایگاه داده، سیستم فایل یا نقطه پایانی شبکه.
  3. پردازشگر سرور: منطقی که هنگام دریافت درخواست initialize یا tools/list از ثبت‌کننده می‌خواند.

مثال پیاده‌سازی

بیایید یک پیاده‌سازی عملی را با استفاده از پایتون و SDK رسمی MCP بررسی کنیم. ما یک دکوراتور ابزار پایه ایجاد می‌کنیم که توابع را به طور خودکار در یک ثبت‌کننده سراسری ثبت می‌کند.

from mcp.server import Server
from mcp.types import Tool, TextContent
import asyncio

# ثبت‌کننده سراسری برای ذخیره ابزارهای کشف شده
tool_registry = {}

def register_tool(name, description):
    """دکوراتور برای ثبت پویای ابزارها."""
    def decorator(func):
        tool_metadata = {
            "name": name,
            "description": description,
            "handler": func
        }
        tool_registry[name] = tool_metadata
        return func
    return decorator

# مثال: ابزار اضافه شده به صورت پویا
@register_tool("get_weather", "Fetches current weather data for a location")
async def get_weather(location: str) -> str:
    # شبیه‌سازی تماس با API
    return f"Weather in {location} is sunny."

# مثال: ابزار پویای دیگر
@register_tool("ping_server", "Checks if the server is alive")
async def ping_server() -> str:
    return "Pong!"

# راه‌اندازی سرور MCP
server = Server("dynamic-tool-server")

@server.list_tools()
async def list_tools():
    """
    ثبت‌کننده پویا را به عنوان لیستی از ابزارهای MCP نمایان می‌کند.
    این روش توسط کلاینت برای کشف ابزارهای موجود فراخوانی می‌شود.
    """
    tools = []
    for name, metadata in tool_registry.items():
        # در یک پیاده‌سازی واقعی، شما باید handler را به یک تعریف Tool مناسب با اسکیماهای ورودی نگاشت کنید
        tools.append(Tool(
            name=name,
            description=metadata["description"]
        ))
    return tools

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    """
    تماس‌های ابزار را به handler صحیح در ثبت‌کننده هدایت می‌کند.
    """
    if name not in tool_registry:
        raise ValueError(f"Unknown tool: {name}")
    
    handler = tool_registry[name]["handler"]
    # اجرای handler با آرگومان‌های ارائه شده
    result = await handler(**arguments)
    return [TextContent(type="text", text=str(result))]

async def main():
    async with server.run() as server:
        await server.serve()

if __name__ == "__main__":
    asyncio.run(main())

استراتژی‌های کشف پیشرفته

مثال بالا از رویکرد مبتنی بر دکوراتور استفاده می‌کند که برای معماری‌های شبیه به پلاگین عالی است. با این حال، برای سناریوهای پیچیده‌تر، ممکن است بخواهید کشف مبتنی بر سیستم فایل یا ثبت مبتنی بر پایگاه داده را پیاده‌سازی کنید. برای مثال، می‌توانید یک پوشه plugins/ را برای ماژول‌های پایتون اسکن کنید، آن‌ها را وارد کرده و به طور خودکار هر تابعی را که با یک ویژگی خاص علامت‌گذاری شده است، ثبت کنید.

یک الگوی پیشرفته دیگر، کشف آگاه از زمینه است. ثبت‌کننده شما می‌تواند یک سرویس پیکربندی یا پایگاه داده مجوزهای کاربر را برای تعیین اینکه کدام ابزارها برای جلسه کاربر فعلی قابل مشاهده هستند، پرس‌وجو کند. این اطمینان حاصل می‌کند که ابزارهای حساس فقط به کلاینت‌های مجاز نمایان شوند، در حالی که ابزارهای عمومی باقی می‌مانند.

بهترین شیوه‌ها برای ثبت پویا

  • اعتبارسنجی اسکیما: همیشه اطمینان حاصل کنید که ابزارهای ثبت شده پویا از تعاریف دقیق JSON Schema برای آرگومان‌های ورودی پیروی می‌کنند. ماژول mcp.types باید برای تعریف دقیق این اسکیماها استفاده شود.
  • مدیریت خطا: مدیریت خطای قوی را در handler call_tool ثبت‌کننده خود پیاده‌سازی کنید. اگر یک ابزار پویا شکست بخورد، سرور باید یک خطای ساختاریافته بازگرداند به جای اینکه کرش کند.
  • بارگذاری مجدد داغ (Hot Reloading): در نظر بگیرید که مکانیزمی برای پاک کردن ثبت‌کننده و اسکن مجدد برای تغییرات پیاده‌سازی کنید. این به توسعه‌دهندگان اجازه می‌دهد ابزارهای جدیدی بدون راه‌اندازی مجدد فرآیند کامل سرور MCP اضافه کنند.

نتیجه‌گیری

پیاده‌سازی کشف و ثبت پویای ابزار، سرور MCP شما را از یک نقطه پایانی استاتیک به یک افزونه زنده و پویا از برنامه‌های هوش مصنوعی شما تبدیل می‌کند. با بهره‌گیری از دکوراتورهای پایتون، ثبت‌کننده‌های متمرکز و اعتبارسنجی اسکیما، می‌توانید سیستم‌هایی بسازید که به آرامی مقیاس‌پذیر باشند و به سرعت با نیازهای جدید سازگار شوند. با ادامه رشد اکوسیستم MCP، اتخاذ این الگوها اطمینان حاصل می‌کند که سرورهای شما انعطاف‌پذیر، امن و با عملکرد بالا باقی بمانند.

Share: