MCP Tool Annotations: cada hint y su valor por defecto
Introducción
Las MCP tool annotations (anotaciones de herramientas MCP) son metadatos opcionales que un servidor Model Context Protocol (MCP) adjunta a cada una de sus herramientas para indicar a los clientes cómo se comporta la herramienta.
Además de un title para mostrar, son cuatro hints (pistas) booleanos: readOnlyHint (la herramienta solo lee datos), destructiveHint (puede destruir datos), idempotentHint (llamarla dos veces no tiene ningún efecto adicional) y openWorldHint (accede a sistemas externos al servidor).
Los clientes las usan para decidir cuándo pedir confirmación al usuario y cómo presentar cada herramienta.
Anthropic presentó MCP en noviembre de 2024, y las anotaciones de herramientas llegaron unos meses después, en la revisión 2025-03-26 de la especificación. Escribí la primera versión de este artículo en mayo de 2025, mientras las añadía al Kubernetes MCP Server. Desde entonces, la especificación ha pasado por tres revisiones más (2025-06-18, 2025-11-25 y 2026-07-28), y a fecha de octubre de 2026 la última sigue definiendo las mismas cinco anotaciones con los mismos valores por defecto. Lo que ha cambiado es todo lo que las rodea: la mayoría de los clientes MCP que he revisado ya las tienen en cuenta, y tanto el directorio de conectores de Anthropic como la revisión de plugins de OpenAI las exigen.
En este artículo te cuento qué son las anotaciones de herramientas, qué significa cada hint y cuál es su valor por defecto, cómo las usan los clientes, por qué no puedes fiarte de ellas a ciegas y cómo definirlas en tu propio servidor. Los ejemplos son del Kubernetes MCP Server; los he probado con la v0.0.67 en octubre de 2026.
¿Qué son las Anotaciones de Herramientas MCP?
Las anotaciones de herramientas MCP son metadatos que puedes adjuntar a tus herramientas MCP para comunicar su comportamiento al cliente MCP. Piensa en ellas como etiquetas que describen lo que hace tu herramienta y cómo se comporta, similar a cómo podrías etiquetar herramientas físicas en un taller.
Viajan con cada herramienta en la respuesta tools/list del servidor, junto a su nombre, su descripción y su esquema de entrada.
Este es el JSON que recibe un cliente para la herramienta helm_list del Kubernetes MCP Server (sin la descripción, el esquema de entrada ni _meta):
{
"name": "helm_list",
"title": "Helm: List",
"annotations": {
"title": "Helm: List",
"readOnlyHint": true,
"destructiveHint": false,
"idempotentHint": false,
"openWorldHint": true
}
}La especificación llama hints a todas estas propiedades, title incluido: ayudan a las aplicaciones cliente a tomar decisiones informadas sobre el uso de herramientas, mostrar interfaces de usuario apropiadas e implementar controles de seguridad.
Nota
Las anotaciones son hints proporcionados por el servidor MCP y son únicamente informativas. No imponen ningún comportamiento o restricción en la herramienta misma. La especificación dice que los clientes DEBEN (MUST) considerarlas no fiables salvo que provengan de un servidor de confianza (hablo de ello más abajo).
¿Por qué son Importantes las Anotaciones de Herramientas MCP?
Las anotaciones de herramientas MCP permiten a los servidores expresar el comportamiento de sus herramientas de manera estandarizada. Al usar anotaciones, las herramientas se vuelven autodescriptivas, lo que aporta varias ventajas:
- Mejora de la Experiencia del Usuario: Un título comprensible permite a los clientes mostrar "Helm: List" en lugar de
helm_list. - Menos Confirmaciones y Más Útiles: Los clientes pueden ejecutar sin preguntar las herramientas de solo lectura y pedir siempre confirmación antes de una destructiva, en lugar de pedirla en cada llamada.
- Modos Seguros en el Servidor: Un servidor puede usar sus propias anotaciones para decidir qué herramientas expone; el modo de solo lectura del Kubernetes MCP Server se basa en ellas.
- Requisito de los Directorios: A fecha de octubre de 2026, tanto el Connectors Directory de Anthropic como la revisión de plugins de OpenAI exigen anotaciones para publicar un servidor.
- Consistencia entre Herramientas: Las anotaciones proporcionan una forma consistente de describir el comportamiento de las herramientas, facilitando a los desarrolladores entender y usar diferentes herramientas en varios servidores MCP.
Las MCP Tool Annotations y sus Valores por Defecto
La especificación MCP define cinco anotaciones, todas opcionales:
| Anotación | Por defecto | Significado |
|---|---|---|
| title | ninguno | Un nombre comprensible para la herramienta |
| readOnlyHint | false | La herramienta solo lee, nunca modifica su entorno |
| destructiveHint | true | La herramienta puede borrar o sobrescribir datos (si no es de solo lectura) |
| idempotentHint | false | Repetir la llamada no tiene efecto adicional (si no es de solo lectura) |
| openWorldHint | true | La herramienta accede a sistemas externos, no a un dominio cerrado |
Los valores por defecto asumen lo peor: según la especificación, una herramienta sin anotaciones puede modificar su entorno, puede destruir datos, no es seguro reintentarla y se comunica con el exterior.
Para un cliente que respeta estos valores, omitir un hint nunca hace que una herramienta parezca más segura de lo que es; solo hace que el cliente pida confirmación más a menudo de lo necesario.
No todos los clientes lo hacen: VS Code, por ejemplo, solo te pide que revises el resultado de una herramienta de mundo abierto cuando openWorldHint es explícitamente true.
readOnlyHint (Solo Lectura)
Por defecto false.
Ponlo a true cuando la herramienta no modifique su entorno, como helm_list.
Es el hint que más tienen en cuenta los clientes: una herramienta de solo lectura puede ejecutarse sin pedir confirmación.
destructiveHint (Destructiva)
Por defecto true, y solo tiene sentido cuando readOnlyHint es false.
true indica que la herramienta puede hacer cambios destructivos, como borrar un pod o desinstalar una release de Helm; false indica que solo hace cambios aditivos, como ejecutar un pod nuevo o instalar una release.
Los clientes que lo leen preguntan antes de ejecutar una herramienta destructiva.
idempotentHint (Idempotente)
Por defecto false, y solo tiene sentido cuando readOnlyHint es false.
true indica que volver a llamar a la herramienta con los mismos argumentos no tiene ningún efecto adicional, así que es seguro reintentarla: desinstalar dos veces la misma release de Helm deja el clúster igual que la primera llamada.
openWorldHint (Mundo Abierto)
Por defecto true.
true indica que la herramienta puede interactuar con un mundo abierto de entidades externas, como una búsqueda web o un clúster de Kubernetes; false indica que trabaja sobre un dominio cerrado, como un almacén de memoria local.
La Anotación title y el title de Primer Nivel
La anotación title tiene un campo hermano.
Desde la revisión 2025-06-18, una herramienta también puede incluir un campo title de primer nivel, y la especificación fija el orden para elegir qué nombre mostrar: title, después annotations.title y por último name.
Por eso el Kubernetes MCP Server envía el mismo título en ambos sitios: los clientes anteriores al campo de primer nivel solo conocen annotations.title, y un cliente más reciente muestra el mismo nombre lea primero el que lea.
Cómo Usan los Clientes MCP las Anotaciones de Herramientas
Cuando escribí la primera versión de este artículo, las anotaciones eran sobre todo una promesa.
A fecha de octubre de 2026, readOnlyHint es la anotación que importa: la mayoría de los clientes la usan para saltarse la confirmación, y algunos, como Codex CLI y el Claude Agent SDK, para ejecutar en paralelo las llamadas a herramientas de solo lectura.
| Cliente | Anotaciones | Qué hace con ellas |
|---|---|---|
| VS Code (Copilot) | title, readOnlyHint, openWorldHint | Ejecuta las herramientas de solo lectura sin preguntar, pide confirmación para el resto y puede pedirte que revises los resultados de mundo abierto. |
| Claude | title, readOnlyHint, destructiveHint | Las herramientas de solo lectura pueden saltarse la confirmación; las destructivas siempre preguntan. |
| ChatGPT | readOnlyHint, destructiveHint, openWorldHint | Trata una herramienta sin readOnlyHint como una acción de escritura que requiere confirmación. |
| Codex CLI | readOnlyHint, destructiveHint, openWorldHint | Por defecto, nunca pide confirmación para las de solo lectura y siempre la pide para las destructivas; ejecuta en paralelo las de solo lectura. |
| Gemini CLI | readOnlyHint; cualquiera, mediante políticas | En Plan Mode, te deja aprobar las de solo lectura y bloquea el resto; sus políticas pueden permitir, preguntar o denegar según cualquier anotación. |
| Goose | readOnlyHint | En modo Smart Approve, ejecuta sin preguntar las de solo lectura, siempre pide confirmación para las marcadas con readOnlyHint: false y deja que el modelo juzgue las que no tienen el hint. |
Ninguno de los clientes que he revisado tiene en cuenta idempotentHint por defecto (una política de Gemini CLI que escribas tú podría usarlo), y Cursor, Windsurf y Zed no documentan ningún uso de las anotaciones.
Defínelo igualmente: documenta si es seguro reintentar la llamada, y solo cuesta una línea.
¿Puedes Fiarte de las Anotaciones de Herramientas MCP?
No a ciegas.
La especificación es explícita: "clients MUST consider tool annotations to be untrusted unless they come from trusted servers" (los clientes deben considerar no fiables las anotaciones de herramientas salvo que provengan de servidores de confianza).
Un servidor malicioso o con errores puede marcar como readOnlyHint: true una herramienta que borra tus datos, y nada en el protocolo lo impide.
En la práctica, decides si confías en un servidor en el momento en que lo instalas o lo activas.
Los clientes usan las anotaciones para relajar sus confirmaciones con los servidores en los que has decidido confiar, y tus propias reglas de permisos tienen prioridad sobre los hints.
Las garantías reales vienen de controles deterministas: los permisos de las credenciales con las que se ejecuta el servidor, el sandboxing o las políticas de red.
En un servidor MCP para Kubernetes, eso es el RBAC de la service account o del usuario de su kubeconfig.
Que una herramienta sea de solo lectura tampoco la hace inofensiva: puede poner ante el modelo Secrets, o texto que controla un atacante, como los logs de un pod.
Las herramientas resources_get y resources_list del Kubernetes MCP Server leen cualquier tipo de recurso, Secrets incluidos, salvo que lo deniegues en su configuración denied_resources.
El blog oficial de MCP trató este tema en profundidad en Tool Annotations as Risk Vocabulary (marzo de 2026). A fecha de octubre de 2026, SEP-1913, todavía un borrador, propone nuevos hints para datos sensibles y resultados no fiables, y un Tool Annotations Interest Group revisa esta y otras propuestas; no se ha aceptado ninguna.
Caso de Uso: Kubernetes MCP Server
Veamos cómo se aplican estas anotaciones en un escenario del mundo real utilizando el Kubernetes MCP Server como ejemplo.
Kubernetes MCP Server es un servidor MCP que proporciona un conjunto de herramientas para interactuar con clústeres de Kubernetes y OpenShift, y todas ellas declaran sus anotaciones.
Esta es la definición de la herramienta helm_list en la v0.0.67 (sin el esquema de entrada ni los requisitos de RBAC).
El servidor declara sus herramientas con su propio tipo api.Tool, que convierte al mcp.Tool del SDK oficial de MCP para Go, y ptr.To viene de k8s.io/utils/ptr:
{Tool: api.Tool{
Name: "helm_list",
Description: "List all the Helm releases in the current or provided namespace (or in all namespaces if specified)",
InputSchema: &jsonschema.Schema{ /* namespace, all_namespaces */ },
Annotations: api.ToolAnnotations{
Title: "Helm: List",
ReadOnlyHint: ptr.To(true),
DestructiveHint: ptr.To(false),
OpenWorldHint: ptr.To(true),
},
}, Handler: helmList},En este ejemplo, la herramienta helm_list se define con varias anotaciones:
- Título: "Helm: List" proporciona un nombre claro y conciso para la herramienta que se presentará a los usuarios finales.
- Read-Only Hint:
trueindica que esta herramienta solo lee datos del clúster de Kubernetes sin realizar ningún cambio. - Destructive Hint: Marcado como
falseya que esta función lista las releases de Helm sin modificar nada. En rigor, la especificación solo lo tiene en cuenta para herramientas que no son de solo lectura, pero definirlo deja clara la intención. - Open World Hint:
trueindica que esta herramienta interactúa con un sistema externo (el clúster de Kubernetes), lo cual es importante para entender su alcance y posibles dependencias. Es una cuestión de criterio: la referencia de plugins de OpenAI, por ejemplo, dice que un espacio de trabajo privado no es de mundo abierto solo porque esté alojado externamente.
El idempotentHint: false del JSON anterior lo pone el SDK de Go, que siempre envía readOnlyHint e idempotentHint; en una herramienta de solo lectura, los clientes lo ignoran.
Compárala con helm_uninstall, que declara DestructiveHint: ptr.To(true) e IdempotentHint: ptr.To(true): borra una release, y desinstalar dos veces la misma release no tiene ningún efecto adicional.
Para más ejemplos, consulta los toolsets del Kubernetes MCP Server, donde todas las herramientas declaran sus anotaciones.
Modo de Solo Lectura y Herramientas Destructivas
El Kubernetes MCP Server también usa sus propias anotaciones para decidir qué herramientas expone. Dos flags filtran la lista de herramientas antes de que ningún cliente la vea:
--read-onlyexpone solo las herramientas anotadas conreadOnlyHint: true.--disable-destructiveoculta las herramientas anotadas condestructiveHint: true.
npx -y kubernetes-mcp-server@latest --read-only --toolsets corenpx viene con Node.js, y el servidor usa tu kubeconfig.
Si tiene más de un contexto, todas las herramientas reciben un argumento context, así que el agente puede acceder a todos ellos: dale al servidor un kubeconfig con un único contexto (--kubeconfig), o añade --disable-multi-cluster para limitarlo al contexto actual.
Como la mayoría de los servidores MCP locales, se comunica por stdio, así que no lo ejecutas en un terminal: añades este comando a la configuración de tu cliente MCP (en Windows nativo, algunos clientes necesitan cmd /c npx en lugar de npx).
He comprobado qué hace cada flag con la v0.0.67 y los toolsets core, config y helm activados (--toolsets core,config,helm; Helm no está activado por defecto).
El número exacto de herramientas depende de tu clúster y tu configuración, pero lo que deja fuera cada flag no:
| Flags | Herramientas expuestas | Qué queda fuera |
|---|---|---|
| ninguno | 23 | nada |
--disable-destructive | 17 | las seis herramientas destructivas, como pods_delete, resources_delete y helm_uninstall |
--read-only | 15 | todas las herramientas que modifican el clúster, incluidas las aditivas: pods_run y helm_install |
A diferencia de un cliente que se fía de los hints de un servidor remoto, aquí es el propio servidor el que aplica sus anotaciones, así que una sesión de solo lectura no puede llamar a una herramienta que escribe.
Eso sí, no es un sandbox.
El toolset config, activado por defecto, incluye configuration_view, una herramienta de solo lectura que devuelve tu kubeconfig, credenciales incluidas.
Un agente que también pueda ejecutar comandos en la shell puede pasárselas a kubectl y escribir igualmente (#1415).
Para una sesión de solo lectura, deja fuera ese toolset, como hace el comando anterior, y dale al servidor un kubeconfig cuyo usuario solo tenga los permisos que quieras darle al agente.
Para un control más fino, las reglas de confirmación del servidor pueden pedir confirmación al usuario antes de ejecutar cualquier herramienta con destructiveHint: true.
Preguntan mediante elicitation de MCP, así que con un cliente que no la admite, la llamada se ejecuta salvo que configures confirmation_fallback = "deny".
Cómo Definir las Anotaciones de Herramientas en Go, TypeScript, Python y Java
Todos los SDK oficiales de MCP permiten definir anotaciones.
Estos fragmentos declaran las mismas anotaciones que helm_list más arriba, título incluido, cada uno con la última versión del SDK a fecha de octubre de 2026.
El SDK de Go envía además el idempotentHint: false por defecto, que los demás omiten; para un cliente, ambas cosas significan lo mismo.
Con el SDK oficial de Go (v1.8.0), DestructiveHint y OpenWorldHint son punteros, porque su valor por defecto es true y el SDK necesita distinguir "sin definir" de false.
Aquí, server es un *mcp.Server y helmList un handler de herramienta tipado:
destructive, openWorld := false, true
mcp.AddTool(server, &mcp.Tool{
Name: "helm_list",
Title: "Helm: List",
Description: "List all the Helm releases",
Annotations: &mcp.ToolAnnotations{
Title: "Helm: List",
ReadOnlyHint: true,
DestructiveHint: &destructive,
OpenWorldHint: &openWorld,
},
}, helmList)Con el SDK de TypeScript (v2.3.1), las anotaciones van en la configuración de la herramienta:
import { McpServer } from '@modelcontextprotocol/server';
const server = new McpServer({ name: 'kubernetes', version: '1.0.0' });
server.registerTool('helm_list', {
title: 'Helm: List',
description: 'List all the Helm releases',
annotations: { title: 'Helm: List', readOnlyHint: true, destructiveHint: false, openWorldHint: true }
}, helmList);Con el SDK de Python (v2.3.0), son un argumento del decorador tool, con los nombres de campo en snake_case:
from mcp.server import MCPServer
from mcp.types import ToolAnnotations
mcp = MCPServer("kubernetes")
@mcp.tool(title="Helm: List",
annotations=ToolAnnotations(title="Helm: List", read_only_hint=True,
destructive_hint=False, open_world_hint=True))
def helm_list(namespace: str | None = None) -> str: ...En la v1, los campos van en camelCase (readOnlyHint=True): la v1 acepta los nombres en snake_case sin dar error, pero los envía como claves desconocidas, así que los clientes no ven ningún hint.
Con el SDK de Java (v2.0.1), el builder de herramientas de io.modelcontextprotocol.spec.McpSchema recibe una instancia de ToolAnnotations:
var tool = McpSchema.Tool.builder("helm_list", Map.of("type", "object"))
.title("Helm: List")
.annotations(McpSchema.ToolAnnotations.builder().title("Helm: List")
.readOnlyHint(true).destructiveHint(false).openWorldHint(true).build())
.build();Buenas Prácticas para las Anotaciones de Herramientas MCP
Cuando implementes anotaciones de herramientas, considera las siguientes pautas:
- Sé Preciso: Asegúrate de que las anotaciones reflejen con precisión el comportamiento de la herramienta. Las anotaciones engañosas pueden llevar a malas experiencias de usuario o problemas de seguridad, y los directorios de conectores y de plugins rechazan los servidores cuyas anotaciones no se corresponden con sus herramientas.
- Define los Hints Explícitamente: No dependas de los valores por defecto. Un cliente que sigue la especificación asume lo peor cuando falta un hint, pero no todos los clientes ni servidores tratan igual un valor ausente.
- Divide las Herramientas cuyo Comportamiento Depende de sus Argumentos: Una herramienta que lee o escribe según un argumento no puede ser de solo lectura. Con dos herramientas, una de solo lectura y otra no, los clientes pueden saltarse la confirmación en la segura.
- Piensa en los Usuarios: Utiliza títulos claros y descriptivos que ayuden a los usuarios (en lugar de a los desarrolladores) a entender el propósito de la herramienta.
Define el
titlede primer nivel, y manténannotations.titlepara los clientes más antiguos. - Considera las Implicaciones de Seguridad: Sé conservador con las anotaciones destructivas y de solo lectura. Cuando tengas dudas, opta por la precaución.
- Mantén las Anotaciones Actualizadas: A medida que las herramientas evolucionan, asegúrate de que sus anotaciones se actualicen para reflejar cualquier cambio en el comportamiento o la funcionalidad.
El Kubernetes MCP Server guarda en sus tests un snapshot de la salida de
tools/list, así que cualquier cambio en una anotación aparece en la revisión de código. - Usa Anotaciones de Manera Consistente: Aplica anotaciones de manera uniforme en todas las herramientas de tu servidor MCP para mantener una experiencia de usuario coherente.
Conclusión
Las anotaciones de herramientas MCP son una parte pequeña de la especificación en la que ya se apoyan la mayoría de los principales clientes MCP para decidir cuándo preguntar antes de ejecutar una herramienta. Unas anotaciones precisas suponen menos confirmaciones para las herramientas seguras, y una confirmación antes de las destructivas en los clientes que tienen en cuenta los hints.
En mi Kubernetes MCP Server, las anotaciones ayudan a los usuarios a entender la diferencia entre operaciones de consulta seguras y modificaciones potencialmente destructivas del clúster. También permiten a quien lo opera ejecutar el servidor en modo de solo lectura, o sin herramientas destructivas, con un solo flag.
A medida que construyes tus propios servidores MCP, recuerda que el propósito de las anotaciones es la comunicación: ayudan a cerrar la brecha entre lo que hace tu herramienta técnicamente y lo que los usuarios necesitan saber para usarla de manera efectiva. Eso sí, no las confundas con una barrera de seguridad.
Te Puede Interesar
- Introducción a Model Context Protocol (MCP): El Futuro de la Integración de IA
- Otorgando Superpoderes a Small Language Models con Model Context Protocol (MCP)
- Tutorial de Goose, agente de IA: CLI, MCP, Ollama y Recipes
- Kubernetes MCP Server se une a la organización Containers
- Agent Client Protocol (ACP): El LSP para Agentes de Codificación con IA
