تصویر از نویسنده
تصویر از نویسنده

ساخت یک سرور MCP ساده

MCP یا پروتکل زمینه مدل (Model Context Protocol)، یک چارچوب پیشگامانه است که به سرعت در حال کسب محبوبیت در جامعه هوش مصنوعی و مدل زبان بزرگ (LLM) است. این پروتکل به عنوان یک رابط جهانی برای سیستم‌های هوش مصنوعی عمل می‌کند و امکان ادغام یکپارچه با منابع خارجی، APIها و خدمات را فراهم می‌سازد. MCP را به عنوان یک پروتکل استاندارد در نظر بگیرید که به LLMها اجازه می‌دهد تا به روشی سازگار و کارآمد با ابزارها و منابع داده تعامل داشته باشند، درست مانند نحوه کار USB-C برای دستگاه‌ها.

در این آموزش، ما سرور MCP خود را با استفاده از Yahoo Finance Python API برای دریافت قیمت‌های سهام بی‌درنگ، مقایسه آن‌ها و ارائه تحلیل تاریخی خواهیم ساخت. این پروژه برای مبتدیان مناسب است، به این معنی که شما فقط به یک درک اولیه از پایتون برای تکمیل این پروژه نیاز دارید.

۱. راه‌اندازی محیط برای استفاده از سرور MCP

ابتدا به وب‌سایت claude.ai بروید و Claude Desktop را دانلود و نصب کنید. سپس، بسته پایتون MCP و YFinance را با استفاده از دستور PIP نصب کنید.

$ pip install "mcp[cli]" yfinance

۲. ساخت سرور MCP

دایرکتوری پروژه را با نام پروژه انتخابی خود ایجاد کنید و سپس فایل پایتون stock_price_server.py را ایجاد کرده و کد زیر را به آن اضافه کنید.

  • مقداردهی اولیه سرور MCP: یک سرور MCP قابل تنظیم با نام "Stock Price Server" با استفاده از کلاس FastMCP ایجاد می‌کند.
  • بازیابی قیمت سهام: تابع get_stock_price آخرین قیمت سهام را برای یک نماد معاملاتی مشخص بازیابی می‌کند، با گزینه‌های جایگزین برای تعطیلی بازار.
  • نمایش منبع: تابع stock_resource داده‌های قیمت سهام را به عنوان یک منبع قالب‌بندی و نمایش می‌دهد و خروجی کاربرپسند ارائه می‌دهد.
  • بازیابی داده‌های تاریخی: تابع get_stock_history داده‌های سهام تاریخی را برای یک دوره مشخص بازیابی کرده و به صورت رشته‌ای با فرمت CSV برمی‌گرداند.
  • مقایسه سهام: تابع compare_stocks قیمت‌های دو نماد معاملاتی را مقایسه می‌کند و یک پیام قالب‌بندی شده را برمی‌گرداند که ارزش‌های نسبی آن‌ها را نشان می‌دهد.
  • مدیریت خطا: هر تابع شامل مدیریت خطای قوی برای برگرداندن پیام‌های معنادار در هنگام عدم موفقیت در بازیابی داده‌ها است.
from mcp.server.fastmcp import FastMCP
import yfinance as yf

# Create an MCP server with a custom name
mcp = FastMCP("Stock Price Server")

@mcp.tool()
def get_stock_price(symbol: str) -> float:
    """
    Retrieve the current stock price for the given ticker symbol.
    Returns the latest closing price as a float.
    """
    try:
        ticker = yf.Ticker(symbol)
        # Get today's historical data; may return empty if market is closed or symbol is invalid.
        data = ticker.history(period="1d")
        if not data.empty:
            # Use the last closing price from today's data
            price = data['Close'].iloc[-1]
            return float(price)
        else:
            # As a fallback, try using the regular market price from the ticker info
            info = ticker.info
            price = info.get("regularMarketPrice", None)
            if price is not None:
                return float(price)
            else:
                return -1.0  # Indicate failure
    except Exception:
        # Return -1.0 to indicate an error occurred when fetching the stock price
        return -1.0

@mcp.resource("stock://{symbol}")
def stock_resource(symbol: str) -> str:
    """
    Expose stock price data as a resource.
    Returns a formatted string with the current stock price for the given symbol.
    """
    price = get_stock_price(symbol)
    if price < 0:
        return f"Error: Could not retrieve price for symbol '{symbol}'."
    return f"The current price of '{symbol}' is ${price:.2f}.".

@mcp.tool()
def get_stock_history(symbol: str, period: str = "1mo") -> str:
    """
    Retrieve historical data for a stock given a ticker symbol and a period.
    Returns the historical data as a CSV formatted string.
    
    Parameters:
        symbol: The stock ticker symbol.
        period: The period over which to retrieve historical data (e.g., '1mo', '3mo', '1y').
    """
    try:
        ticker = yf.Ticker(symbol)
        data = ticker.history(period=period)
        if data.empty:
            return f"No historical data found for symbol '{symbol}' with period '{period}'."
        # Convert the DataFrame to a CSV formatted string
        csv_data = data.to_csv()
        return csv_data
    except Exception as e:
        return f"Error fetching historical data: {str(e)}"

