תרגול זה ידריך אתכם בתהליך הקמה מלא של שרת MCP (Model Context Protocol) באמצעות ספריית FastMCP בפייתון. פרוטוקול MCP הוא תקן שמאפשר למודלי שפה גדולים (LLMs) גישה ל״כלים״ (Tools) וליכולות חיצוניות, מה שמרחיב משמעותית את יכולותיהם לענות על שאלות מורכבות, לבצע פעולות ולגשת לנתונים עדכניים.
ספריית FastMCP הופכת את בניית השרתים הללו לפשוטה ואינטואיטיבית, תוך שימוש במנגנוני decorators וסכמות נתונים מובנות. במהלך התרגול, נבנה את הקוד צעד אחר צעד, נבין כיצד פועלים Middlewares (תוכנות ביניים) לטיפול בבקשות, וכיצד להוסיף יכולות חדשות לשרת.
נבחן דרכים שונות לאינטראקציה עם השרת: שליחת בקשות ישירות (כמו עם curl), חיבור ככלי מקומי לכלים כמו GitHub Copilot ב-VS Code, ובניית Client ייעודי. התרגול הזה הוא קו זינוק מעשי להפיכת מודלי שפה לחלק אינטגרלי מהארכיטקטורה של האפליקציות שלכם.
שימו לב – תרגול זה מובנה מאוד והוא מהווה בסיס למחקר וללימוד דרך ״לכלוך הידיים״ בהמשך הדרך. חשוב להכיר את החלקים השונים בתרגול ובמערכת. עם זאת – בכל פרק וסעיף, הרגישו חופשי לחקור יותר לעומק ולסקור גם מושגים שונים ואפשרויות שונות שלא הוזכרו במפורש. נתקעתם? לא נורא – חזרו להוראות המקוריות, ותמיד אפשר להתחיל פרויקט חדש ונקי, ולהתנסות מראש הפרק הנוכחי.
בהצלחה!
1. התקנה והקמת שלד השרת (server.py)
בפרק זה נתקין את הספריות הנדרשות, וניצור את השלד הבסיסי של השרת באמצעות העתקת מקטעי קוד מוסברים לקובץ הראשי שלנו.
הכנה
עליכם לוודא שמותקן אצלכם Python 3.10 ומעלה, ושאתם נמצאים בסביבה וירטואלית פעילה. צרו קובץ חדש בשם server.py.
-
תרגיל 1 – התקנת FastMCP והגדרות בסיסיות
- התקינו את FastMCP והספריות הנלוות הנדרשות לפרויקט:
pip install fastmcp requests - העתיקו והדביקו את קטעי הקוד הבאים לראש הקובץ server.py, אחד אחרי השני:
- אימפורטים נדרשים:
from fastmcp import FastMCP from fastmcp.server.middleware import Middleware, MiddlewareContext import logging import json - הגדרת הלוגינג: הגדירו לוגינג בסיסי שיעזור לנו לעקוב אחר פעולת השרת:
# Set logging level and disable FastMCP's default logging logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') log = logging.getLogger(__name__) - יצירת מופע FastMCP: צרו את השרת הראשי.
mcp = FastMCP("Demo 🚀", stateless_http=True)הסבר: הארגומנט stateless_http=True חשוב. הוא מנחה את FastMCP להתייחס לכל בקשת HTTP כאל אירוע נפרד, ולוודא שה-Tool קורא ל-LLM לא ישמור מצב (State) בין שיחות שונות. זהו המצב הנפוץ ביותר בשרתי Tools.
- התקינו את FastMCP והספריות הנלוות הנדרשות לפרויקט:
2. יישום Middleware ללוגינג
Middleware מאפשר לכם להריץ לוגיקה לפני ואחרי הפעלת ה-Tool המרכזי. נשתמש בו כדי לראות את הבקשה המלאה בפורמט JSON-RPC.
-
תרגיל 2 – יצירת HttpLoggingMiddleware
- העתיקו את קוד ה-Middleware הבא והדביקו אותו מתחת לקטע הקוד הקודם:
class HttpLoggingMiddleware(Middleware): async def on_message(self, context: MiddlewareContext, call_next): """Called for every MCP message (request).""" full_request_data = None if context.method is not None and context.message is not None: try: # 1. Determine the serializable payload serializable_body = None if isinstance(context.message, dict): serializable_body = context.message elif hasattr(context.message, 'model_dump'): serializable_body = context.message.model_dump() elif hasattr(context.message, 'dict'): serializable_body = context.message.dict() else: serializable_body = context.message # 2. Reconstruct the full JSON-RPC envelope full_request_data = { "jsonrpc": "2.0" } if hasattr(context, 'id') and context.id is not None: full_request_data["id"] = context.id if isinstance(serializable_body, dict) and 'method' in serializable_body and ('params' in serializable_body or 'arguments' in serializable_body): full_request_data.update(serializable_body) else: full_request_data["method"] = context.method if context.method is not None and context.method != "prompts/list" and context.method != "tools/list": full_request_data["params"] = serializable_body else: full_request_data.update(serializable_body) # 3. Pretty-print the full JSON body if full_request_data is not None: json_body = json.dumps(full_request_data, indent=4) print("--- 📥 INCOMING FULL JSON-RPC REQUEST ---") print(json_body) print("--------------------------------------") except Exception as e: log.error(f"Failed to log full JSON body: {e.__class__.__name__}: {e}") # Continue processing the request result = await call_next(context) return result - רישום Middleware: רשמו את ה-Middleware לשרת FastMCP שלכם:
# Register the middleware mcp.add_middleware(HttpLoggingMiddleware())הסבר: הפקודה mcp.add_middleware() מוסיפה את הלוגיקה החדשה שלנו לשרשרת הטיפול בבקשות.
- העתיקו את קוד ה-Middleware הבא והדביקו אותו מתחת לקטע הקוד הקודם:
3. הוספת כלים (Tools) והרצת השרת
Tools הם לב ליבו של שרת MCP. כל פונקציה עם Decorator מתאים הופכת לכלי זמין למודל.
-
תרגיל 3 – יצירת ה-Tool הבסיסי (חישוב)
- הוסיפו את ה-Tool הפשוט הבא שמטרתו היא להוסיף שני מספרים:
@mcp.tool def add(a: int, b: int) -> int: """Add two numbers""" return a + b - הוספת Tool מתקדם (מזג אוויר): הוסיפו את כלי מזג האוויר שמדמה קריאה לשירות חיצוני:
@mcp.tool def get_current_weather(city: str) -> str: """ Get the current weather for a specific city. Args: city: The name of the city (e.g., "Tel Aviv"). Returns: A JSON string containing the current weather data. """ log.info(f"Tool called: get_current_weather for {city}") # Dummy data response. In a real app, you would use requests/httpx here. weather_data = { "city": city, "temperature": 25, "unit": "Celsius", "condition": "Sunny with light wind" } return json.dumps(weather_data, indent=2) - הרצת השרת: הוסיפו את בלוק ההרצה הראשי והריצו את הקובץ.
if __name__ == "__main__": mcp.run(transport="http", host="127.0.0.1", port=3000, log_level="info" ) - הריצו את השרת מתוך סביבת הפיתוח את הטרמינל.
- וודאו שהשרת מופעל ומאזין בכתובת http://127.0.0.1:3000.
- הוסיפו את ה-Tool הפשוט הבא שמטרתו היא להוסיף שני מספרים:
4. אינטראקציה: בדיקה באמצעות cURL וחיבור ל-VS Code
נבחן את השרת באמצעות בקשות HTTP ישירות, ונחבר אותו ככלי ל-GitHub Copilot.
-
תרגיל 4 – בדיקת הכלים באמצעות cURL
- ודאו שהשרת רץ. פתחו טרמינל חדש ושלחו בקשה לכלי add (התחביר חייב להיות JSON-RPC):
Linux / MacWindows PowerShellWindows CMDcurl -X POST http://127.0.0.1:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "add", "arguments": { "a": 100, "b": 25 } } }'curl -Method POST "http://127.0.0.1:3000/mcp" ` -Headers @{ "Content-Type" = "application/json" } ` -Headers @{ "Accept" = "application/json, text/event-stream" } ` -Body '{ "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "add", "arguments": { "a": 100, "b": 25 } } }'curl -X POST http://127.0.0.1:3000/mcp ^ -H "Content-Type: application/json" ^ -H "Accept: application/json, text/event-stream" ^ -d "{ \"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"tools/call\", \"params\": { \"name\": \"add\", \"arguments\": { \"a\": 100, \"b\": 25 } } }" - בדקו את התוצאה (אמורה להיות 125). בדקו בטרמינל של השרת את הפלט המלא של ה-Middleware.
- שלחו בקשה לכלי get_current_weather:
Linux / MacWindows PowerShellWindows CMDcurl -X POST http://127.0.0.1:3000/mcp \ -H "Content-Type: application/json" \ -H "Accept: application/json, text/event-stream" \ -d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_current_weather", "arguments": { "city": "Berlin" } } }'curl -Method POST "http://127.0.0.1:3000/mcp" ` -Headers @{ "Content-Type" = "application/json" } ` -Headers @{ "Accept" = "application/json, text/event-stream" } ` -Body '{ "jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": { "name": "get_current_weather", "arguments": { "city": "Berlin" } } }'curl -X POST http://127.0.0.1:3000/mcp ^ -H "Content-Type: application/json" ^ -H "Accept: application/json, text/event-stream" ^ -d "{ \"jsonrpc\": \"2.0\", \"id\": 2, \"method\": \"tools/call\", \"params\": { \"name\": \"get_current_weather\", \"arguments\": { \"city\": \"Berlin\" } } }"
- ודאו שהשרת רץ. פתחו טרמינל חדש ושלחו בקשה לכלי add (התחביר חייב להיות JSON-RPC):
-
תרגיל 5 – חיבור השרת ל-GitHub Copilot (דרך mcp.json)
- התקינו את הרחבת GitHub Copilot Chat ב-VS Code.
- צרו קובץ תצורה בשם mcp.json בנתיב המשתמש שלכם (לרוב ~/.mcp.json ב-Linux/Mac או בתיקיית המשתמש ב-Windows).
- וודאו שהשרת עדיין מופעל ומאזין בכתובת http://127.0.0.1:3000.
- הכניסו את התוכן הבא לקובץ.
שימו לב: אם הקובץmcp.jsonכבר קיים לכם במערכת ומופיע בו תוכן קודם – הטמיעו רק את התוכן בתוך אובייקט הserversשכבר קיים ב JSON:{ "servers": { "fastmcp-demo": { "type": "http", "url": "http://localhost:3000/mcp" } } } - פתחו את VS Code, ובצ'אט של Copilot Chat נסחו שאלה שתחייב אותו להשתמש ב-Tool. שימו לב לפקודה שתופיע בטרמינל השרת כאשר Copilot יחליט להשתמש בכלי.
What is the sum of 5 and 37, and what is the current weather condition in London?
5. בניית FastMCP Client
FastMCP מספק גם Client פשוט וקל לשימוש, המאפשר קריאות Tool פרוגרמטיות מתוך קוד Python.
-
תרגיל 6 – יצירת ה-Client
- צרו קובץ חדש בשם client.py. וודאו ש-server.py עדיין רץ.
- הכניסו את הקוד הבא:
import asyncio from fastmcp import FastMCP async def main(): # create an instance of the client client = FastMCP.from_client("http://127.0.0.1:3000/") try: # calling Add tool print("Calling 'add' tool...") result_add = await client._call_tool_mcp("add", {"a": 1, "b": 2}) print(f"Result from 'add': {result_add}") # calling Weather tool print("\nCalling 'get_current_weather' tool...") result_weather = await client._call_tool_mcp("get_current_weather", {"city": 1, "b": 2}) print(f"Result from 'get_current_weather': {result_weather}") except Exception as e: print(f"An error occurred: {e}") finally: # closing resources await client.close() if __name__ == "__main__": asyncio.run(main()) - הריצו את הלקוח:
python client.py - וודאו שהפלט מכיל את התוצאות משני הכלים, ושבטרמינל השרת מופיעים הלוגים המתאימים.
6. תרגול פתוח ואתגרים מתקדמים
הגיע הזמן ״ללכלך את הידיים״ ולחקור יכולות מתקדמות נוספות שלא היו בקוד המקורי. נתמקד בחשיפת השרת החוצה ובחיבורו למודלי LLM חיצוניים.
-
תרגיל 7 – חשיפת ה-localhost וחיבור ל-ChatGPT
- התקנת cloudflared: ודאו שהכלי cloudflared מותקן במחשב שלכם.
- יצירת מנהרה (Tunnel): ודאו ש-server.py רץ על פורט 3000, ופתחו טרמינל חדש כדי ליצור מנהרה ציבורית זמנית:
cloudflared tunnel --url http://127.0.0.1:3000 - הכלי יספק לכם כתובת URL ציבורית זמנית (בסגנון https://random-id.trycloudflare.com).
- חיבור ל-ChatGPT: היכנסו ל-OpenAI Platform ובחרו באפשרות ליצור Custom GPT (אם יש לכם גישת מפתחים) או Connector. עליכם לספק את ה-URL הציבורי שקיבלתם. (תרגיל זה מניח שה-LLM יודע ליצור את מפרט ה-OpenAPI הנדרש עבור ה-Tools).
- בצעו ניסוי בצ'אט: שאלו שאלה באנגלית שתחייב את המודל להפעיל את get_current_weather tool דרך החיבור שיצרתם.
-
תרגיל 8 – הוספת כלי מתוחכם (API אמיתי)
- הוסיפו כלי חדש המבצע קריאת HTTP אמיתית ל-API חיצוני חינמי (כגון API המציע בדיחות רנדומליות, ציטוטים, או מטבעות).
- הגדירו Tool בשם get_quote שאינו מקבל פרמטרים ומחזיר מחרוזת של ציטוט רנדומלי (השתמשו בספריית requests הפעם).
- הריצו מחדש את השרת ובדקו את ה-Tool באמצעות cURL או Copilot:
Tell me a random programming quote.
סיימתם בהצלחה את התרגול המעשי לבניית שרת MCP באמצעות FastMCP. למדתם לבנות את הקוד בהדרגה, להטמיע לוגיקה באמצעות Middlewares, להוסיף כלים, ולהשתמש בשרת ממקורות שונים – החל מ-cURL, דרך Client ייעודי ועד לחיבור LLMs חיצוניים כמו Copilot ו-ChatGPT. ידע זה הוא הבסיס לבניית ארכיטקטורות AI מתקדמות.