Normes d'intégration des applis connectées MCP

Le serveur MCP établit le framework permettant de connecter les fonctions de votre application (outils MCP) à la Connected Apps Platform. Pour lui permettre de sélectionner, d'appeler et de traiter les résultats de votre service de manière plus fiable, votre configuration MCP doit respecter strictement les normes suivantes.

Principes directeurs

Pour chaque fonction, concentrez-vous sur l'intention utilisateur et les cas d'utilisation, et non sur les capacités de la fonction. La description est le principal moyen d'indiquer au modèle à quoi sert votre outil et à quels cas d'utilisation il peut répondre.

Gestion des versions

Pour assurer des déploiements MCP évolutifs et robustes, adoptez une architecture d'URI structurée qui utilise le contrôle des versions basé sur le chemin d'accès (par exemple, /v1, /v2). Cela vous permet de maintenir la rétrocompatibilité et de contrôler les nouvelles fonctionnalités. En complétant cela avec des sous-domaines spécifiques au fournisseur, tels que https://gemini.mcp.company.com/mcp/v1, vous pouvez gérer le trafic de manière précise et optimiser les définitions d'outils adaptées au contexte et aux comportements de traitement uniques des différents modèles d'IA.

Compatibilité des versions du protocole MCP

La plate-forme Connected Apps est compatible avec la spécification du protocole MCP (Model Context Protocol) jusqu'à la version 2025-11-25. Les versions plus récentes des spécifications ne sont pas encore prises en charge.

  • Responsabilité du développeur : Vous devez vous assurer que votre serveur MCP respecte strictement une version de protocole compatible avec la plate-forme Connected Apps (2025-11-25) lors du handshake initialize et dans toutes les définitions d'outils et de schémas.
  • Rétrocompatibilité de la plate-forme : à mesure que la Connected Apps Platform adoptera de nouvelles versions de la spécification MCP, notre client maintiendra la rétrocompatibilité avec les versions de protocole précédemment prises en charge, afin que les intégrations de production existantes continuent de fonctionner sans interruption.
  • Gérer les mises à niveau : lorsque vous êtes prêt à adopter une spécification MCP récemment compatible ou à introduire des modifications de schéma, exposez ces mises à jour sur un nouveau chemin d'URI avec version (par exemple, /mcp/v2) tout en conservant votre point de terminaison existant (/mcp/v1) pour le trafic actif.

Les modifications apportées aux schémas MCP sont autorisées entre les versions de l'application. Nous vous recommandons d'exploiter cette fonctionnalité et de gérer les versions des points de terminaison MCP pour permettre un déploiement progressif des nouvelles fonctionnalités, ou de vous appuyer strictement sur des modifications rétrocompatibles.

Spécification du protocole de transport

