תקני השילוב של אפליקציות מקושרות ל-MCP

שרת ה-MCP יוצר את המסגרת לחיבור הפונקציות של האפליקציה (כלי MCP) ל-Connected Apps Platform. כדי שהמודל יוכל לבחור, להפעיל ולעבד את התוצאות של השירות בצורה מהימנה יותר, הגדרת ה-MCP צריכה לעמוד בדרישות המחמירות של התקנים הבאים.

העקרונות המנחים

בכל פונקציה, מתמקדים בכוונת המשתמש (Intent) ובמקרים לדוגמה, ולא ביכולות של הפונקציה. התיאור הוא הדרך העיקרית להסביר למודל מה המטרה של הכלי ובאילו תרחישים אפשר להשתמש בו.

ניהול גרסאות

כדי לתמוך בפריסות MCP יציבות וניתנות להתאמה, כדאי להשתמש בארכיטקטורת URI מובנית שמבוססת על ניהול גרסאות לפי נתיב – לדוגמה, ‎/v1, /v2. כך תוכלו לשמור על תאימות לדורות קודמים ולהגביל את הגישה לתכונות חדשות. אם מוסיפים לזה תת-דומיינים ספציפיים לספק, כמו https://gemini.mcp.company.com/mcp/v1, אפשר לנהל את התנועה באופן פרטני ולבצע אופטימיזציה של הגדרות הכלים בהתאם להקשר הייחודי ולהתנהגויות העיבוד של מודלים שונים של AI.

תאימות של גרסת פרוטוקול MCP

פלטפורמת האפליקציות המקושרות תומכת במפרט של Model Context Protocol‏ (MCP) עד גרסה 2025-11-25. עדיין אין תמיכה בגרסאות חדשות יותר של המפרט.

  • אחריות המפתח: באחריותך לוודא ששרת ה-MCP שלך פועל בהתאם לגרסת הפרוטוקול שנתמכת על ידי פלטפורמת האפליקציות המקושרות (2025-11-25) במהלך לחיצת היד של initialize ובכל הגדרות הכלים והסכימות.
  • תאימות לדורות קודמים של הפלטפורמה: ככל ש-Connected Apps Platform תאמץ גרסאות חדשות יותר של מפרט MCP בעתיד, הלקוח שלנו ישמור על תאימות לדורות קודמים עם גרסאות פרוטוקול שנתמכו בעבר, כדי שהשילובים הקיימים בסביבת הייצור ימשיכו לפעול ללא הפרעה.
  • ניהול שדרוגים: כשאתם מוכנים לאמץ מפרט MCP חדש שנתמך או להוסיף שינויים בסכימה, אתם צריכים לחשוף את העדכונים האלה בנתיב URI חדש עם גרסה (לדוגמה, /mcp/v2) תוך שמירה על נקודת הקצה הקיימת (/mcp/v1) לתנועה פעילה.

מותר לבצע שינויים בסכימות של MCP בין גרסאות של האפליקציה. מומלץ להשתמש בתכונה הזו ולהגדיר גרסאות לנקודות הקצה של MCP כדי לתמוך בהשקה הדרגתית של תכונות חדשות, או להסתמך רק על שינויים שתואמים לדורות קודמים.

מפרט פרוטוקול התעבורה

פלטפורמת האפליקציות המקושרות תומכת רק במפרט של Model Context Protocol ב-Streamable HTTP transport, גרסה 2025-03-26 ואילך. הוא לא תומך ב-HTTP מדור קודם עם העברת SSE, כפי שמתואר במפרט מ-5 בנובמבר 2024.

  • נקודת קצה אחת ב-HTTP. נקודת הקצה של MCP שסופקה ב-Connected Console (לדוגמה, https://api.example.com/mcp) היא כתובת ה-URL היחידה שאליה מוצרי Google הרלוונטיים שולחים את כל בקשות ה-JSON-RPC‏ (initialize, tools/list, tools/call) דרך HTTP POST רגיל.
  • סטרימינג של SSE בתוך HTTP שניתן להעביר בסטרימינג. אין תמיכה בהעברת SSE מדור קודם עם כמה נקודות קצה, אבל יש תמיכה באירועים שנשלחים מהשרת, כמו text/event-stream, ב-HTTP שניתן להעביר בסטרימינג. בקשות יוצאות ממוצרי Google הרלוונטיים כוללות את Accept: application/json, text/event-stream, כלומר השרת יכול להחזיר מטען ייעודי (payload) רגיל של application/json או להעביר בסטרימינג תשובות מצטברות באמצעות Content-Type: text/event-stream ישירות בגוף התשובה של HTTP POST.
  • ‫GET stream ו-405 Method Not Allowed. הלקוחות יכולים לנסות להפעיל סטרימינג אופציונלי של GET בנקודת הקצה (endpoint) כדי לקבל התראות מהשרת. אם השרת שלכם הוא ללא מצב (stateless) או שהוא מגיב רק לבקשות, החזרה של HTTP 405 Method Not Allowed נתמכת באופן מפורש ומטופלת בצורה נקייה על ידי שרת ה-proxy של הלקוח במוצר הרלוונטי של Google.

הוראות לשרת

פלטפורמת האפליקציות המקושרות מותאמת לקבלת הוראות מהשרת, וכך מאפשרת רמה מסוימת של שליטה בהתנהגות המודל שלא זמינה באמצעים אחרים.

פועלים לפי ההוראות של השרת.

התייחסות כ "רמז למודל" עם הקשר שימוש

כדי לספק רמזים למודלים, צריך לפעול לפי ההנחיות הבאות.

  • כתבו הוראות בתור "רמז" או מדריך ברמה גבוהה, כדי לעזור ל-LLM להבין את המטרה והיכולות הכלליות של השרת.
  • תארו מה הוא יכול לעשות, במקום לפרט תכונות או לתאר איך המודל צריך להשתמש בכלים ובמשאבים של השרת. אם המודל מבין את ה"מה" בצורה נכונה, הוא יכול לקבוע את ה"איך" בצורה די טובה על סמך התהליך שעובר המשתמש.
  • הטקסט הזה יתווסף ישירות להנחיית המערכת של המודל. ההנחיה צריכה להיות ברורה, מכוונת וחסכונית בטוקנים.

השלימו, אל תשכפלו

השתמשו בשדה הזה כדי לספק הקשר גלובלי שרלוונטי לכל הכלים, כדי להימנע מכפילויות בתיאורים של כלים ספציפיים.

דוגמאות להוראות לשרת

הדוגמאות הבאות מראות מה כדאי לעשות ומה לא כדאי לעשות כשכותבים הוראות לשרת.

מומלץ לא מומלץ

אתה מנהל מאגרים מומחה ב-GitHub. השרת הזה מספק גישה עמוקה למטא-נתונים של המאגר, ל-Issue Tracker ולתהליכי עבודה של בקשות משיכה. אפשר להשתמש בו כדי לשמור על תקינות הפרויקט, להפוך את תהליך המיון לאוטומטי ולוודא שהקוד עומד בתקנים. הניחו שכל הפעולות מבוצעות בהקשר של הארגון המאומת, אלא אם צוין אחרת. כדי לשמור על הסדר במאגר, כדאי לתת עדיפות לזיהוי שרשורים לא פעילים או בקשות משיכה לא מקושרות.

תמציתיות, מנחות ומשלימות את המודל

  • מגדיר את ה "מה" (תקינות הפרויקט, מיון) ולא את ה "איך"
  • היקף האימות שחל על כל הכלים

בשרת הזה יש כלים ל-GitHub. כדאי להשתמש בכלי list_issues כשהמשתמש שואל על בעיות. אפשר להשתמש ב-create_pull_request כדי ליצור בקשת משיכה. השתמש בכלים האלה בזהירות כדי לעזור למשתמש לנהל את הקוד שלו. תמיד צריך לבדוק את שם המאגר לפני שקוראים לכלי. אם המשתמש מבקש סיכום, צריך קודם להפעיל את הכלים ואז לסכם את הפלט

  • אל תפרט שוב את שמות הכלים,
  • אל תגידו למודל "איך" לחשוב, כי זה עלול להתנגש עם החשיבה המובנית של המודל, שמשתמשת בהקשר של המשתמש כדי לבחור את האפשרות הנכונה.
  • לא מסביר את אופי הגישה של השרת או את המגבלות הספציפיות שלו)

