Estándares de integración de apps conectadas de MCP

El servidor de MCP establece el framework para conectar las funciones de tu app (herramientas de MCP) a la Connected Apps Platform. Para que pueda seleccionar, llamar y procesar los resultados de tu servicio de forma más confiable, tu configuración de MCP debe cumplir estrictamente con los siguientes estándares.

Principios rectores

Para cada función, enfócate en la intención del usuario y los casos de uso, y no en las capacidades de la función. La descripción es la forma principal de indicarle al modelo para qué sirve tu herramienta y a qué casos de uso puede responder.

Control de versiones

Para admitir implementaciones de MCP escalables y sólidas, adopta una arquitectura de URI estructurada que use el control de versiones basado en rutas, por ejemplo, /v1, /v2. De esta manera, puedes mantener la retrocompatibilidad y controlar las funciones nuevas. Complementar esto con subdominios específicos del proveedor, como https://gemini.mcp.company.com/mcp/v1, permite una administración detallada del tráfico y la optimización de las definiciones de herramientas adaptadas al contexto único y los comportamientos de procesamiento de diferentes modelos de IA.

Compatibilidad de versiones del protocolo MCP

La Connected Apps Platform admite la especificación del Protocolo de contexto del modelo (MCP) hasta la versión 2025-11-25. Aún no se admiten las versiones más recientes de la especificación.

  • Responsabilidad del desarrollador: Eres responsable de garantizar que tu servidor de MCP cumpla estrictamente con una versión del protocolo compatible con la plataforma de apps conectadas (2025-11-25) durante el protocolo de enlace initialize y en todas las definiciones de herramientas y esquemas.
  • Retrocompatibilidad de la plataforma: A medida que la Connected Apps Platform adopte versiones más recientes de la especificación del MCP en el futuro, nuestro cliente mantendrá la retrocompatibilidad con las versiones del protocolo admitidas anteriormente para que las integraciones de producción existentes sigan funcionando sin interrupciones.
  • Administra las actualizaciones: Cuando tengas todo listo para adoptar una especificación de MCP nueva o introducir cambios en el esquema, expón esas actualizaciones en una nueva ruta de URI con versión (por ejemplo, /mcp/v2) mientras mantienes tu extremo existente (/mcp/v1) para el tráfico activo.

Se permiten los cambios en los esquemas de MCP entre las versiones de la app. Te recomendamos que aproveches esta función y crees versiones de los extremos de MCP para admitir un lanzamiento gradual de funciones nuevas o que dependas estrictamente de los cambios retrocompatibles.

Especificación del protocolo de transporte