La plate-forme Connected Apps est strictement compatible avec la version 2025-03-26 et ultérieure de la spécification du protocole de contexte de modèle de transport HTTP Streamable. Il n'est pas compatible avec l'ancien transport HTTP avec SSE décrit par la spécification du 05/11/2024.

  • Point de terminaison HTTP unique Le point de terminaison MCP fourni dans la Connected Console (par exemple, https://api.example.com/mcp) est l'URL unique vers laquelle les produits Google concernés envoient toutes les requêtes JSON-RPC (initialize, tools/list, tools/call) via une requête HTTP POST standard.
  • Streaming SSE dans un flux HTTP. L'ancien transport SSE multipoint de terminaison n'est pas pris en charge, mais les événements envoyés par le serveur, tels que text/event-stream, sont pris en charge dans le transport HTTP diffusable. Les requêtes sortantes des produits Google concernés incluent Accept: application/json, text/event-stream, ce qui signifie que votre serveur peut renvoyer une charge utile application/json standard ou diffuser des réponses incrémentielles à l'aide de Content-Type: text/event-stream directement dans le corps de la réponse HTTP POST.
  • Flux GET et 405 Méthode non autorisée. Les clients peuvent tenter d'établir un flux GET facultatif sur le point de terminaison pour les notifications de serveur à client. Si votre serveur est sans état ou ne gère que les requêtes-réponses, le renvoi de HTTP 405 Method Not Allowed est explicitement accepté et géré correctement par le proxy client du produit Google concerné.

Instructions du serveur

La plate-forme Connected Apps est optimisée pour ingérer les instructions du serveur, ce qui permet de contrôler le comportement du modèle d'une manière qui n'est pas possible par d'autres moyens.

Suivez les instructions du serveur.

Traiter comme une "indication de modèle" avec un contexte d'utilisation

Suivez ces consignes pour fournir des indications aux modèles.

  • Rédigez des instructions sous la forme d'un "indice" ou d'un guide général pour aider le LLM à comprendre l'objectif et les capacités globales du serveur.
  • Décrivez ce qu'il peut faire, au lieu de lister les fonctionnalités ou de décrire comment le modèle doit utiliser les outils et les ressources du serveur. Si le modèle comprend correctement le "quoi", il peut déterminer le "comment" de manière assez précise en fonction du parcours utilisateur.
  • Partez du principe que ce texte sera ajouté directement à l'invite système du modèle. Soyez clair, directif et efficace en termes de jetons.

Complétez, ne dupliquez pas

Utilisez cet espace pour le contexte global qui s'applique à tous les outils, en évitant les redondances avec les descriptions d'outils individuels.

Exemples d'instructions de serveur

Les exemples suivants montrent ce qu'il faut faire et ne pas faire pour rédiger correctement des instructions de serveur.

Recommandé Non recommandé

Tu es un responsable de dépôt GitHub spécialisé. Ce serveur fournit un accès approfondi aux métadonnées du dépôt, au suivi des problèmes et aux workflows de demande d'extraction. Utilisez-le pour maintenir l'état du projet, automatiser le tri et garantir le respect des normes de code. Sauf indication contraire, toutes les actions sont effectuées dans le contexte de l'organisation authentifiée. Priorisez l'identification des threads obsolètes ou des RP non associées pour que le dépôt reste organisé.

Concises, directives et complémentaires au modèle

  • Définit le "quoi" (état du projet, tri) plutôt que le "comment"
  • Mentionne le champ d'application de l'authentification qui s'applique à tous les outils

Ce serveur dispose d'outils pour GitHub. Vous devez utiliser l'outil list_issues lorsque l'utilisateur demande des problèmes. Vous pouvez utiliser create_pull_request pour créer une demande d'extraction. Utilise ces outils avec précaution pour aider l'utilisateur à gérer son code. Vérifiez toujours le nom du dépôt avant d'appeler un outil. Si l'utilisateur demande un résumé, appelez d'abord les outils, puis résumez le résultat.

  • ne répertoriez pas les noms des outils,
  • Ne dites pas au modèle "comment" penser, car cela peut entrer en conflit avec son raisonnement intégré, qui utilisera le contexte de l'utilisateur pour faire le bon choix.
  • n'explique pas la nature de l'accès du serveur ni ses contraintes spécifiques)

Consignes d'utilisation des outils

Les consignes suivantes décrivent les bonnes pratiques pour créer des configurations de serveur MCP pour différentes fonctions ou outils de votre application.

Conventions d'attribution de noms aux outils

Respectez les consignes suivantes pour nommer votre outil :

Utiliser des noms intuitifs et lisibles par l'humain

Utilisez des noms lisibles par l'humain, avec des significations claires et intuitives, plutôt que des noms ambigus. Par exemple, get_user_information est plus direct que userInfo.

Respectez la casse appropriée

Respectez les règles de casse suivantes pour les noms de fonctions d'outil et les déclencheurs d'application :

  • Casse des fonctions d'outil. Utilisez snake_case ou camelCase pour les noms de fonctions d'outils définis dans votre schéma MCP (par exemple, get_user_information ou publishDraft).
  • Boîtier de la poignée de déclenchement de l'application. Les déclencheurs et les mentions d'applications (par exemple, @MyTwoWordApp) ne sont pas sensibles à la casse. La plate-forme normalise les entrées utilisateur en minuscules (@mytwowordapp), PascalCase (@MyTwoWordApp) et camelCase (@myTwoWordApp).
  • Mise en forme du nom à afficher Enregistrez le titre officiel de votre application en utilisant le PascalCase ou des espaces standards pour un affichage visuel clair dans les éléments d'interface utilisateur.
  • Gestion des fautes de frappe Bien que les variations de casse soient gérées automatiquement, les fautes de frappe (par exemple, @mytwowrodapp) reposent sur la reconnaissance de l'intent de remplacement plutôt que sur la correspondance directe de chaînes. Les développeurs doivent encourager l'orthographe exacte des identifiants dans la documentation.

Utiliser une dénomination explicite verbe-nom

Utilisez un nom verb_noun spécifique et évitez toute ambiguïté. Par exemple, publish_draft est préférable à handle_content.

Précision de l'outil

Respectez les consignes suivantes concernant la précision des outils.

Traiter les outils comme des points de terminaison atomiques