הנחיות לשימוש בכלי

ההנחיות הבאות מתארות שיטות מומלצות ליצירת הגדרות של שרת MCP לפונקציות או לכלים שונים באפליקציה.

מוסכמות למתן שמות לכלים

חשוב להקפיד על ההנחיות הבאות כשנותנים שם לכלי:

שימוש בשמות אינטואיטיביים שקריאים לאנשים

השתמשו בשמות קריאים לאנשים עם משמעויות ברורות ואינטואיטיביות במקום שמות מעורפלים. לדוגמה, get_user_information פשוט יותר מ-userInfo.

הקפידו על שימוש נכון באותיות רישיות

הקפידו על הכללים הבאים לגבי שימוש באותיות רישיות בשמות של פונקציות כלים וטריגרים של אפליקציות:

  • אותיות רישיות בפונקציות של כלים. משתמשים ב-snake_case או ב-camelCase לשמות של פונקציות הכלים שמוגדרים בסכימת ה-MCP (לדוגמה, get_user_information או publishDraft).
  • אותיות רישיות בנקודת האחיזה של הטריגר באפליקציה. הטריגרים והתיוגים של האפליקציות (לדוגמה, @MyTwoWordApp) הם לא תלויי-רישיות. הפלטפורמה מנרמלת את הקלט של המשתמשים לאותיות קטנות (@mytwowordapp), ל-PascalCase (@MyTwoWordApp) ול-camelCase (@myTwoWordApp).
  • עיצוב השם המוצג. כדי שהשם הרשמי של האפליקציה יוצג בצורה ברורה ברכיבים בממשק המשתמש, צריך לרשום אותו ב-PascalCase או עם רווחים רגילים.
  • טיפול בשגיאות הקלדה. למרות שווריאציות של אותיות רישיות מטופלות באופן אוטומטי, שגיאות הקלדה של תווים (לדוגמה, @mytwowrodapp) מסתמכות על זיהוי כוונה חלופית ולא על התאמת מחרוזת ישירה. המפתחים צריכים לעודד איות מדויק של הכינוי במסמכים.

שימוש בשמות מפורשים של פעלים ושמות עצם

השתמשו בשמות ספציפיים ל-verb_noun והימנעו משמות מעורפלים. לדוגמה, publish_draft עדיף על handle_content.

רמת הפירוט של הכלי

חשוב להקפיד על ההנחיות הבאות לגבי רמת הפירוט של הכלי.

התייחסות לכלים כאל נקודות קצה אטומיות

התייחסו לכלים כאל נקודות קצה אטומיות, בלי תנאים פנימיים או כמה פונקציות עם פרמטרים נדרשים משלהן. כלים מפורטים מאפשרים למודל לשרשר שלבים באופן לוגי, וכך לצמצם הזיות.

שימוש בסכימות שטוחות יותר

אם אתם צריכים אובייקטים עם רמות עמוקות של הטמעה או לוגיקה מורכבת של סכימת oneOf / anyOf כדי לאמת קלט, כנראה שהכלי שלכם רחב מדי.

הקפדה על אמצעי ההגנה של צבירה מראש ו-payload

למרות שהפרוטוקול לא אוכף צבירה מראש של נתונים עבור עומסי נתונים קטנים, בפועל צבירה מראש של נתונים בקצה העורפי נדרשת מאוד כשעובדים עם קבוצות גדולות של רשומות, היסטוריה ארוכה וקבוצות נתונים ממקורות מרובים. פלטפורמת האפליקציות המקושרות אוכפת אמצעי הגנה על מגבלות חלון ההקשר, זמן האחזור של הביצוע ושלבי החשיבה של המודל. כדי לעמוד בהנחיות האלה, צריך לפעול לפי ההוראות הבאות:

  • סינון וסיכום בקצה העורפי. תמיד צריך לסנן, לצבור מראש או לסכם זרמי נתונים גדולים בשרת ה-MCP לפני שמחזירים תשובות למוצרים הרלוונטיים של Google.
  • הימנעו מהעתקה והדבקה של טקסט גולמי. אל תעבירו שורות של מסד נתונים גולמי או יומנים שלמים ללא אינדקס לתוך המטען הייעודי (payload) שהכלי מחזיר.