La Connected Apps Platform admite estrictamente la especificación del Protocolo de contexto del modelo de transporte HTTP de transmisión, versión 2025-03-26 y posteriores. No admite el HTTP heredado con transporte de SSE que se describe en la especificación del 5 de noviembre de 2024.

  • Un solo extremo HTTP. El extremo de MCP proporcionado en Connected Console (por ejemplo, https://api.example.com/mcp) es la URL única a la que los productos de Google aplicables envían todas las solicitudes JSON-RPC (initialize, tools/list y tools/call) a través de HTTP POST estándar.
  • Transmisión de SSE dentro de HTTP transmisible. No se admite el transporte de SSE de varios extremos heredado, pero sí se admiten los eventos enviados por el servidor, como text/event-stream, en HTTP transmitible. Las solicitudes salientes de los productos de Google aplicables incluyen Accept: application/json, text/event-stream, lo que significa que tu servidor puede devolver una carga útil application/json estándar o transmitir respuestas incrementales con Content-Type: text/event-stream directamente en el cuerpo de la respuesta HTTP POST.
  • GET stream y 405 Method Not Allowed. Los clientes pueden intentar una transmisión opcional de GET en el extremo para las notificaciones de servidor a cliente. Si tu servidor no tiene estado o solo es de solicitud-respuesta, la devolución de HTTP 405 Method Not Allowed es compatible de forma explícita y el proxy del cliente del producto de Google aplicable lo controla de forma limpia.

Instrucciones del servidor

La Connected Apps Platform está optimizada para transferir instrucciones del servidor, lo que permite un grado de control sobre el comportamiento del modelo que no está disponible por otros medios.

Sigue las instrucciones del servidor.

Tratar como una "sugerencia de modelo" con contexto de uso

Sigue estos lineamientos para proporcionar sugerencias a los modelos.

  • Escribe instrucciones como una "sugerencia" o guía de alto nivel para ayudar al LLM a comprender el propósito y las capacidades generales del servidor.
  • Describe lo que puede hacer, en lugar de enumerar funciones o describir cómo el modelo debe usar las herramientas y los recursos del servidor. Si el modelo comprende el "qué" correctamente, puede determinar el "cómo" bastante bien según el recorrido del usuario.
  • Supón que este texto se agregará directamente a la instrucción del sistema del modelo. Mantén la claridad, la directiva y la eficiencia de los tokens.

Complementa, no dupliques

Usa este espacio para el contexto global que se aplica a todas las herramientas, evitando la redundancia con las descripciones de las herramientas individuales.

Ejemplos de instrucciones del servidor

En los siguientes ejemplos, se muestran las prácticas recomendadas y las que se deben evitar para escribir correctamente las instrucciones del servidor.

Recomendado No recomendado

Actúa como encargado especializado del mantenimiento de repositorios de GitHub. Este servidor proporciona acceso profundo a los metadatos del repositorio, el seguimiento de problemas y los flujos de trabajo de PR. Úsala para mantener el estado del proyecto, automatizar la clasificación y garantizar los estándares de código. Se supone que todas las acciones se realizan en el contexto de la organización autenticada, a menos que se especifique lo contrario. Prioriza la identificación de hilos inactivos o solicitudes de extracción no vinculadas para mantener el repositorio organizado.

Conciso, directivo y complementario al modelo

  • Define el "qué" (estado del proyecto, clasificación) en lugar del "cómo".
  • Menciona el permiso de autenticación que se aplica a todas las herramientas

Este servidor tiene herramientas para GitHub. Debes usar la herramienta list_issues cuando el usuario pregunte por problemas. Puedes usar create_pull_request para crear una PR. Usa estas herramientas con cuidado para ayudar al usuario a administrar su código. Siempre verifica el nombre del repositorio antes de llamar a una herramienta. Si el usuario solicita un resumen, llama primero a las herramientas y, luego, resume el resultado

  • no vuelvas a enumerar los nombres de las herramientas,
  • No le digas al modelo "cómo" pensar, ya que esto puede entrar en conflicto con el razonamiento integrado del modelo, que usará el contexto del usuario para tomar la decisión correcta.
  • no explica la naturaleza del acceso del servidor ni sus restricciones específicas)

Lineamientos de las herramientas

En los siguientes lineamientos, se describen las prácticas recomendadas para crear configuraciones del servidor de MCP para varias funciones o herramientas dentro de tu app.

Convenciones de nomenclatura de herramientas

Sigue estos lineamientos para asignar un nombre a tu herramienta:

Usa nombres intuitivos y legibles por humanos

Usa nombres legibles por humanos con significados claros e intuitivos en lugar de nombres ambiguos. Por ejemplo, get_user_information es más directo que userInfo.

Observa el estilo de mayúsculas y minúsculas adecuado

Cumple con las siguientes reglas de uso de mayúsculas y minúsculas para los nombres de las funciones de herramientas y los activadores de apps:

  • Uso de mayúsculas y minúsculas en las funciones de las herramientas. Usa snake_case o camelCase para los nombres de las funciones de herramientas definidos en tu esquema de MCP (por ejemplo, get_user_information o publishDraft).
  • Uso de mayúsculas y minúsculas en el controlador de activadores de la app. Los activadores y las menciones de la app (por ejemplo, @MyTwoWordApp) no distinguen mayúsculas de minúsculas. La plataforma normaliza las entradas de los usuarios en minúsculas (@mytwowordapp), PascalCase (@MyTwoWordApp) y camelCase (@myTwoWordApp).
  • Formato del nombre visible. Registra el título oficial de tu app con PascalCase o espacios estándar para que se muestre de forma clara en los elementos de la IU.
  • Manejo de errores tipográficos. Si bien las variaciones de mayúsculas y minúsculas se controlan automáticamente, los errores tipográficos de caracteres (por ejemplo, @mytwowrodapp) se basan en el reconocimiento de intents de resguardo, en lugar de la coincidencia directa de cadenas. Los desarrolladores deben fomentar la ortografía correcta de los identificadores en la documentación.

Usa nombres explícitos de verbo-sustantivo

Usa nombres de verb_noun específicos y evita la ambigüedad; por ejemplo, publish_draft es mejor que handle_content.