Traitez les outils comme des points de terminaison atomiques sans conditions d'outil internes ni fonctionnalités multiples avec les paramètres requis respectifs. Les outils précis permettent au modèle d'enchaîner les étapes de manière logique, ce qui réduit les hallucinations.

Utiliser des schémas plus plats

Si vous avez besoin d'objets profondément imbriqués ou d'une logique de schéma oneOf/anyOf complexe pour valider les entrées, votre outil est probablement trop vaste.

Observer les garde-fous de pré-agrégation et de charge utile

Bien que la pré-agrégation des données ne soit pas strictement imposée par le protocole pour les charges utiles de petite taille, elle est fortement requise en pratique lorsque vous travaillez avec des ensembles d'enregistrements volumineux, un historique longitudinal et des ensembles de données multisources. La plate-forme Connected Apps applique des garde-fous concernant les limites de la fenêtre de contexte, la latence d'exécution et les étapes de raisonnement du modèle. Pour respecter ces garde-fous, suivez ces consignes :

  • Filtrer et résumer sur le backend Filtrez, pré-agrégiez ou résumez toujours les flux de données volumineux sur votre serveur MCP avant de renvoyer des réponses aux produits Google concernés.
  • Évitez les dumps bruts. Ne videz jamais les lignes de base de données brutes ni les journaux non indexés complets dans la charge utile de retour de l'outil.

Omettre les outils internes et de métadonnées

N'exposez que les fonctionnalités destinées au modèle dans la réponse tools/list de votre serveur :

  • Filtrer les outils d'aide : omettez tous les outils internes, administratifs ou de métadonnées qui ne sont pas destinés à être appelés par le modèle (par exemple, les vérifications de l'état du serveur, les routines de configuration internes ou les outils d'aide pour les développeurs).
  • Efficacité de la fenêtre de contexte : l'exclusion des outils inutiles permet de garder votre schéma MCP concis, de réduire la consommation de jetons de la fenêtre de contexte et d'éviter toute confusion dans le routage des outils du modèle. Les serveurs MCP exposant des dizaines d'outils ou des schémas de "méga-outils" profondément imbriqués seront signalés lors de l'examen pour correction.

Bonnes pratiques et pratiques interdites concernant la précision des outils

Les exemples suivants montrent les bonnes et mauvaises pratiques concernant l'attribution de noms aux outils et l'utilisation de la précision.

Recommandé Non recommandé

Outils précis avec des noms et des paramètres clairs

Le schéma d'entrée de chaque outil est strict. Si le LLM souhaite créer un utilisateur, il doit fournir une adresse e-mail. Si elle souhaite supprimer un élément, elle doit fournir un ID. Il n'y a pas de devinettes.

...
@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}"

    ...

Nom de l'outil : manage_user

Description : "Utilisez cet outil pour créer, modifier, supprimer ou récupérer des utilisateurs."