השמטת כלים פנימיים וכלים של מטא

חשפו רק יכולות שרלוונטיות למודל בתגובת tools/list של השרת:

  • סינון כלי עזר: השמיטו כלים פנימיים, מטא-כלים או כלי ניהול שהמודל לא אמור לקרוא להם (לדוגמה, בדיקות תקינות של השרת, שגרות הגדרה פנימיות או כלי עזר למפתחים).
  • יעילות של חלון ההקשר: החרגה של כלים מיותרים שומרת על סכימת MCP תמציתית, מפחיתה את צריכת הטוקנים בחלון ההקשר ומונעת בלבול בניתוב הכלים של המודל. שרתי MCP שחושפים עשרות כלים או סכימות של "כלי-על" עם רמות עמוקות של היררכיה יסומנו במהלך הבדיקה כדי לתקן אותם.

מה כדאי ומה לא כדאי לעשות כשמגדירים את רמת הפירוט של הכלי

בדוגמאות הבאות מוצגות הנחיות לגבי מה מותר ומה אסור לעשות בנוגע למתן שמות לכלים ולשימוש ברמת הפירוט.

מומלץ לא מומלץ

כלים מפורטים עם שמות ופרמטרים ברורים

סכימת הקלט של כל כלי היא מחמירה. אם ה-LLM רוצה ליצור משתמש, הוא צריך לספק כתובת אימייל. כדי למחוק, צריך לספק מזהה. אין ניחושים.

...
@mcp.tool()
def create_user(email: str, role: str = "viewer") -> str:
    """Register a new user. Returns the new User ID."""
    # Logic is purely creation
    return "user_123"

@mcp.tool()
def delete_user(user_id: str) -> str:
    """Permanently remove a user by their ID."""
    # Logic is purely deletion
    return f"User {user_id} deleted"

@mcp.tool()
def update_user_role(user_id: str, new_role: str) -> str:
    """Change an existing user's permission level."""
    return f"User {user_id} is now {new_role}"

    ...

שם הכלי: manage_user

תיאור: "השתמש בכלי הזה כדי ליצור, לעדכן, למחוק או לאחזר משתמשים".