Nivel de detalle de las herramientas

Ten en cuenta los siguientes lineamientos con respecto al nivel de detalle de las herramientas.

Trata las herramientas como extremos atómicos

Trata las herramientas como extremos atómicos sin condiciones internas ni múltiples funciones con sus respectivos parámetros obligatorios. Las herramientas detalladas permiten que el modelo encadene los pasos de forma lógica, lo que reduce las alucinaciones.

Usa esquemas más planos

Si necesitas objetos anidados de forma profunda o una lógica de esquema oneOf o anyOf compleja para validar las entradas, es probable que tu herramienta sea demasiado amplia.

Observa los mecanismos de protección de la carga útil y la agregación previa

Aunque el protocolo no exige de forma estricta la agregación previa de datos para cargas útiles pequeñas y con alcance, la agregación previa de backend es muy necesaria en la práctica cuando se trabaja con conjuntos de registros grandes, historial longitudinal y conjuntos de datos de varias fuentes. La Plataforma de apps conectadas aplica protecciones en torno a los límites de la ventana de contexto, la latencia de ejecución y los pasos de razonamiento del modelo. Para cumplir con estas protecciones, sigue estos lineamientos:

  • Filtra y resume en el backend. Siempre filtra, agrega previamente o resume los flujos de datos grandes en tu servidor de MCP antes de devolver las respuestas a los productos de Google aplicables.
  • Evita los volcados sin procesar. Nunca vuelques filas de bases de datos sin procesar ni registros completos no indexados en la carga útil de devolución de la herramienta.

Omitir herramientas internas y de metadatos

Expón solo las funciones orientadas al modelo en la respuesta tools/list de tu servidor:

  • Filtra las herramientas auxiliares: Omite cualquier herramienta interna, administrativa o de metadatos que no esté diseñada para que la llame el modelo (por ejemplo, verificaciones de estado del servidor, rutinas de configuración interna o asistentes de utilidades para desarrolladores).
  • Eficiencia de la ventana de contexto: Excluir las herramientas innecesarias mantiene tu esquema de MCP conciso, reduce el consumo de tokens de la ventana de contexto y evita la confusión del modelo en el enrutamiento de herramientas. Los servidores de MCP que expongan decenas de herramientas o esquemas de "megaherramientas" con un anidamiento profundo se marcarán durante la revisión para que se corrijan.

Sugerencias y precauciones para el nivel de detalle de las herramientas

En los siguientes ejemplos, se muestran las prácticas recomendadas y las que se deben evitar en relación con los nombres de las herramientas y el uso de la granularidad.

Recomendado No recomendado

Herramientas detalladas con nombres y parámetros claros

El esquema de entrada para cada herramienta es estricto. Si el LLM desea crear un usuario, debe proporcionar un correo electrónico. Si desea borrar, debe proporcionar un ID. No hay que adivinar.

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

    ...

Nombre de la herramienta: manage_user

Descripción: "Usa esta herramienta para crear, actualizar, borrar o recuperar usuarios".

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

Declara anotaciones de herramientas para mayor seguridad

Configura anotaciones de protocolo dentro de las definiciones de tus herramientas para transmitir el comportamiento de ejecución y activar puertas de seguridad integradas en los productos de Google aplicables:

  • Puertas de confirmación del tiempo de ejecución: Los productos de Google aplicables usan annotations.destructiveHint: true y annotations.openWorldHint: true como marcas clave para activar las solicitudes de confirmación del usuario en el tiempo de ejecución. Declara destructiveHint: true en acciones que cambian el estado, escriben o destruyen, y establece openWorldHint: true para las herramientas que interactúan con entornos de mundo abierto o externos, de modo que la plataforma solicite de forma nativa al usuario que confirme antes de la ejecución.
  • Sugerencia de consulta de solo lectura: Establece readOnlyHint: true en las herramientas de consulta que solo recuperan datos sin modificar el estado del backend.
  • Valores predeterminados de anotación explícitos: Según la especificación del protocolo de contexto del modelo, omitir readOnlyHint hace que los clientes asuman readOnlyHint: false y destructiveHint: true de forma predeterminada por seguridad. Declarar de forma explícita las anotaciones en todas las herramientas garantiza un enrutamiento a modelos predecible y una seguridad de ejecución adecuada.

Descripciones de herramientas

La descripción es el único contexto que tiene el modelo para decidir si tu herramienta puede resolver el problema actual. Sigue estos lineamientos para escribir descripciones:

Escribe instrucciones, no comentarios

Escribe descripciones de herramientas como instrucciones, y no como comentarios de código, que suelen ser pasivos. Los LLM responden bien a las directivas.

Explica el "cómo"

Una buena descripción reduce la brecha entre "Tengo una herramienta" y "Sé cómo conectar esta herramienta a una conversación".

Explica el "por qué"

Distingue esta herramienta de otras similares, por ejemplo, "Usa esta para usuarios internos, usa customer_update para externos".

Indícale al modelo dónde encontrar los argumentos, por ejemplo, "de la herramienta order_search".

Especifica el formato

Especifica las unidades (metros o pies) y los formatos (fechas ISO, versiones semánticas).

Evita la discreción del modelo

No le indiques al modelo que use su "mejor criterio" ni sugieras acciones opcionales sin guía.

Ejemplos de descripciones de herramientas

En los siguientes ejemplos, se muestran las prácticas recomendadas y las que se deben evitar para escribir descripciones de herramientas.

Recomendado No recomendado

Fuente de información

"Actualiza el correo electrónico de un usuario. Se debe usar estrictamente el UUID "id" que devuelve la herramienta search_users. No infieras ni adivines los IDs de usuario".

(Vincula de forma explícita el resultado de una herramienta con la entrada de esta.)

"Actualiza la dirección de correo electrónico del usuario".

(El modelo podría adivinar un ID como 12345).

Formato y restricción

"Programa una reunión. La fecha debe tener el formato ISO 8601 (AAAA-MM-DD). Si el usuario dice 'mañana' o hace otra referencia relativa, calcula la fecha según el contexto actual".

"Programa una reunión para la fecha indicada".

(parece correcto para un humano, por ejemplo, "mañana", pero falla la validación del esquema, que necesita "2025-10-12")

Expectativas de resultados

"Recupera los registros del servidor. Devuelve las últimas 50 líneas de texto sin procesar. Para el análisis, solicita períodos más cortos para evitar los límites de tokens".

"Obtener registros del servidor".

(El modelo puede llamar a una herramienta que espera un resumen, obtener un volcado de JSON sin procesar de 5 MB y generar una mala experiencia del usuario).

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

    ...

Esta descripción actúa como un mini manual. Controla la fuente (de dónde obtener el ID), las restricciones (enums válidos) y la acción.

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

Esto se basa en los nombres de las variables para hacer todo el trabajo. Deja que el modelo adivine los valores válidos para "status".

Parámetros de la herramienta

Además de la herramienta en sí, describe los parámetros para que no sean ambiguos.

Tipos explícitos

Usa tipos específicos y sólidos (string, integer, boolean, array).

Usa enums para conjuntos de valores fijos

Si un parámetro solo acepta un conjunto fijo de valores (por ejemplo, daylight, cool, warm), indícalos en un array enum. Esto mejora drásticamente la precisión.

Indicar claramente los parámetros obligatorios

Define con claridad qué parámetros son obligatorios para que la función se ejecute.

Aplica la coincidencia semántica de esquemas

Cuando integres tu app, es posible que se requiera una coincidencia de esquema semántico de los parámetros de tus herramientas con la vertical para la que estás desarrollando. Recibirás el esquema vertical esperado (un esquema JSON) durante el proceso de integración.

Ejemplos de parámetros de herramientas

En los siguientes ejemplos, se muestran las prácticas recomendadas y las que se deben evitar en relación con el manejo de los parámetros de las herramientas.

Recomendado No recomendado

Formatos y unidades de los argumentos

radius: Es el radio en metros. Debe ser un número de punto flotante mayor que 0".

(evita la alucinación de unidades)

radius: "El radio del círculo".

Formatos y contexto de los IDs

user_id: El UUID de la base de datos (por ejemplo, 550e8400-e29b…). No uses direcciones de correo electrónico aquí".

Nota: Como práctica recomendada, todos los campos de ID numéricos se deben tratar como valores de cadena. En particular, si tu ID puede tener más de 10 dígitos, corres el riesgo de que los sistemas internos lo trunquen (lo fuercen a un contenedor de 32 bits) y que el modelo use esta versión en futuras llamadas a la herramienta.

(evita errores de tipo)

user_id: "El ID del usuario".

Expectativas de valor que se devuelve

"Actualiza el registro y devuelve el objeto JSON actualizado, incluida la nueva marca de tiempo".