...
@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"
    """
    ...

Déclarer des annotations d'outils pour la sécurité

Configurez des annotations de protocole dans vos définitions d'outils pour transmettre le comportement d'exécution et déclencher des barrières de sécurité intégrées dans les produits Google applicables :

  • Portes de confirmation d'exécution : les produits Google concernés utilisent annotations.destructiveHint: true et annotations.openWorldHint: true comme indicateurs clés pour déclencher des invites de confirmation de l'utilisateur lors de l'exécution. Déclarez destructiveHint: true sur les actions de modification d'état, d'écriture ou destructives, et définissez openWorldHint: true pour les outils qui interagissent avec des environnements en monde ouvert ou externes afin que la surface demande nativement à l'utilisateur de confirmer avant l'exécution.
  • Indication de requête en lecture seule : définissez readOnlyHint: true sur les outils de requête qui ne font que récupérer des données sans modifier l'état du backend.
  • Valeurs par défaut des annotations explicites : conformément à la spécification du protocole MCP (Model Context Protocol), l'omission de readOnlyHint amène les clients à supposer readOnlyHint: false et destructiveHint: true par défaut pour des raisons de sécurité. La déclaration explicite des annotations sur tous les outils garantit un routage prévisible vers les modèles et une exécution sécurisée.

Descriptions des outils

La description est le seul contexte dont dispose le modèle pour décider si votre outil peut résoudre le problème actuel. Respectez les consignes suivantes pour rédiger des descriptions :

Rédigez des instructions, pas des commentaires

Rédigez les descriptions des outils sous forme d'instructions, et non de commentaires de code, qui sont souvent passifs. Les LLM répondent bien aux directives.

Expliquez le "comment"

Une bonne description comble le fossé entre "Je dispose d'un outil" et "Je sais comment intégrer cet outil dans une conversation".

Expliquez le "pourquoi"

Distinguez cet outil d'outils similaires. Par exemple, "Utilisez cet outil pour les utilisateurs internes, utilisez customer_update pour les utilisateurs externes".

Indiquez au modèle où trouver les arguments (par exemple, "à partir de l'outil order_search").

Spécifier le format

Spécifiez les unités (mètres ou pieds) et les formats (dates ISO, versions sémantiques).

Éviter la discrétion du modèle

N'indiquez pas au modèle d'utiliser son "meilleur jugement" ni de suggérer des actions facultatives et non guidées.

Exemples de descriptions d'outils

Les exemples suivants montrent ce qu'il faut faire et ne pas faire lors de la rédaction des descriptions d'outils.

Recommandé Non recommandé

Source de référence

"Met à jour l'adresse e-mail d'un utilisateur. Vous devez impérativement utiliser l'UUID "id" renvoyé par l'outil search_users. Ne déduisez pas ni ne devinez les ID utilisateur."

(Il associe explicitement la sortie d'un outil à l'entrée de celui-ci.)

"Modifie l'adresse e-mail de l'utilisateur."

(Le modèle peut deviner un ID comme 12345.)

Format et contrainte

"Planifie une réunion. "date" doit être au format ISO 8601 (AAAA-MM-JJ). Si l'utilisateur dit "demain" ou utilise une autre référence relative, calculez la date en fonction du contexte actuel."

"Planifie une réunion pour la date indiquée."

(semble correct pour un humain (par exemple, "demain"), mais échoue à la validation du schéma (nécessite "2025-10-12"))

Résultats attendus

"Récupère les journaux du serveur. Renvoie les 50 dernières lignes de texte brut. Pour l'analyse, demandez des périodes plus courtes afin d'éviter les limites de jetons."

"Obtenir les journaux du serveur"

(Le modèle peut appeler un outil en attendant un résumé, obtenir un vidage JSON brut de 5 Mo et entraîner une mauvaise expérience utilisateur.)

@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...

    ...

Cette description fait office de mini-manuel. Il gère la source (où obtenir l'ID), les contraintes (énumérations valides) et l'action.

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

Cette méthode s'appuie sur les noms des variables pour effectuer tout le travail. Le modèle doit deviner les valeurs valides pour "status".

Paramètres de l'outil

En plus de l'outil lui-même, décrivez les paramètres pour qu'ils soient sans ambiguïté.

Types explicites

Utilisez des types forts et spécifiques (string, integer, boolean, array).

Utiliser des énumérations pour les ensembles de valeurs fixes

Si un paramètre n'accepte qu'un ensemble fixe de valeurs (par exemple, daylight, cool, warm), listez-les dans un tableau enum. Cela améliore considérablement la précision.

Indiquez clairement les paramètres requis.

Définissez clairement les paramètres obligatoires pour le bon fonctionnement de la fonction.

Appliquer la correspondance de schéma sémantique

Lors de l'intégration de votre application, il peut être nécessaire de faire correspondre le schéma sémantique des paramètres de vos outils avec le secteur pour lequel vous développez. Vous recevrez le schéma vertical attendu (un schéma JSON) lors du processus d'intégration.

Exemples de paramètres d'outil

Les exemples suivants montrent les bonnes et mauvaises pratiques concernant la gestion des paramètres d'outil.

Recommandé Non recommandé

Formats et unités des arguments

radius : rayon en mètres. Doit être un nombre à virgule flottante supérieur à 0."

(empêche les hallucinations d'unités)

radius : "Rayon du cercle."

Formats et contexte des ID

user_id : UUID de la base de données (par exemple, 550e8400-e29b...). N'utilisez pas d'adresses e-mail ici."

Remarque : Nous vous recommandons de traiter tous les champs d'ID numériques comme des valeurs de chaîne. En particulier, si votre ID peut comporter 10 chiffres ou plus, il risque d'être tronqué par les systèmes internes (forcé dans un conteneur 32 bits) et cette version sera utilisée par le modèle dans les futurs appels d'outils.

(évite les erreurs de type)

user_id: "ID de l'utilisateur."

Valeurs renvoyées attendues

"Met à jour l'enregistrement et renvoie l'objet JSON mis à jour, y compris le nouveau code temporel."

(Indique au modèle qu'il n'a pas besoin d'appeler un outil "get" immédiatement après l'outil "update" pour vérifier la modification.)

"Met à jour l'enregistrement."


@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."""
    ...

