פוסט
MCP: פרוטוקול ההקשר למודלים
מה זה MCP, למה הוא קיים, hosts, clients ו-servers, כלים, משאבים ו-prompts, שני ה-transports, ושרת MCP קטן ב-Python.
הפוסט הקודם הגדיר כלי בתוך אפליקציה אחת. כדי להשתמש בו ב-IDE, באפליקציית הצ’אט ובסוכן, צריך לכתוב את הדבק שלוש פעמים. עם MCP (Model Context Protocol), תקן פתוח, כותבים את הכלי פעם אחת כשרת MCP, וכל אפליקציה שמדברת MCP יכולה להשתמש בו.
העובדות מבוססות על מפרט MCP (גרסה 2026-07-28 בזמן הכתיבה) ועל המדריך הרשמי Build a server. הקוד לא הורץ בשביל הפוסט.
למה צריך פרוטוקול
בלי תקן, N אפליקציות ו-M מקורות נתונים צריכים N × M אינטגרציות. עם פרוטוקול משותף, כל אפליקציה וכל מקור מממשים MCP פעם אחת.
המפרט מציין שההשראה שלו היא ה-Language Server Protocol, שעשה את אותו הדבר לשפות תכנות ולעורכים: language server אחד עובד בכל עורך שמדבר LSP.
Hosts, clients ו-servers
המפרט מגדיר שלושה תפקידים:
- Host: האפליקציה שהמשתמש עובד בה, כמו IDE, אפליקציית צ’אט או סוכן. הוא מחזיק את השיחה ואת המודל, והוא מבקש מהמשתמש הסכמה.
- Client: מחבר בתוך ה-host. כל client מדבר עם server אחד בדיוק.
- Server: תוכנה שמציעה יכולות: קבצים, מסד נתונים, API חיצוני.
לפי התכנון, server לא אמור לקרוא את כל השיחה או “לראות לתוך” שרתים אחרים: ה-host מחליט מה כל שרת מקבל.
מה שרת מציע
שרתים מציעים שלושה סוגי דברים, והם נבדלים במי ששולט בהם:
- Tools: פונקציות שהמודל יכול לקרוא להן, כמו הכלים מהפוסט הקודם. המודל מחליט מתי.
- Resources: נתונים כמו קבצים, רשומות או תגובות API, שהאפליקציה או המשתמש מצרפים כהקשר.
- Prompts: תבניות מוכנות שהמשתמש בוחר, הרבה פעמים כפקודת slash.
בכיוון ההפוך, שרת יכול לבקש דברים מה-client: elicitation (לבקש מהמשתמש מידע נוסף) ו-sampling (לבקש מהמודל של ה-host לייצר טקסט).
ההודעות הן JSON-RPC 2.0. המפרט מגדיר שני transports סטנדרטיים: stdio, שבו ה-host מפעיל את השרת כתת-תהליך והם מדברים דרך הקלט והפלט הסטנדרטיים, ו-Streamable HTTP, שבו כל הודעה היא HTTP POST ל-endpoint אחד. שרתים מקומיים משתמשים בדרך כלל ב-stdio, ושרתים מרוחקים ב-HTTP.
שרת MCP קטן ב-Python
המדריך הרשמי משתמש ב-uv ובחבילה mcp:
uv init notes-server
cd notes-server
uv add "mcp[cli]"
שרת עם כלי אחד. ה-SDK בונה את סכמת הכלי מה-type hints ומה-docstring:
import logging
from mcp.server import MCPServer
logger = logging.getLogger(__name__)
mcp = MCPServer("notes")
NOTES = {"shopping": "milk, eggs, bread", "ideas": "a blog series about AI"}
@mcp.tool()
def read_note(name: str) -> str:
"""Read one of the user's notes.
Args:
name: The note name, for example "shopping"
"""
logger.info("reading note %s", name) # הלוגים הולכים ל-stderr
return NOTES.get(name, f"No note named {name!r}. Available: {', '.join(NOTES)}")
if __name__ == "__main__":
mcp.run(transport="stdio")
האזהרה החשובה במדריך: בשרת stdio, לעולם אל תכתבו ל-stdout. ה-stdout נושא את הודעות ה-JSON-RPC, ו-print() אחד שנשכח משבש אותן. השתמשו ב-logging, שכותב ל-stderr.
חיבור לאפליקציה
לכל host יש הגדרות משלו, אבל רובם בנויים באותה צורה: פקודה שמפעילה את השרת. ב-Claude Desktop, המדריך מוסיף את השרת ל-claude_desktop_config.json:
{
"mcpServers": {
"notes": {
"command": "uv",
"args": ["--directory", "/ABSOLUTE/PATH/TO/notes-server", "run", "server.py"]
}
}
}
אחרי הפעלה מחדש, ה-host מפעיל את השרת, מקבל את רשימת הכלים שלו ומציע אותם למודל. Claude Code, סביבות פיתוח ו-frameworks רבים לסוכנים תומכים בשרתי MCP בצורה דומה, ול-API של Claude יש MCP connector לשרתים מרוחקים.
אבטחה
לפי המפרט, כלים “מייצגים הרצת קוד שרירותית, ויש להתייחס אליהם בזהירות המתאימה”. העקרונות המרכזיים שלו:
- המשתמש חייב לתת הסכמה מפורשת לפני שכלי רץ או לפני שמידע משותף עם שרת.
- תיאורים ו-annotations של כלים משרת שאתם לא סומכים עליו צריכים להיחשב לא אמינים.
- מי שמממש צריך לבנות תהליכי הסכמה והרשאה ברורים.
בפועל: התקינו שרתי MCP רק ממקורות שאתם סומכים עליהם, קראו מה הכלים שלהם יכולים לעשות, ותנו להם את הגישה המצומצמת ביותר שעובדת. שרת זדוני, או מסמך זדוני ששרת מחזיר, יכולים לנסות לכוון את המודל: זה prompt injection, והפוסט על אבטחה מסביר אותו.
הפוסט הבא עוסק בסוכנים: מה הופך מודל עם כלים לסוכן.