(Le indica al modelo que no necesita llamar a una herramienta "get" inmediatamente después de "update" para verificar el cambio).

"Actualiza el registro".


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

El LLM no sabe qué sintaxis admite "query" (¿SQL? ¿Regex? Texto sin formato) No sabe cuál es el "límite" máximo.

Respuestas y manejo de errores

De acuerdo con el principio básico de La respuesta es la siguiente instrucción, la herramienta informa el resultado de su ejecución subyacente devolviendo una carga útil de datos, que luego se pega directamente en la ventana de contexto del LLM. El éxito o el fracaso del resultado determina lo que sucede a continuación:

  • Si se ejecuta correctamente, el modelo necesita el valor que se muestra para saber qué ocurrió y decidir el siguiente paso.
  • Si falla, el modelo necesita saber por qué falló y cómo corregirlo. Una falla (error 500) detiene la conversación; un mensaje de error descriptivo permite que el modelo se corrija por sí mismo.

Ya sea que la lógica subyacente de tu herramienta tenga éxito o falle, debes dar formato a la carga útil del valor que se muestra para que el modelo pueda analizarla con facilidad. Sigue estas prácticas recomendadas cuando empaquetes la carga útil de la respuesta.

Usa JSON

Dar formato a los datos estructurados en TextContent (restricción temporal) Debido a que structuredContent aún no se admite en la Connected Apps Platform, serializa tus datos de forma manual. Incluso si devuelves una lista sencilla, json.dumps().

Incluye URLs en la respuesta

Las URLs que se devuelven deben ser relativamente cortas y no tener muchos parámetros. Se recomienda usar servicios de acortamiento de URLs para ahorrar en el recuento de tokens y reducir el riesgo de alucinaciones.

Cargas útiles autodescriptivas contra las alucinaciones

Siempre vincula los códigos sin procesar o los IDs internos con nombres visibles legibles por humanos, unidades de medida explícitas y rangos de referencia. Nunca devuelvas claves de diccionario comprimidas ni códigos numéricos sin asignar que obliguen al modelo a inferir el contexto.

Implementa un manejo de errores sólido

Muestra mensajes de error claros y significativos para que el modelo pueda comprender qué salió mal y se lo informe al usuario. Consulta el manejo de errores de MCP.

Usa try/except

Une la lógica de la herramienta en bloques try/except y devuelve errores en forma de cadena.

Proporciona errores con diálogo de acción

Sugerir el siguiente paso en el mensaje de error (por ejemplo, "Intenta usar la herramienta X primero").

Confirmar acciones

No devuelvas cadenas vacías para las herramientas de efectos secundarios (crear, actualizar o borrar).

Ejemplos de respuestas y manejo de errores

En los siguientes ejemplos, se muestran las prácticas recomendadas y las que se deben evitar en relación con las respuestas y el manejo de errores.

Recomendado No recomendado

Serialización explícita


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

Atrapa e informa


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

(La herramienta "se ejecuta correctamente" desde el punto de vista técnico (devuelve una cadena), pero la cadena contiene los detalles del error. El modelo lee esto, se da cuenta de que "ese ID no existe" y puede pedirle al usuario el ID correcto).


...
@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 falla, el servidor arroja un error 500. El LLM recibe un error de ejecución genérico y no sabe por qué (¿el ID era incorrecto? ¿La base de datos está inactiva? Permission denied?). Es probable que vuelva a intentar la misma entrada incorrecta).

Respuestas vacías

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

Los LLM suelen confundirse con las respuestas vacías. Podrían alucinar con "La herramienta falló" o simplemente repetir la llamada.

Carga útil autodescriptiva contra las alucinaciones

Siempre vincula los códigos sin procesar o los IDs internos con nombres visibles legibles por humanos, unidades de medición explícitas y rangos de referencia normales.

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

(Esto le indica al modelo exactamente qué significa el valor sin obligarlo a inferir unidades o umbrales de referencia).

IDs sin procesar, compresión personalizada o códigos sin asignar

Devolver IDs internos sin procesar, abreviaturas de diccionarios personalizados o códigos numéricos sin etiquetas.

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

(Obliga al modelo a adivinar a qué se refiere 105, lo que genera unidades alucinadas, falta de contexto o explicaciones imprecisas).

Manejo de errores del MCP