Le LLM ne sait pas quelle syntaxe "query" accepte (SQL ? Expression régulière ? Texte brut ?) Il ne connaît pas la "limite" maximale.

Réponses et gestion des erreurs

Conformément au principe de base La réponse est le prochain prompt, l'outil signale le résultat de son exécution sous-jacente en renvoyant une charge utile de données, qui est ensuite collée directement dans la fenêtre de contexte du LLM. La réussite ou l'échec du résultat détermine la suite des événements :

  • Si l'opération réussit : le modèle a besoin de la valeur de retour pour savoir ce qui s'est passé et décider de l'étape suivante.
  • En cas d'échec : le modèle doit savoir pourquoi il a échoué et comment résoudre le problème. Un plantage (erreur 500) interrompt la conversation. Un message d'erreur descriptif permet au modèle de s'autocorriger.

Que la logique sous-jacente de votre outil réussisse ou échoue, vous devez formater la charge utile de la valeur de retour afin que le modèle puisse l'analyser facilement. Suivez ces bonnes pratiques lorsque vous empaquetez votre charge utile de réponse.

Utiliser JSON

Formatez les données structurées dans TextContent (contrainte temporaire). Étant donné que structuredContent n'est pas encore compatible avec Connected Apps Platform, sérialisez manuellement vos données. Même si vous renvoyez une liste simple, json.dumps().

Inclure les URL dans la réponse

Les URL renvoyées doivent être relativement courtes et ne pas comporter trop de paramètres. Il est recommandé d'utiliser des services de raccourcissement d'URL pour réduire le nombre de jetons et le risque d'hallucinations.

Charges utiles anti-hallucination autodescriptives

Associez toujours les codes bruts ou les ID internes à des noms à afficher lisibles par l'humain, des unités de mesure explicites et des plages de référence. Ne renvoyez jamais de clés de dictionnaire compressées ni de codes numériques non mappés qui obligent le modèle à déduire le contexte.

Mettre en place une gestion robuste des exceptions

Renvoyez des messages d'erreur clairs et explicites pour que le modèle puisse comprendre ce qui s'est mal passé et en informer l'utilisateur. Consultez la section Gestion des erreurs MCP.

Utiliser try/except

Encapsulez la logique de l'outil dans des blocs try/except et renvoyez les erreurs sous forme de chaînes.

Fournir des erreurs exploitables

Suggérez l'étape suivante dans le message d'erreur (par exemple, "Essayez d'abord d'utiliser l'outil X").

Confirmer les actions

Ne renvoyez pas de chaînes vides pour les outils à effet secondaire (création/mise à jour/suppression).

Exemples de réponses et de gestion des erreurs

Les exemples suivants montrent les bonnes et mauvaises pratiques concernant les réponses et la gestion des erreurs.

Recommandé Non recommandé

Sérialisation explicite


...
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)

Détecter et informer


...
@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."

(L'outil "réussit" techniquement (renvoie une chaîne), mais la chaîne contient les détails de l'erreur. Le modèle lit cette réponse, se rend compte que l'ID n'existe pas et peut demander à l'utilisateur de fournir l'ID correct.)


...
@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)

(Si get_user échoue, le serveur renvoie une erreur 500. Le LLM reçoit une erreur d'exécution générique et ne sait pas pourquoi (l'ID était-il incorrect ? Base de données indisponible ? Autorisation refusée ?). Il est probable qu'il réessaie exactement la même entrée incorrecte.)

Réponses vides

...
@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.

Les LLM sont souvent perturbés par les réponses vides. Il peut halluciner "L'outil a échoué" ou simplement répéter l'appel.

Charge utile d'anti-hallucination autodescriptive

Associez toujours les codes bruts ou les ID internes à des noms à afficher lisibles par l'humain, à des unités de mesure explicites et à des plages de référence normales.

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