@mcp.tool()
def compare_stocks(symbol1: str, symbol2: str) -> str:
    """
    Compare the current stock prices of two ticker symbols.
    Returns a formatted message comparing the two stock prices.
    
    Parameters:
        symbol1: The first stock ticker symbol.
        symbol2: The second stock ticker symbol.
    """
    price1 = get_stock_price(symbol1)
    price2 = get_stock_price(symbol2)
    if price1 < 0 or price2 < 0:
        return f"Error: Could not retrieve data for comparison of '{symbol1}' and '{symbol2}'."
    if price1 > price2:
        result = f"{symbol1} (${price1:.2f}) is higher than {symbol2} (${price2:.2f})."
    elif price1 < price2:
        result = f"{symbol1} (${price1:.2f}) is lower than {symbol2} (${price2:.2f})."
    else:
        result = f"Both {symbol1} and {symbol2} have the same price (${price1:.2f})."
    return result

if __name__ == "__main__":
    mcp.run()

۳. بررسی سرور MCP

اکنون سرور خود را با استفاده از MCP Server Inspector با اجرای دستور زیر آزمایش خواهیم کرد:

$ mcp dev stock_price_server.py

این دستور شما را به URL هدایت می‌کند که MCP Inspector در آن ارائه می‌شود. با استفاده از رابط کاربری، می‌توانید ابزارهای مختلف را آزمایش کنید و اطمینان حاصل کنید که همه چیز مطابق نظر کار می‌کند.

این سرور اکنون موارد زیر را در معرض نمایش قرار می‌دهد:

  • get_stock_price: ابزاری برای دریافت آخرین قیمت
  • stock_resource: منبعی که یک پیام قیمت قابل خواندن توسط انسان را برمی‌گرداند
  • get_stock_history: ابزاری که داده‌های تاریخی را به صورت CSV برمی‌گرداند
  • compare_stocks: ابزاری برای مقایسه قیمت‌های فعلی دو سهام
تصویری از رابط کاربری MCP Server Inspector

۴. تنظیم سرور MCP برای Claude Desktop

هنگامی که از سرور MCP خود راضی شدیم، آن را با اجرای دستور زیر در ترمینال در Claude Desktop ادغام خواهیم کرد:

$ mcp install stock_price_server.py --name "Stock Price Server"

وقتی Claude Desktop را دوباره راه‌اندازی کنید، آیکون‌های جدیدی را در زیر گزینه چت مشاهده خواهید کرد. این نشان می‌دهد که MCP ما پیکربندی شده است. می‌توانید روی این آیکون‌ها کلیک کنید تا بررسی کنید چه تعداد ابزار برای Claude Desktop در دسترس است.

تصویری از آیکون‌های MCP در Claude Desktop

۵. آزمایش سرور MCP با Claude Desktop

ما با درخواست از Claude Desktop برای مقایسه دو قیمت سهام شروع خواهیم کرد.

درخواست: "لطفاً قیمت سهام مایکروسافت و تسلا را مقایسه کنید؟"

پس از وارد کردن درخواست، از شما درخواست مجوز برای استفاده از ابزار مشخص شده می‌کند. فقط روی دکمه‌ای که می‌گوید "Allow for This Chat" کلیک کنید.

تصویری از درخواست مجوز در Claude Desktop

ما یک مقایسه ساده از قیمت سهام مایکروسافت و تسلا داریم.

تصویری از مقایسه قیمت سهام در Claude Desktop

اکنون یک تحلیل تاریخی از سهام تسلا برای ماه گذشته درخواست خواهیم کرد.

درخواست: "لطفاً داده‌های تاریخی تسلا را برای ماه گذشته ارائه دهید؟"

بار دیگر، ما یک تحلیل عالی دریافت کردیم، حتی بهتر از اینکه من به صورت دستی فایل CSV را بارگذاری کرده بودم.

تصویری از تحلیل تاریخی سهام در Claude Desktop

نکات پایانی

MCP یک مفهوم جدید است که بر ایده‌های سنتی مانند فراخوانی تابع و عوامل هوش مصنوعی بنا شده است. در آینده، هدف ما این است که این فناوری‌ها را برای دستیابی به ادغام یکپارچه منابع خارجی با هوش مصنوعی شما کامل کنیم. در نتیجه، بنا به درخواست شما، قادر خواهد بود وظایف مختلفی مانند سفارش مواد غذایی، ارسال ایمیل، ایجاد لیست پخش Spotify و به اشتراک گذاشتن آنها با دوستان خود را انجام دهد.

به طور کلی، MCP به طور چشمگیری پتانسیل Claude Desktop را بهبود می‌بخشد و به آن اجازه می‌دهد تا وظایف پیچیده مختلفی را با سهولت انجام دهد. با ادغام یکپارچه منابع خارجی، LLM اکنون می تواند با اطلاعات دنیای واقعی تعامل داشته باشد.