Es fundamental controlar los errores de forma ordenada.

  • Para los errores recuperables (como un ID de usuario no válido o un parámetro opcional faltante), devuelve una cadena de texto normal que contenga detalles descriptivos del error en la respuesta de la herramienta. Esto permite que el modelo inspeccione los comentarios, comprenda qué salió mal y se corrija o le pida al usuario que aclare la situación.
  • En el caso de errores de terminal (como límite de frecuencia, fallas de autenticación o de permisos, o interrupciones del servidor de backend), genera un McpError con el código de error adecuado para que la plataforma pueda controlar la falla de forma sistemática.

Ejemplo de cuerpo de respuesta de error (JSON)

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

Message contiene un volcado de JSON del campo ErrorData del MCP. Si se devuelve el code correcto y el message visible para el modelo, la Connected Apps Platform puede leer el mensaje de error y transmitir una explicación útil en lenguaje natural al usuario. Por ejemplo, "Lo siento, no pude encontrar el lugar con ese ID. ¿Podrías verificar el nombre?"

MCP permite que los clientes se conecten a servidores de MCP con la especificación JSON-RPC 2.0. JSON-RPC tiene ciertos errores predefinidos que se envían para errores comunes, como solicitudes no válidas, errores de análisis, etc. En esta guía, se explica cómo los servidores de MCP pueden devolver errores personalizados.

Status
Code
Mensaje Uso ¿Es necesario usar
return
de forma explícita?
Errores de usuario o cliente
-32300 USER_RATE_LIMITED El usuario alcanzó su límite de uso máximo. SÍ
-32301 MISSING_REQUIRED_INFORMATION La solicitud de entrada no tiene toda la información necesaria SÍ
-32302 USER_PERMISSION_DENIED El usuario rechazó el permiso para usar la herramienta. Por ejemplo, el usuario debe tener una cuenta empresarial, restricción de edad, configuración regional, etc., o no tener una suscripción empresarial de la herramienta. SÍ
Errores de la aplicación/errores de lógica empresarial
-32400 RUNTIME_ERROR La ejecución del código del servidor generó un error SÍ
-32401 NULL_POINTER_EXCEPTION Intento de ejecutar un puntero o un objeto nulo SÍ
-32402 OUT_OF_MEMORY No hay memoria suficiente en el código del servidor para asignarla a un objeto. SÍ
Errores de infraestructura
-32500 DEADLINE_EXCEEDED La solicitud está tardando más del tiempo permitido. Puede ocurrir por muchos motivos, p.ej., servidor sobrecargado, problemas de red, etc. SÍ
-32501 RESOURCE_EXHAUSTED El servidor se quedó sin memoria, espacio en el disco, subprocesos, tiempo de CPU, etcétera. SÍ
-32502 SERVICE_UNAVAILABLE El servicio dependiente (p. ej., otro microservicio, base de datos, caché, etc.) no está disponible. SÍ
Errores de JSON-RPC (estos errores forman parte del transporte de MCP)
-32700 PARSE_ERROR El servidor no pudo analizar la solicitud NO
-32600 INVALID_REQUEST Solicitud del cliente con formato incorrecto NO
-32601 METHOD_NOT_FOUND Nombre de la herramienta de MCP no válido NO
-32602 INVALID_PARAMS Parámetros de solicitud no válidos, incluidos parámetros faltantes o tipos de parámetros que no coinciden NO
-32603 INTERNAL_ERROR Respuesta predeterminada NO

A continuación, se muestra un ejemplo de cómo puedes generar un error de MCP en tu servidor con el SDK de Python oficial (mcp). Genera un McpError que contenga una carga útil de ErrorData, que el SDK serializa automáticamente en el formato de error JSON-RPC requerido con el estado de error propagado.

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

Contexto de la herramienta

Los productos de Google aplicables admiten una API de contexto de herramientas para pasar indicadores a los servidores de MCP. Esta API se usa en casos de uso válidos que requieren información sensible, por ejemplo, metadatos que no forman parte de la definición principal de la herramienta, como en el caso de una configuración regional para herramientas que necesitan localización. La API de Tool Context solo se expone a través de Connected Console.

Cuando registras un indicador como current_user_location_fine con tu app en Connected Console, los productos de Google aplicables aumentarán las solicitudes de MCP tools/call con una entrada _meta adicional que proporcione los datos solicitados. El conjunto de indicadores compatibles es el siguiente:

  • current_user_location_fine (solo para Gemini, para verticales permitidas)
  • 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"
      }
    }
  }
}