(Cela indique exactement au modèle ce que signifie la valeur, sans l'obliger à déduire des unités ou des seuils de référence.)

ID bruts, compression personnalisée ou codes non mappés

Renvoyer des ID internes bruts, des abréviations de dictionnaire personnalisées ou des codes numériques sans libellés.

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

(Le modèle est obligé de deviner à quoi correspond "105", ce qui entraîne des hallucinations d'unités, un manque de contexte ou des explications inexactes.)

Gestion des erreurs MCP

Il est crucial de gérer les erreurs de manière optimale.

  • Pour les erreurs récupérables (comme un ID utilisateur non valide ou un paramètre facultatif manquant), renvoyez une chaîne de texte normale contenant des détails descriptifs sur l'erreur dans la réponse de l'outil. Cela permet au modèle d'inspecter les commentaires, de comprendre ce qui n'a pas fonctionné et de s'autocorriger ou de demander des clarifications à l'utilisateur.
  • Pour les erreurs fatales (telles que la limitation du débit, les échecs d'authentification ou d'autorisation, ou les pannes du serveur backend), déclenchez une McpError avec le code d'erreur approprié afin que la plate-forme puisse gérer l'échec de manière systématique.

Exemple de corps de réponse d'erreur (JSON)

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

Message contient un dump JSON du champ ErrorData du MCP. En renvoyant le bon code et le message visible par le modèle, la Connected Apps Platform peut lire le message d'erreur et transmettre une explication utile en langage naturel à l'utilisateur. Par exemple, "Désolé, je n'ai pas trouvé l'établissement associé à cet ID. Pourriez-vous vérifier le nom ?"

MCP permet aux clients de se connecter aux serveurs MCP à l'aide de la spécification JSON-RPC 2.0. JSON-RPC envoie certaines erreurs prédéfinies pour les erreurs courantes, telles que les requêtes non valides, les erreurs d'analyse, etc. Ce guide explique comment les serveurs MCP peuvent renvoyer des erreurs personnalisées.

Status
Code
Message Utilisation Dois-je utiliser
return
de manière explicite ?
Erreurs utilisateur/client
-32300 USER_RATE_LIMITED L'utilisateur a atteint sa limite d'utilisation maximale. OUI
-32301 MISSING_REQUIRED_INFORMATION La requête d'entrée ne contient pas toutes les informations nécessaires OUI
-32302 USER_PERMISSION_DENIED L'utilisateur a refusé l'autorisation d'utiliser l'outil. Par exemple, l'utilisateur doit disposer d'un compte d'entreprise, d'une limite d'âge, d'un paramètre régional, etc., ou ne pas disposer d'un abonnement d'entreprise à l'outil. OUI
Erreurs d'application/Erreurs de logique métier
-32400 RUNTIME_ERROR L'exécution de code du serveur a généré une erreur OUI
-32401 NULL_POINTER_EXCEPTION Tentative d'exécution d'un pointeur/objet nul OUI
-32402 OUT_OF_MEMORY Mémoire insuffisante dans le code du serveur pour l'allocation à un objet OUI
Erreurs d'infrastructure
-32500 DEADLINE_EXCEEDED La requête prend plus de temps que prévu. Peut se produire pour de nombreuses raisons, par exemple un serveur surchargé, des problèmes de réseau, etc. OUI
-32501 RESOURCE_EXHAUSTED Le serveur a manqué de mémoire insuffisante, d'espace disque, de threads, de temps CPU, etc. OUI
-32502 SERVICE_UNAVAILABLE Le service dépendant (par exemple, un autre microservice, une base de données, un cache, etc.) n'est pas disponible. OUI
Erreurs JSON-RPC (ces erreurs font partie du transport MCP)
-32700 PARSE_ERROR Le serveur n'a pas pu analyser la requête NON
-32600 INVALID_REQUEST Requête client incorrecte NON
-32601 METHOD_NOT_FOUND Nom d'outil MCP non valide NON
-32602 INVALID_PARAMS Paramètres de requête non valides, y compris des paramètres manquants ou des types de paramètres incompatibles NON
-32603 INTERNAL_ERROR Réponse par défaut NON

Voici un exemple de génération d'une erreur MCP sur votre serveur à l'aide du SDK Python officiel (mcp). Générez une McpError contenant une charge utile ErrorData, que le SDK sérialise automatiquement au format d'erreur JSON-RPC requis avec l'état d'erreur renseigné.

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."
    ),
  )

Contexte de l'outil

Les produits Google concernés sont compatibles avec une API Tool Context pour transmettre des signaux aux serveurs MCP. Cette API est utilisée dans des cas d'utilisation valides nécessitant des informations sensibles, par exemple des métadonnées qui ne font pas partie de la définition de l'outil de base, comme dans le cas d'un paramètre régional pour les outils nécessitant une localisation. L'API Tool Context n'est exposée que via la Connected Console.

Lorsque vous enregistrez un signal tel que current_user_location_fine avec votre application dans la Connected Console, les produits Google applicables complètent les requêtes MCP tools/call avec une entrée _meta supplémentaire fournissant les données demandées. L'ensemble des signaux compatibles est le suivant :

  • current_user_location_fine (Gemini uniquement, pour les secteurs autorisés)
  • 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"
      }
    }
  }
}

Pour décompresser ces données :

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)"

Rendu de l'expérience utilisateur

Applis MCP