...
@mcp.tool()
def manage_user(
    action: Literal["create", "update", "delete", "get"],
    user_id: Optional[str] = None,
    email: Optional[str] = None,
    role: Optional[str] = "viewer"
) -> str:
    """
    Use this to manage users.
    WARNING: logic is hidden inside Python, not visible in the schema.
    """
    if action == "create":
        if not email: return "Error: Email required for creation" # Runtime error, not schema error
        return f"Created user {email}"
    elif action == "delete":
        if not user_id: return "Error: User ID required"
        return f"Deleted {user_id}"
    
    return "Action completed"
    """
    ...

הצהרה על הערות של כלים לצורך בטיחות

כדי להעביר את אופן הביצוע ולהפעיל שערי בטיחות מובנים במוצרים הרלוונטיים של Google, צריך להגדיר הערות פרוטוקול בהגדרות של הכלים:

  • שערי אישור בזמן ריצה: מוצרי Google הרלוונטיים משתמשים ב-annotations.destructiveHint: true וב-annotations.openWorldHint: true כדגלים מרכזיים להפעלת הנחיות לאישור משתמש בזמן ריצה. הצהירו על destructiveHint: true בפעולות שמשנות מצב, פעולות כתיבה או פעולות הרסניות, והגדירו את openWorldHint: true לכלים שיוצרים אינטראקציה עם סביבות פתוחות או חיצוניות, כדי שהממשק יבקש מהמשתמש אישור באופן טבעי לפני הביצוע.
  • הנחיה לשאילתה לקריאה בלבד: מגדירים את readOnlyHint: true בכלי שאילתות שרק מאחזרים נתונים בלי לשנות את המצב של הקצה העורפי.
  • ברירות מחדל להערות מפורשות: לפי המפרט של Model Context Protocol, אם משמיטים את readOnlyHint, הלקוחות מניחים שברירות המחדל הן readOnlyHint: false ו-destructiveHint: true מטעמי בטיחות. הצהרה מפורשת על הערות בכל הכלים מבטיחה ניתוב משימות למודלים שניתן לחזות מראש וביצוע בטוח.

תיאורי הכלים

התיאור הוא ההקשר היחיד שיש למודל כדי להחליט אם הכלי יכול לפתור את הבעיה הנוכחית. חשוב להקפיד על ההנחיות הבאות כשכותבים תיאורים:

לכתוב הוראות, לא הערות

כתבו את תיאורי הכלים כהוראות, ולא כהערות בקוד, שלרוב הן פסיביות. מודלים גדולים של שפה (LLM) מגיבים היטב להנחיות.

הסבירו את ה "איך"

תיאור טוב מגשר על הפער בין "יש לי כלי" לבין "אני יודע איך לשלב את הכלי הזה בשיחה".

הסבירו את הסיבה

הסבירו מה ההבדל בין הכלי הזה לכלים דומים – לדוגמה, "השתמשו בכלי הזה למשתמשים פנימיים, וב-customer_update למשתמשים חיצוניים".

אומרים למודל איפה למצוא את הארגומנטים – לדוגמה, "מהכלי order_search".

ציון הפורמט

ציינו יחידות (מטרים לעומת רגל) ופורמטים (תאריכי ISO, גרסאות סמנטיות).

הימנעות משיקול דעת של המודל

אל תנחו את המודל להשתמש ב"שיקול הדעת הטוב ביותר" שלו, ואל תציעו פעולות אופציונליות ללא הנחיות.

דוגמאות לתיאורי כלים

הדוגמאות הבאות מראות מה כדאי ומה לא כדאי לעשות כשכותבים תיאורים של כלים.

מומלץ לא מומלץ

מקור מידע אמין

"עדכון כתובת האימייל של המשתמש. חובה להשתמש ב-UUID "id" שמוחזר מהכלי search_users. אל תסיקו או תנחשו מזהי משתמשים".

(הוא מקשר באופן מפורש את הפלט של כלי אחד לקלט של הכלי הזה.)

"עדכון כתובת האימייל של המשתמש".

(המודל עשוי לנחש מזהה כמו 12345).

פורמט ומגבלה

"קביעת פגישה. התאריך צריך להיות בפורמט ISO 8601‏ (YYYY-MM-DD). אם המשתמש אומר "מחר" או התייחסות יחסית אחרת, צריך לחשב את התאריך על סמך ההקשר הנוכחי".

"קבע פגישה בתאריך הנתון".

(נראה נכון לאדם (לדוגמה, "מחר") אבל נכשל באימות הסכימה (צריך להיות "2025-10-12"))

ציפיות לגבי הפלט

"אחזור של יומני שרת. הפונקציה מחזירה את 50 השורות האחרונות של הטקסט הגולמי. כדי להימנע ממגבלות על אסימונים, כדאי לבקש חלונות זמן קטנים יותר לניתוח הנתונים".

"קבלת יומני שרת".

(יכול להיות שהמודל יפעיל כלי ויצפה לקבל סיכום, אבל יקבל קובץ dump גולמי של JSON בגודל 5MB, מה שעלול לפגוע בחוויית המשתמש).

@mcp.tool()
def update_campaign_status(campaign_id: str, status: str) -> str:
    """
    Promotes or pauses an advertising campaign.
    
    CRITICAL USAGE RULES:
    1. 'campaign_id': Must be the 32-character UUID retrieved from 'list_campaigns'.
    2. 'status': Must be exactly one of: ['active', 'paused', 'archived'].
    
    Returns: A confirmation string with the new status and timestamp.
    """
    # Logic...

    ...

התיאור הזה משמש כמדריך קצר. הוא מטפל במקור (מאיפה לקבל את המזהה), במגבלות (ערכי enum חוקיים) ובפעולה.

@mcp.tool()
def update_campaign_status(id: str, status: str) -> str:
    """
    Updates the campaign status in the database.
    """
    # Logic...

השיטה הזו מסתמכת על שמות המשתנים כדי לבצע את כל העבודה. המודל צריך לנחש מהם הערכים החוקיים של status.

פרמטרים של כלי

בנוסף לכלי עצמו, תארו את הפרמטרים כדי שיהיו חד-משמעיים.

סוגים מפורשים

השתמשו בסוגים ספציפיים וחזקים (string, integer, boolean, array).

שימוש ב-enum לקבוצות של ערכים קבועים

אם פרמטר מקבל רק קבוצה קבועה של ערכים (לדוגמה, daylight, cool, warm), צריך לציין אותם במערך enum. זה משפר באופן משמעותי את הדיוק.

לציין במפורש את הפרמטרים הנדרשים

הגדירו בבירור אילו פרמטרים נדרשים כדי שהפונקציה תפעל.

הפעלת התאמה סמנטית של סכימות

כשמשלבים את האפליקציה, יכול להיות שיהיה צורך בהתאמה של סכימה סמנטית מהפרמטרים של הכלים שלכם לענף שאתם מפתחים בשבילו. במהלך תהליך ההצטרפות תקבלו את הסכימה הצפויה של הענף (סכימת JSON).

דוגמאות לפרמטרים של כלים

בדוגמאות הבאות מוצגות הנחיות לטיפול בפרמטרים של כלים.

מומלץ לא מומלץ

פורמטים ויחידות של ארגומנטים

‫radius: "הרדיוס במטרים. הערך חייב להיות מספר עשרוני שגדול מ-0".

(מונע הזיה של יחידות)

radius: "The radius of the circle."‎

פורמטים והקשר של מזהים

‫user_id: "ה-UUID של מסד הנתונים (לדוגמה, 550e8400-e29b...). אל תשתמשו כאן בכתובות אימייל".

הערה: מומלץ להתייחס לכל שדות המזהים המספריים כערכי מחרוזת. במיוחד אם המזהה יכול להיות באורך של 10 ספרות או יותר, יש סיכון שהוא ייחתך על ידי מערכות פנימיות (ייאלץ להיכנס למאגר של 32 ביט) והגרסה הזו תשמש את המודל בקריאות עתידיות לכלים.

(מונע שגיאות הקשורות לסוג)

‫user_id: "מזהה המשתמש".

ציפיות לגבי ערך ההחזר

"מעדכן את הרשומה ומחזיר את אובייקט ה-JSON המעודכן, כולל חותמת הזמן החדשה".

(ההנחיה הזו אומרת למודל שהוא לא צריך להפעיל פונקציית "get" מיד אחרי ה"update" כדי לאמת את השינוי).

"עדכון הרשומה"


@mcp.tool()
def search_logs(query: str, limit: int = 10) -> str:
    """
    Searches server error logs using Lucene syntax (e.g. 'level:ERROR AND service:auth').
    
    Args:
        query: A Lucene-formatted search string.
        limit: Max results to return. capped at 50.
    
    Returns:
        A formatted string of log entries with timestamps.
    """
    ...
  
@mcp.tool()
def search_logs(query: str, limit: int = 10) -> str:
    """Searches the logs."""
    ...

ה-LLM לא יודע באיזה תחביר "שאילתה" תומכת (SQL? ביטוי רגולרי? טקסט פשוט?) הוא לא יודע מהי "המגבלה" המקסימלית.

תגובות וטיפול בשגיאות

בהתאם לעיקרון הבסיסי של התגובה היא ההנחיה הבאה, הכלי מדווח על תוצאת ההפעלה הבסיסית שלו על ידי החזרת מטען נתונים ייעודי (payload), שמודבק ישירות בחלון ההקשר של ה-LLM. התוצאה של הפעולה קובעת מה יקרה בהמשך:

  • אם הפעולה בוצעה בהצלחה: המודל צריך את ערך ההחזרה כדי לדעת מה קרה ולהחליט מה השלב הבא.
  • אם הוא נכשל: המודל צריך לדעת למה הוא נכשל ואיך לפתור את הבעיה. קריסה (שגיאה 500) עוצרת את השיחה, אבל הודעת שגיאה תיאורית מאפשרת למודל לתקן את עצמו.

לא משנה אם הלוגיקה הבסיסית של הכלי מצליחה או נכשלת, צריך לעצב את המטען הייעודי (payload) של ערך ההחזרה כך שהמודל יוכל לנתח אותו בקלות. כדאי לפעול לפי השיטות המומלצות הבאות כשמארזים את המטען הייעודי (payload) של התגובה.

שימוש ב-JSON

פורמט של נתונים מובְנים ב-TextContent (מגבלה זמנית). ‫structuredContent עדיין לא נתמך ב-Connected Apps Platform, לכן צריך לבצע סריאליזציה של הנתונים באופן ידני. גם אם התשובה היא רשימה פשוטה, json.dumps() אותה.

הכללת כתובות URL בתשובה

כתובות ה-URL שמוחזרות צריכות להיות קצרות יחסית ובלי הרבה פרמטרים. מומלץ להשתמש בשירותים לקיצור כתובות URL כדי לחסוך במספר הטוקנים ולהפחית את הסיכון להזיות.

מטענים ייעודיים (payloads) למניעת הזיות שמתארים את עצמם

תמיד צריך לשייך קודים גולמיים או מזהים פנימיים לשמות תצוגה קריאים לאנשים, ליחידות מדידה מפורשות ולטווחי ייחוס. אל תחזירו מפתחות מילון דחוסים או קודים מספריים לא ממופים שמאלצים את המודל להסיק את ההקשר.

הטמעה של טיפול יעיל בשגיאות

החזירו הודעות שגיאה ברורות ומשמעותיות כדי שהמודל יוכל להבין מה השתבש וליידע את המשתמש. איך מטפלים בשגיאות ב-MCP

שימוש ב-try/except

עוטפים את הלוגיקה של הכלי בבלוקים של try/except ומחזירים שגיאות כמחרוזות.

הצגת שגיאות שמאפשרות נקיטת פעולה

הציעו את השלב הבא בהודעת השגיאה (לדוגמה, "נסו להשתמש קודם בכלי X").

אשר פעולות

אל תחזירו מחרוזות ריקות לכלים עם השפעות משניות (יצירה/עדכון/מחיקה).

דוגמאות לתגובות ולטיפול בשגיאות

בדוגמאות הבאות מוצגות הנחיות לגבי מה כדאי לעשות ומה לא כדאי לעשות בנוגע לתגובות ולטיפול בשגיאות.

מומלץ לא מומלץ

סידור פרקים מפורש


...
import json

@mcp.tool()
def query_metrics(metric_id: str) -> str:
    result = {"id": metric_id, "value": 42, "unit": "ms"}
    # GOOD: Returns '{"id": "cpu", "value": 42}' -> Valid JSON
    return json.dumps(result, indent=2)

...
@mcp.tool()
def query_metrics(metric_id: str) -> str:
    result = {"id": metric_id, "value": 42, "unit": "ms"}
    # BAD: Returns "{'id': 'cpu', 'value': 42}" -> Invalid JSON
    return str(result)

תפיסה ודיווח


...
@mcp.tool()
def get_user_details(user_id: str) -> str:
    try:
        user = db.get_user(user_id)
        if not user:
             # GOOD: Informative error returned as content
            return f"Error: User with ID '{user_id}' not found. Please verify the ID using 'search_users'."
        return json.dumps(user)
    except Exception as e:
        return f"Error: Database connection failed ({str(e)}). Please try again later."

(הכלי "מצליח" מבחינה טכנית (מחזיר מחרוזת), אבל המחרוזת מכילה את פרטי השגיאה. המודל קורא את זה, מבין שהמזהה לא קיים ויכול לבקש מהמשתמש את המזהה הנכון.


...
@mcp.tool()
def get_user_details(user_id: str) -> str:
    # BAD: Unhandled exception if ID not found
    user = db.get_user(user_id)
    return json.dumps(user)

(אם get_user נכשל, השרת מחזיר שגיאה 500. ה-LLM מקבל שגיאת הפעלה כללית ולא יודע למה (האם המזהה היה שגוי? מסד הנתונים לא פועל? אין הרשאה?). סביר להניח שהוא ינסה שוב עם אותו קלט שגוי).

תשובות ריקות

...
@mcp.tool()
def post_story(story_content: str) -> str:
    service_name = "story_service"
    api_client.post("/stories", json={"content": story_content})
    # GOOD: Explicit confirmation of state change.
    return f"Service '{service_name}' successfully posted content. Status is now 'posted'."

...
@mcp.tool()
def post_story(storyContent: str):
    subprocess.post(["postsrv", "story", storyContent])
    # BAD: Returns null/empty string. Model is confused.

מודלים גדולים של שפה (LLM) מתבלבלים לפעמים כשהם מקבלים תשובות ריקות. הם עלולים להזות את התשובה "הכלי נכשל" או פשוט לחזור על הקריאה.

מטען ייעודי (payload) שמתאר את עצמו למניעת הזיות

תמיד צריך לשייך קודים גולמיים או מזהים פנימיים לשמות תצוגה קריאים לאנשים, ליחידות מידה מפורשות ולטווחי ייחוס רגילים.

{"lab_code": "2345-7", "display_name": "Glucose [Mass/volume] in Blood", "value": 105, "unit": "mg/dL", "reference_range": "70-99 mg/dL"}

(כך המודל יודע בדיוק מה המשמעות של הערך, בלי להסיק מהן יחידות המידה או ספי הייחוס).

מזהים גולמיים, דחיסה בהתאמה אישית או קודים לא ממופים

החזרת מזהים פנימיים גולמיים, קיצורים של מילונים מותאמים אישית או קודים מספריים ללא תוויות.

{"code": "2345-7", "v": 105}

(המודל נאלץ לנחש למה המספר 105 מתייחס, מה שמוביל להזיות לגבי יחידות, להקשר חסר או להסברים לא מדויקים).

טיפול בשגיאות MCP

חשוב מאוד לטפל בשגיאות בצורה חלקה.

  • בשגיאות שאפשר לתקן (כמו מזהה משתמש לא חוקי או פרמטר אופציונלי חסר), מחזירים מחרוזת טקסט רגילה שמכילה פרטים תיאוריים של השגיאה בתגובת הכלי. כך המודל יכול לבדוק את המשוב, להבין מה השתבש ולתקן את עצמו או לבקש מהמשתמש הבהרה.
  • במקרה של שגיאות סופיות (כמו הגבלת קצב של יצירת בקשות, כשלים באימות או בהרשאות, או הפסקות זמניות בפעילות של שרת בק-אנד), צריך להעלות McpError עם קוד השגיאה המתאים כדי שהפלטפורמה תוכל לטפל בכשל באופן שיטתי.

דוגמה לגוף תגובה של שגיאה (JSON)

{
  "jsonrpc": "2.0",
  "error": {
    "code": -32302,
    "message": "User permission denied for the requested operation.",
    "data": null
  },
  "id": 1
}

השדה Message מכיל קובץ dump בפורמט JSON של השדה ErrorData של ה-MCP. כשהפלטפורמה של האפליקציות המקושרות מקבלת את הערכים הנכונים של code ו-message, היא יכולה לקרוא את הודעת השגיאה ולהעביר למשתמש הסבר מועיל בשפה טבעית. לדוגמה, "סליחה, לא הצלחתי למצוא את המקום עם המזהה הזה. אפשר לבדוק את השם?"

פרוטוקול MCP מאפשר ללקוחות להתחבר לשרתי MCP באמצעות מפרט JSON-RPC 2.0. ב-JSON-RPC יש שגיאות מסוימות שמוגדרות מראש ונשלחות במקרים של שגיאות נפוצות, כמו בקשה לא תקינה, שגיאות ניתוח וכו'. במדריך הזה מוסבר איך שרתי MCP יכולים לשלוח בחזרה שגיאות בהתאמה אישית.

קוד
סטטוס
הודעה שימוש צריך להחזיר (
return
) באופן מפורש?
שגיאות של משתמשים או לקוחות
-32300 USER_RATE_LIMITED המשתמש הגיע למגבלת השימוש המקסימלית. כן
-32301 MISSING_REQUIRED_INFORMATION בבקשת הקלט אין את כל המידע הדרוש כן
-32302 USER_PERMISSION_DENIED המשתמש לא נתן הרשאה להשתמש בכלי. לדוגמה, אם למשתמשים אין חשבון ארגוני, אם הם לא עומדים בהגבלת הגיל, אם הם נמצאים במיקום מסוים וכו', או אם אין להם מינוי ארגוני לכלי. כן
שגיאות באפליקציה או בלוגיקה העסקית
-32400 RUNTIME_ERROR הפעלת קוד השרת גרמה לשגיאה כן
-32401 NULL_POINTER_EXCEPTION ניסיון להפעיל מצביע/אובייקט מסוג null כן
-32402 OUT_OF_MEMORY אין מספיק זיכרון בקוד השרת כדי להקצות לאובייקט כן
שגיאות בתשתית
-32500 DEADLINE_EXCEEDED הבקשה נמשכת יותר מהזמן המותר. יכולות להיות לכך הרבה סיבות, למשל עומס יתר בשרת, בעיות ברשת וכו'. כן
-32501 RESOURCE_EXHAUSTED בשרת נגמר הזיכרון, המקום בכונן, השרשורים, זמן המעבד (CPU) וכו'. כן
-32502 SERVICE_UNAVAILABLE שירות תלוי (למשל, מיקרו-שירות אחר, מסד נתונים, מטמון וכו') לא זמין כן
שגיאות JSON-RPC (השגיאות האלה הן חלק מהעברת MCP)
-32700 PARSE_ERROR השרת לא הצליח לנתח את הבקשה לא
-32600 INVALID_REQUEST בקשת לקוח בפורמט שגוי לא
-32601 METHOD_NOT_FOUND שם לא תקין של כלי MCP לא
-32602 INVALID_PARAMS פרמטרים לא תקינים של בקשה, כולל פרמטרים חסרים או סוגי פרמטרים לא תואמים לא
-32603 INTERNAL_ERROR תשובת ברירת המחדל לא

בדוגמה הבאה מוסבר איך להעלות שגיאת MCP בשרת באמצעות ערכת ה-SDK הרשמית של Python ‏(mcp). מעלים McpError שמכיל מטען ייעודי (payload) מסוג ErrorData, שערכת ה-SDK מבצעת לו סריאליזציה באופן אוטומטי לפורמט הנדרש של שגיאת JSON-RPC, עם סטטוס השגיאה.

from mcp import types
from mcp.shared.exceptions import McpError

@mcp.tool()
def foo_tool() -> list[types.TextContent]:
  """Always returns an error."""
  raise McpError(
    types.ErrorData(
        code=-32302, # USER_PERMISSION_DENIED
        message="Message to show to the model."
    ),
  )

הקשר הכלי

מוצרי Google הרלוונטיים תומכים ב-Tool Context API כדי להעביר אותות לשרתי MCP. ה-API הזה משמש בתרחישים תקינים שדורשים מידע רגיש – לדוגמה, מטא-נתונים שלא נכללים בהגדרה של כלי הליבה, כמו במקרה של הגדרת מיקום לכלי שצריך להתאים לשוק המקומי. ה-API של Tool Context חשוף רק דרך Connected Console.

כשרושמים אות כמו current_user_location_fine באפליקציה ב-Connected Console, מוצרי Google הרלוונטיים מוסיפים לבקשות MCP tools/call רשומה נוספת של _meta שמספקת את הנתונים המבוקשים. אלה האותות הנתמכים:

  • current_user_location_fine (רק ב-Gemini, בענפים מותרים)
  • user_locale
  • current_user_location_coarse
{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "name": "find-restaurant",
    "arguments": {"query": "restaurants near me"},
    "_meta": {
      "current_user_location_fine": {
        "latitude_degrees": 37.7749,
        "longitude_degrees": -122.4194,
        "accuracy_meters": 112.4221
      },
      "user_locale": {
        "language_code": "en",
        "region_code": "US"
      }
    }
  }
}

כדי לפענח את הנתונים האלה:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("remote_mcp")

@mcp.tool()
async def find_restaurants(query: str, ctx: Context) -> str:
   # Access context directly from _meta
   request_context = ctx.request_context
   meta_dict = ctx.request_context.meta.model_dump() if ctx.request_context.meta else {}

   location_context = meta_dict.get("current_user_location_fine", {})
   lat = location_context.get("latitude_degrees")
   lng = location_context.get("longitude_degrees")
   if lat and lng:
       return f"Finding '{query}' near ({lat}, {lng})"
   return f"Finding '{query}' (no location provided)"

עיבוד של חוויית המשתמש (UX)

אפליקציות MCP

מוצרי Google הרלוונטיים תומכים בשילובים של אפליקציות MCP בתהליכים נבחרים שעוברים המשתמשים, כדי לאפשר פיתוח של ממשקי משתמש בהתאמה אישית. כדי לקבל הוראות כלליות לשילוב, פועלים לפי המפרט.

השילוב של אפליקציות MCP במוצרים הרלוונטיים של Google כולל את ההסתייגויות הבאות.

הטמעת משאבים בזמן הרישום

מוצרי Google הרלוונטיים מאחזרים משאבי ממשק משתמש במהלך הטמעת הכלים, בדומה לרשימת הכלים ולתיאורי הכלים. זה אומר שכל עדכון במשאבים (למשל, שינויים ב-JavaScript) לא יזוהה באופן אוטומטי, ויהיה צורך להטמיע מחדש את הכלי.

הגודל של משאב ממשק משתמש יחיד לא יכול להיות יותר מ-15MB, והגודל המצטבר של משאבי ממשק המשתמש בשרת לא יכול להיות יותר מ-100MB.

משאבי ממשק המשתמש חייבים להשתמש באחד מסוגי ה-MIME הנתמכים: text/html,‏ text/javascript,‏ text/css או text/html;profile=mcp-app. סוגי MIME לא סטנדרטיים או ספציפיים לפלטפורמה ייכשלו באימות כשיועברו לתצוגה מקדימה.

הנחיות בנושא CSP

מוצרי Google הרלוונטיים פועלים לפי המפרט הרשמי של אפליקציות MCP, שכולל את CSP‏ [1], [2], ויחסמו כל בקשה שמפרה את ההנחיות של CSP.

במוצרים רלוונטיים של Google, צריך גם להוסיף את blob: ו-data: ל-CSP, אם משתמשים בו. הם לא יתווספו כברירת מחדל. המפתחים יכולים לבחור אם להוסיף אותם ל-CSP או לא.

Script-src הוא חריג

ההוראות היחידות שאנחנו מאפשרים הן: unsafe-inline (נוספת כברירת מחדל), wasm-unsafe-eval ו-data: (אם היא כלולה ב-resource_domains). אם iframe טוען סקריפטים חיצוניים, אפשר לפתור את הבעיה על ידי הוספת JS ל-HTML או שימוש ב-Subresource Integrity (SRI) Hash.

  • אפשרות 1: הטמעה של JS בתוך השורה או בחבילה ב-HTML (הכי פשוט)

    • קוד JS של החבילה:

      • מטמיעים את התוכן של component-init.js ישירות בתוך תגי <script> במטען הייעודי (payload) של ה-HTML שמוחזר למשאב של ממשק המשתמש:

        <script>
        // Paste component-init.js content directly here
        </script>
        
    • הסרת תגי <script src> מרחוק

      • מוחקים <script src="https://api.mycompany.com/..."> הפניות ממסמך ה-HTML.
    • כלי להטמעה מחדש או לעדכון

  • אפשרות 2: שימוש ב-Subresource Integrity (SRI) Hash:

    צריך להשתמש באפשרות הזו אם הסקריפט חייב להישאר מאוחסן באופן חיצוני בכתובת https://api.company.com/....

    • חישוב גיבוב (hash) מסוג SHA-256 של הסקריפט
      • יוצרים את גיבוב (hash) ה-SHA-256 ב-base64 של component-init.js
    • צריך להוסיף את הערך של מאפיין ה-Hash אל resourceDomains (חובה לכלול את הקידומת sha256- כדי להתאים למאפיין integrity)
    • עדכון תג HTML <script>
      • מוסיפים את המאפיינים integrity ו-crossorigin לתג הסקריפט בווידג'ט ה-HTML.
    • אימות של כותרת CORS ב-CDN או בשרת
      • צריך לוודא שהדומיין api.company.com מציג את component-init.js עם Access-Control-Allow-Origin: * (או מאפשר scf.usercontent.goog) כדי שהדפדפן יוכל לקרוא את גוף התגובה לאימות SRI.
    • כלי להטמעה מחדש או לעדכון

הנחיות אבטחה לתיאור של כלי MCP

התיאור הוא ההקשר היחיד שיש למודל כדי להבין את היכולות של הכלי, ולכן צריך לכתוב אותו בצורה מדויקת ומאובטחת כדי למנוע התנהגות לא מכוונת. כשאתם מנסחים את תיאורי הכלים, חשוב לפעול לפי ההנחיות הבאות.

  • תארו את הפונקציונליות, אבל אל תכתיבו את ההתנהגות. התיאור חייב לתאר באופן מדויק מה הכלי עושה, ולא להורות למודל לבצע פעולות נוספות.
  • הגדרת ההיקף והדרישות. ציינו בבירור את המטרה העיקרית של הכלי, את הנסיבות הספציפיות (מתי) שבהן צריך להשתמש בו ואת כל הקלט הנדרש (פרמטרים או ארגומנטים).
  • הקפידו על אמיתות. התיאור חייב לייצג בצורה מדויקת את הקוד שעליו הכלי מבוסס. אל תטענו שכלי מסוים הוא לקריאה בלבד אם הוא מבצע פעולת כתיבה או מחיקה.

סיכוני אבטחה ואיך להימנע מהם

אזור מסוכן מומלץ הימנעו מהשיטה הזו בכל מחיר

החדרת פרומפטים

השתמשו בשפה אובייקטיבית והצהרתית כדי לציין בבירור את המטרה והפונקציונליות של הכלי.

להשתמש בפקודות ציווי כדי לשנות את ההתנהגות של המודל או את תהליכי המערכת (לדוגמה, "אתה חייב להגיד...", "אחרי הריצה, חובה..."). מותר להשתמש במונחים שמתארים חובה, כמו "חובה" או "קריטי", רק כשמגדירים אילוצים של פרמטרים מובְנים או כללי שימוש.

השתמשו בעיצוב רגיל ופשוט לטקסט של תיאור הכלי.

להשתמש בעיצוב שמושך תשומת לב – לדוגמה, שימוש מוגזם באותיות רישיות ובתגים כמו VERY IMPORTANT: או **CRITICAL**.

התמקדו רק בפונקציה של הכלי ובהתנהגות הצפויה שלו.

לכלול הוראות למשחק תפקידים או פקודות להתעלמות מהוראות קודמות.

הצללה וחטיפה של כלים

חשוב לוודא שהתיאור ספציפי ומוגבל ליכולות הקשורות בפועל של הכלי.

לכתוב תיאור רחב מדי או מעורפל, או לטעון שכלי אחד מבצע הרבה פעולות לא קשורות.

בחרו שם ייחודי, תיאורי והגיוני לכלי.

להשתמש בשם של כלי שהוא וריאציה קלה של כלי מהימן, או בשם גנרי (לדוגמה, do_everything_tool, assistant_tool).

אל תציינו בתיאור שמות של אפליקציות אחרות או של כלים של פלטפורמות חיצוניות.

להפנות באופן מפורש לכלים אחרים או ליצור כללים חדשים לגבי התזמון או אופן השימוש בכלים אחרים.

מאפשרים למתכנן של המודל לבחור את הכלי המתאים ביותר על סמך ההקשר של המשתמש.

לכלול שפה שפוגעת בתחרות או כל סוג של הנחיית SEO שמורה למודל להעדיף את הכלי שלכם על פני כלים דומים.

מניפולציה של טריגרים

התיאור לא מתייחס לביטויים כלליים מהיסטוריית השיחות ולא מגיב להם.

ליצור לוגיקה מותנית שמפעילה פעולה מזיקה על סמך ביטויים נפוצים ולא מזיקים של משתמשים (לדוגמה, "תודה", "לסיכום").

ניצול לרעה של פרמטרים

צריך להגדיר רק את הפרמטרים שנדרשים לפונקציה של הכלי, ולהשתמש בשמות ספציפיים לנתוני הקלט (לדוגמה, file_id, search_term).

הגדירו פרמטרים של פונקציות עם שמות שמשקפים את המצב הפנימי של הנציג (לדוגמה, system_prompt,‏ conversation_history,‏ full_context).

זליגת נתונים

שמירה על פרטיות כבר בשלב התכנון – מזהים אטומים ואימות שמנוהל על ידי המארח.

צריך להשתמש במזהים לא רגישים, ולא בפרטים אישיים מזהים (PII) גולמיים. כל הטיפול בנתונים חייב להתבצע בגבולות מאובטחים ומורשים, ואסור לציין בתיאור הציבורי שהנתונים נשלחים לגורם חיצוני. ההרשאות להפעלת הכלי יועברו באופן שקט באמצעות לחיצת יד של OAuth.

לפני ששולחים מידע רגיש למוצרי Google הרלוונטיים, צריך להסיר ממנו את התוכן הזדוני או הרגיש.

לבקש מהמשתמש פרטים אישיים מזהים (PII), מידע בריאותי מוגן (PHI) או כל מידע אישי ו/או רגיש אחר, נתונים אישיים או עסקיים או ישות בכל תפקיד שמפר את התנאים וההגבלות של מוצרי Google הרלוונטיים.

להזכיר או לדרוש שליחה של נתוני משתמשים (שאילתה, מיקום, הקשר) לכתובות URL לא מורשות של צד שלישי, לשירותי רישום ביומן או למערכות חיצוניות.

שיטות מומלצות לפונקציונליות ולמתן שמות

בנוסף לאבטחת התיאור של הכלי, אתם צריכים לוודא שהמודל יכול לבחור ולהפעיל אותו בצורה מהימנה בלי להתבלבל. חשוב לפעול לפי השיטות המומלצות הבאות בנוגע לפונקציונליות ולמתן שמות:

  • דיוק הפרמטרים. חשוב לוודא שכל השמות והסוגים של הפרמטרים בתיאור תואמים בדיוק להטמעה בפועל של הכלי.
  • מתן שמות הגיוניים. שם הכלי צריך לרמוז בצורה ברורה על הפונקציה שלו. אל תשתמשו בשמות כלליים מדי כמו "execute". השם צריך להיות עקבי עם השמות של הכלים האחרים בסביבה העסקית.

נספח: הוספה לרשימת ההיתרים של התשתית והרשת

אם תשתית האירוח, API Gateway או חומת האש מגבילים את החיבורים הנכנסים לפי כתובת ה-IP של המקור, צריך להוסיף לרשימת ההיתרים את בלוקי ה-CIDR הבאים של Google לתעבורת נתונים יוצאת:

  • 108.177.64.0/20
  • 142.250.88.0/22
  • 172.217.80.0/20
  • 192.178.20.0/22
  • 192.179.0.0/20
  • 74.125.232.0/24
  • 136.121.40.0/21

חשוב לוודא שהסביבה שלכם מאפשרת תנועה מטווח ה-IP האלה ביציאת HTTPS‏ 443, כדי שמוצרי Google הרלוונטיים יוכלו להגיע לשרת ה-MCP המרוחק שלכם לצורך אתחול MCP, גילוי כלים וביצוע בקשות.