Para desglosar estos datos, haz lo siguiente:

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

Renderización de la UX

Apps de MCP

Los productos de Google aplicables admiten integraciones de apps de MCP para recorridos del usuario seleccionados, lo que permite crear interfaces de usuario personalizadas. Sigue la especificación para obtener instrucciones generales de integración.

La integración de las apps de MCP en los productos de Google aplicables incluye las siguientes advertencias.

Transferencia de recursos en el momento del registro

Los productos de Google aplicables recuperan los recursos de la IU durante el tiempo de transferencia de la herramienta, de manera similar a la lista y las descripciones de las herramientas. Esto significa que las actualizaciones de recursos, como los cambios en JavaScript, no se detectarán automáticamente y requerirán que la herramienta vuelva a transferir los datos.

Un solo recurso de IU no debe superar los 15 MB de tamaño, y los recursos de IU acumulativos en tu servidor no deben superar los 100 MB.

Los recursos de la IU deben usar uno de los tipos de MIME admitidos: text/html, text/javascript, text/css o text/html;profile=mcp-app. Los tipos de MIME no estándar o específicos de la plataforma no pasarán la validación cuando se envíen a la vista previa.

Lineamientos de CSP

Los productos de Google aplicables siguen la especificación oficial de las apps de MCP, que incluye la CSP [1], [2], y bloquearán cualquier solicitud que infrinja las directivas de la CSP.

Los productos de Google aplicables también requieren agregar blob: y data: a la CSP, si se usa. No se agregarán de forma predeterminada. Los desarrolladores deciden si las agregan (o no) a la CSP.

Script-src es una excepción

Las únicas directivas que permitimos son: unsafe-inline (se agrega de forma predeterminada), wasm-unsafe-eval y data: (si se incluye en resource_domains). Si el iframe carga secuencias de comandos externas, se puede resolver agrupando JS en HTML o usando el hash de integridad de subrecursos (SRI).

  • Opción 1: Intercalar o agrupar JS en HTML (la más sencilla)

    • Código JS del paquete:

      • Intercala el contenido de component-init.js directamente dentro de las etiquetas <script> en la carga útil de HTML que se muestra para el recurso de IU:

        <script>
        // Paste component-init.js content directly here
        </script>
        
    • Quita las etiquetas de <script src> remotas

      • Borra las referencias de <script src="https://api.mycompany.com/..."> del documento HTML.
    • Herramienta de reenvío y actualización

  • Opción 2: Usa el hash de integridad de subrecursos (SRI):

    Usa esta opción si la secuencia de comandos debe permanecer alojada de forma externa en https://api.company.com/....

    • Calcula el hash SHA-256 de la secuencia de comandos
      • Genera el hash SHA-256 en base64 de component-init.js
    • Agrega el hash a resourceDomains (debe incluir el prefijo sha256- para que coincida con el atributo integrity).
    • Actualiza la etiqueta HTML <script>
      • Agrega los atributos integrity y crossorigin a la etiqueta de secuencia de comandos en el widget de HTML.
    • Verifica el encabezado de CORS en la CDN o el servidor
      • Asegúrate de que api.company.com entregue component-init.js con Access-Control-Allow-Origin: * (o permita scf.usercontent.goog) para que el navegador pueda leer el cuerpo de la respuesta para la verificación de SRI.
    • Herramienta de reenvío y actualización

Lineamientos de seguridad para la descripción de la herramienta de MCP

Debido a que la descripción es el único contexto que tiene el modelo para comprender las capacidades de la herramienta, debe escribirse de forma precisa y segura para evitar comportamientos no deseados. Sigue estos lineamientos cuando redactes las descripciones de tus herramientas.

  • Describe la funcionalidad, pero no dictes el comportamiento. La descripción debe describir con precisión lo que hace la herramienta, no ordenar al modelo que realice acciones posteriores.
  • Define el alcance y los requisitos. Indica claramente el objetivo principal de la herramienta, las circunstancias específicas (Cuándo) para su uso y todas las entradas (parámetros o argumentos) requeridas.
  • Garantiza la veracidad. La descripción debe ser una representación veraz del código subyacente de la herramienta. No afirmes que una herramienta es de solo lectura si realiza una operación de escritura o eliminación.

Riesgos de seguridad y cómo evitarlos

Área de riesgo Recomendado Evita esta práctica a toda costa

Inyección de instrucciones