Les produits Google concernés sont compatibles avec les intégrations d'applications MCP pour certains parcours utilisateur afin de permettre la création d'interfaces utilisateur personnalisées. Suivez les spécifications pour obtenir des instructions d'intégration générales.

L'intégration des applications MCP aux produits Google applicables est soumise aux restrictions suivantes.

Ingestion de ressources au moment de l'enregistrement

Les produits Google concernés récupèrent les ressources d'interface utilisateur au moment de l'ingestion de l'outil, de la même manière que la liste et les descriptions des outils. Cela signifie que les mises à jour des ressources (par exemple, les modifications apportées au code JavaScript) ne seront pas récupérées automatiquement et nécessiteront une nouvelle ingestion de l'outil.

Une ressource d'UI ne doit pas dépasser 15 Mo, et la taille cumulée des ressources d'UI sur votre serveur ne doit pas dépasser 100 Mo.

Les ressources d'interface utilisateur doivent utiliser l'un des types MIME compatibles : text/html, text/javascript, text/css ou text/html;profile=mcp-app. Les types MIME non standards ou spécifiques à une plate-forme échoueront lors de la validation lors de l'envoi vers l'aperçu.

Consignes pour les CSP

Les produits Google concernés respectent la spécification officielle des applications MCP, qui inclut les CSP [1], [2], et bloquent toutes les requêtes qui ne respectent pas les directives CSP.

Les produits Google applicables nécessitent également d'ajouter blob: et data: à la CSP, le cas échéant. Ils ne seront pas ajoutés par défaut. Il appartient aux développeurs de les ajouter (ou non) à la CSP.

Script-src est une exception

Les seules directives que nous autorisons sont : unsafe-inline (ajoutée par défaut), wasm-unsafe-eval et data: (si inclus dans resource_domains). Si l'iframe charge des scripts externes, vous pouvez résoudre le problème en regroupant le code JS dans le code HTML ou en utilisant un hachage SRI (Subresource Integrity).

  • Option 1 : Intégrer/Regrouper le code JS dans le code HTML (le plus simple)

    • Code JS du bundle :

      • Insérez le contenu de component-init.js directement dans les balises <script> de la charge utile HTML renvoyée pour la ressource d'UI :

        <script>
        // Paste component-init.js content directly here
        </script>
        
    • Supprimer les tags <script src> distants

      • Supprimez les références <script src="https://api.mycompany.com/..."> du document HTML.
    • Outil de réingestion/mise à jour

  • Option 2 : Utiliser le hachage SRI (Subresource Integrity) :

    Utilisez cette option si le script doit rester hébergé en externe sur https://api.company.com/....

    • Calculer le hachage SHA-256 du script
      • Générez le hachage SHA-256 en base64 de component-init.js.
    • Ajoutez le hachage à resourceDomains (doit inclure le préfixe sha256- pour correspondre à l'attribut integrity).
    • Mettre à jour la balise HTML <script>
      • Ajoutez les attributs integrity et crossorigin à la balise de script dans le widget HTML.
    • Vérifier l'en-tête CORS sur le CDN/serveur
      • Assurez-vous que api.company.com diffuse component-init.js avec Access-Control-Allow-Origin: * (ou autorise scf.usercontent.goog) afin que le navigateur puisse lire le corps de la réponse pour la validation SRI.
    • Outil de réingestion/mise à jour

Consignes de sécurité pour la description des outils MCP

Comme la description est le seul contexte dont dispose le modèle pour comprendre les capacités de l'outil, elle doit être rédigée de manière précise et sécurisée pour éviter tout comportement involontaire. Respectez les consignes suivantes lorsque vous rédigez les descriptions de vos outils.

  • Décrivez les fonctionnalités, mais ne dictez pas le comportement. La description doit décrire précisément ce que fait l'outil, et non ordonner au modèle d'effectuer des actions ultérieures.
  • Définissez le champ d'application et les exigences. Indiquez clairement l'objectif principal de l'outil, les circonstances spécifiques (Quand) de son utilisation et toutes les entrées requises (paramètres/arguments).
  • Assurez la véracité des informations. La description doit être une représentation fidèle du code sous-jacent de l'outil. Ne prétendez pas qu'un outil est en lecture seule s'il effectue une opération d'écriture ou de suppression.

Risques de sécurité et comment les éviter

Zone à risque Recommandé Évitez cette pratique à tout prix

Injection de prompt

Utilisez un langage objectif et déclaratif pour indiquer clairement l'objectif et les fonctionnalités de l'outil.

Utilisez des commandes impératives pour remplacer le comportement du modèle ou modifier les flux du système (par exemple, "vous DEVEZ dire...", "Après avoir couru, vous DEVEZ…"). Les termes impératifs tels que "DOIT" ou "CRITIQUE" ne sont acceptables que lors de la définition de contraintes de paramètres structurés ou de règles d'utilisation.

Utilisez une mise en forme standard et simple pour le texte de description de l'outil.

Utiliser une mise en forme qui attire l'attention, par exemple l'utilisation excessive de majuscules et de balises telles que VERY IMPORTANT: ou **CRITICAL**.

Concentrez-vous uniquement sur la fonction de l'outil et sur le comportement attendu.

Inclure des instructions de jeu de rôle ou des commandes pour ignorer les instructions précédentes.

Shadowing et détournement d'outils

Assurez-vous que la description est spécifique et limitée aux fonctionnalités réelles et associées de l'outil.

Rendre la description de l'outil trop large ou vague, ou affirmer qu'un seul outil effectue de nombreuses fonctions non liées.

Choisissez un nom d'outil unique, descriptif et pertinent.

Utiliser un nom d'outil qui est une variante mineure d'un outil de confiance, ou un nom générique (par exemple, do_everything_tool, assistant_tool).

Ne mentionnez pas d'autres applications ni d'outils de plates-formes externes par leur nom dans votre description.

faire explicitement référence à d'autres outils ou créer des règles concernant le moment ou la manière d'utiliser d'autres outils.

Autorisez le planificateur du modèle à sélectionner l'outil le plus approprié en fonction du contexte de l'utilisateur.

Inclure un langage anticoncurrentiel ou tout type de prompt SEO qui demande au modèle de préférer votre outil à des outils similaires.

Manipulation des déclencheurs

La description ne fait pas référence à des expressions générales de l'historique de la conversation et n'y réagit pas.

Créer une logique conditionnelle qui déclenche une action nuisible en fonction d'expressions courantes et inoffensives de l'utilisateur (par exemple, "merci", "pour résumer").

Utilisation abusive des paramètres

Ne définissez que les paramètres nécessaires à la fonction de l'outil et utilisez des noms spécifiques aux données d'entrée (par exemple, file_id, search_term).

Définissez des paramètres de fonction avec des noms qui reflètent l'état interne de l'agent (par exemple, system_prompt, conversation_history, full_context).

Exfiltration de données

Protection des données personnelles dès la conception : identifiants opaques et authentification gérée par l'hôte.

Utilisez des ID non sensibles, et non des informations brutes permettant d'identifier personnellement l'utilisateur. Toutes les données doivent être traitées dans des limites autorisées et sécurisées, et ne doivent pas être référencées dans la description publique comme étant envoyées en externe. L'exécution de l'outil héritera des autorisations de manière silencieuse via le handshake OAuth.

Toutes les informations sensibles doivent être nettoyées avant d'être envoyées aux produits Google concernés.

Demander des informations permettant d'identifier personnellement l'utilisateur, des données de santé protégées ou toute autre information personnelle et/ou sensible de l'utilisateur, des données personnelles ou d'entreprise, ou une entité d'une manière qui enfreint les conditions d'utilisation des produits Google applicables.

Mentionner ou exiger l'envoi de données utilisateur (requête, position, contexte) à des URL tierces, des services de journalisation ou des systèmes externes non autorisés.

Bonnes pratiques concernant les fonctionnalités et les noms

En plus de sécuriser la description de votre outil, vous devez vous assurer que le modèle peut le sélectionner et l'exécuter de manière fiable, sans confusion. Respectez les bonnes pratiques suivantes en matière de fonctionnement et de dénomination :

  • Précision des paramètres. Assurez-vous que tous les noms et types de paramètres de la description correspondent exactement à l'implémentation réelle de l'outil.
  • Noms pertinents. Le nom de l'outil doit indiquer clairement sa fonction. Évitez les noms trop génériques comme "execute". Le nom doit également être cohérent avec l'écosystème d'outils plus large.

Annexe : Infrastructure et mise sur liste d'autorisation du réseau

Si votre infrastructure d'hébergement, votre passerelle d'API ou votre pare-feu limitent les connexions entrantes par adresse IP source, ajoutez à la liste d'autorisation les blocs CIDR sortants de Google suivants :

  • 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

Assurez-vous que votre environnement autorise le trafic provenant de ces plages d'adresses IP sur le port HTTPS 443 afin que les produits Google concernés puissent accéder à votre serveur MCP distant pour l'initialisation du MCP, la découverte d'outils et l'exécution des requêtes.