Usa un lenguaje objetivo y declarativo para indicar claramente el propósito y la funcionalidad de la herramienta.

Usa comandos imperativos para anular el comportamiento del modelo o alterar los flujos del sistema (por ejemplo, "DEBES decir…", "Después de correr, DEBES…"). Los términos imperativos como DEBE o CRÍTICO solo se aceptan cuando se definen restricciones de parámetros estructurados o reglas de uso.

Usa un formato estándar y sin formato para el texto de descripción de la herramienta.

Usar un formato que llame la atención, por ejemplo, el uso excesivo de mayúsculas y etiquetas como VERY IMPORTANT: o **CRITICAL**

Céntrate únicamente en la función de la herramienta y el comportamiento esperado.

Incluir instrucciones de juego de rol o comandos para ignorar instrucciones anteriores

Duplicación y usurpación de herramientas

Asegúrate de que la descripción sea específica y se limite a las capacidades reales y relacionadas de la herramienta.

Hacer que la descripción de la herramienta sea demasiado amplia o vaga, o afirmar que una sola herramienta realiza muchas funciones no relacionadas

Elige un nombre de herramienta único, descriptivo y sensato.

Usa un nombre de herramienta que sea una variación menor de una herramienta de confianza o un nombre genérico (por ejemplo, do_everything_tool, assistant_tool).

No menciones otras apps ni herramientas de plataformas externas por su nombre en la descripción.

Hacer referencia explícita a otras herramientas o crear reglas nuevas sobre cuándo o cómo se deben usar otras herramientas

Permite que el planificador del modelo seleccione la herramienta más adecuada según el contexto del usuario.

Incluir lenguaje anticompetitivo o cualquier tipo de instrucción de SEO que le indique al modelo que prefiera tu herramienta por sobre otras similares

Manipulación de activadores

La descripción no hace referencia ni reacciona a frases generales del historial de conversaciones.

Crear lógica condicional que active una acción dañina basada en frases comunes e inocuas de los usuarios (por ejemplo, "gracias", "en resumen")

Abuso de parámetros

Solo define los parámetros necesarios para la función de la herramienta y usa nombres específicos para los datos de entrada (por ejemplo, file_id, search_term).

Define los parámetros de la función con nombres que reflejen el estado interno del agente (por ejemplo, system_prompt, conversation_history, full_context).

Robo de datos

Privacidad como prioridad en el diseño: Identificadores opacos y autenticación administrada por el host.

Usa IDs no sensibles, no IIP sin procesar. Todo el manejo de datos debe realizarse dentro de límites autorizados y seguros, y no se debe hacer referencia en la descripción pública a que se envían de forma externa. La ejecución de la herramienta heredará los permisos de forma silenciosa a través del protocolo de enlace de OAuth.

Toda la información sensible se debe limpiar antes de enviarla a los productos de Google correspondientes.

Solicitar IIP, ISP o cualquier otra información personal o sensible del usuario, datos personales o de la empresa, o de la entidad en cualquier capacidad que infrinja las condiciones del servicio de los productos de Google aplicables

Mencionar o requerir el envío de datos del usuario (búsqueda, ubicación, contexto) a URLs de terceros, servicios de registro o sistemas externos no autorizados

Prácticas recomendadas funcionales y de asignación de nombres

Además de proteger la descripción de tu herramienta, debes asegurarte de que el modelo pueda seleccionarla y ejecutarla de forma confiable sin confusiones. Sigue estas prácticas recomendadas funcionales y de asignación de nombres:

  • Precisión de los parámetros. Asegúrate de que todos los nombres y tipos de parámetros de la descripción coincidan exactamente con la implementación real de la herramienta.
  • Nombres lógicos. El nombre de la herramienta debe ser una pista clara y sólida sobre su función. Evita los nombres demasiado genéricos, como "execute". El nombre también debe ser coherente con el ecosistema de herramientas más amplio.

Apéndice: Infraestructura y lista de entidades permitidas de la red

Si tu infraestructura de hosting, API Gateway o firewall restringe las conexiones entrantes por dirección IP de origen, agrega a la lista de entidades permitidas los siguientes bloques CIDR de salida de 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

Asegúrate de que tu entorno permita el tráfico de estos rangos de IP en el puerto HTTPS 443 para que los productos de Google aplicables puedan llegar a tu servidor de MCP remoto para la inicialización de MCP, el descubrimiento de herramientas y la ejecución de solicitudes.