Publicaciones

Por qué construimos un servidor MCP nativo para retros

Ilustración editorial de un tablero de retro con notas adhesivas fluyendo hacia un panel de chat a la izquierda, gradiente suave en morado y rosa, estilo vectorial plano moderno, el chat está eligiendo herramientas de una pequeña paleta, sin texto legible ni etiquetas de interfaz
Kelly Lewandowski

Kelly Lewandowski

Última actualización 19/05/20267 min de lectura

Podríamos haber lanzado un servidor MCP de Kollabe en una tarde pasando nuestra especificación OpenAPI por un generador de código. En su lugar, nos pasamos un par de semanas diseñando la superficie de herramientas a mano. Esta es la parte de esa decisión que más nos sorprendió: el trabajo trataba casi por completo sobre retros. Los standups y el planning poker son mecánicos. Envías respuestas; emites un voto. Un modelo que sabe leer JSON y escribir JSON se las arregla bien con un wrapper generado. Las retros tienen la forma opuesta. Son largas, desordenadas, anónimas en partes, votadas, con reacciones, agrupadas, resumidas, y hacen referencia a personas a las que puede que no sepas buscar por su nombre. La primera versión que probamos, la que reflejaba REST uno a uno, se cayó en cuanto un modelo intentó dar kudos a alguien.

"Nativo" no significa "código distinto"

Un servidor MCP nativo no es un backend separado. El nuestro es una capa fina sobre los mismos endpoints /api/v1/ a los que cualquiera con un token de acceso personal puede llamar directamente. Los mismos handlers, los mismos esquemas Zod, los mismos chequeos de permisos. Si cambiamos una regla en uno, el otro se mueve con él. Lo que sí significa "nativo" es que la superficie de herramientas fue diseñada para lo que la va a usar. Una API REST la lee un desarrollador con la documentación abierta. Un servidor MCP lo lee un modelo en medio de una conversación, con miles de tokens de prompt del sistema ya gastados y un usuario esperando. Los dos consumidores quieren cosas distintas del mismo backend. Cuatro diferencias terminaron importando para las retros.

Decisión 1: menos herramientas, con toggles en lugar de pares

Un servidor generado nos habría dado un retro_create_reaction y un retro_delete_reaction, igual que nuestras rutas REST separan create de delete. Dos herramientas por cada reacción con emoji. Multiplica eso entre ítems y comentarios y estás gastando tokens reales en ruido antes de que el modelo haya hecho algo útil. Colapsamos cada acción reversible en una sola herramienta. retro_toggle_reaction es una herramienta que activa o desactiva un emoji según si quien llama ya ha reaccionado o no. Devuelve "added" o "removed" en la respuesta, para que el modelo pueda narrar lo que pasó sin guardar ids de reacciones que solo necesitaría para llamar a delete. La misma lógica mantuvo los votos a ítems como un par (puedes tener varios votos sobre el mismo ítem, así que sí necesitas un id para quitar uno) y mantuvo la creación y la eliminación de ítems separadas (los ítems no son estado reversible, son registros). Toggle cuando es reversible, separados cuando no.

Decisión 2: escribir pistas dentro de las descripciones, no en la documentación

La herramienta de kudos en retros nos enseñó esto. La primera versión aceptaba un userId y un kudoType y devolvía un error amigable si pasabas a alguien que no estaba en el espacio. Los modelos se inventaban consistentemente un user id, recibían el error, pedían perdón y le pedían al usuario que pegara el id correcto. Inútil. Lo arreglamos reescribiendo la descripción de la herramienta en lugar del handler:
Da kudos a otro usuario, asociado a un ítem de retro existente (crea uno primero con retro_create_item si no existe ninguno). El receptor debe ser miembro del espacio de la retro — usa organization_list_users (admite un filtro de búsqueda) para buscar el id de usuario por nombre.
El mismo código, el mismo error, pero ahora el modelo lee la descripción, llama a organization_list_users con el nombre que el usuario dijo en voz alta, obtiene el id y da los kudos de un tirón. El handler no cambió. La pista sí. Ilustración de una burbuja de chat a la izquierda con un pequeño flujo de trabajo a la derecha que muestra tres pasos: buscar un usuario, encontrar su registro y luego adjuntar kudos a un ítem de retro, paleta pastel suave, estilo editorial vectorial plano Empezamos a hacer esto en todas partes. retro_update avisa dentro de la descripción que eliminar una columna también elimina todos los ítems que contiene. retro_cast_item_vote menciona explícitamente el tope de votos por tablero y por columna para que el modelo pueda avisar al usuario antes de chocar contra el 400. Cada "tienes que saber esto para llamarme correctamente" va dentro de la herramienta, no en una guía aparte que nadie lee.

Decisión 3: una herramienta de búsqueda semántica, no una cadena de list-and-filter

Las retros se acumulan. Un equipo que hace una cada dos semanas tiene 26 tableros al año, con quizá 800 ítems entre todos. Cuando alguien le pregunta a un asistente "qué dijimos sobre los despliegues inestables el trimestre pasado", la peor respuesta posible es que el modelo llame a retro_list, luego a retro_list_items por cada resultado, y se los lea todos al contexto. Eso es una tormenta de llamadas a herramientas que le cuesta dinero al usuario y produce una respuesta peor que un grep. Así que construimos una herramienta search que ejecuta búsqueda semántica en todo el espacio a la vez. Devuelve ítems de retros, comentarios, action items, respuestas de standup, respuestas de encuestas, respuestas de ice-breakers y notas, ordenados por similitud coseno respecto a la consulta y agrupados por tipo. El modelo recibe los 20 resultados relevantes en una sola llamada en lugar de abanicarse sobre cientos de registros.

Decisión 4: consentimiento por funcionalidad en el OAuth

El servidor MCP de Kollabe tiene aproximadamente cuarenta herramientas entre retros, standups, planning poker, action items y búsqueda. Pedirle a un usuario que dé consentimiento a las cuarenta en una sola pantalla es el tipo de decisión que la gente acepta sin leer. Dividimos la pantalla de consentimiento por categoría. Cuando conectas Kollabe a Claude o Cursor, marcas las categorías que quieres (retros, standups, planning poker, action items, búsqueda) y el token queda limitado a esas. Un equipo que solo quiere que su PM redacte action items de retro desde Claude no tiene por qué dar acceso a standups ni a poker. Una revocación desde la página de ajustes del usuario lo mata, hayan dado consentimiento a una sola categoría o a todas. El token también nombra una organización concreta de Kollabe. Si perteneces a varias orgs, eliges cuál en la pantalla de consentimiento, y el token actúa como tú, solo en esa org. Si cambias de org, reconectas.

Qué significa esto en el tablero de retro

Un usuario que ha conectado Kollabe a su cliente de IA ahora puede tener una conversación así, con el modelo haciendo el trabajo de campo:
  1. Pre-cargar el tablero
    "Abre la retro de este sprint y añade ítems a partir de los postmortems que escribimos en Linear esta quincena, uno por incidente, en la columna Qué Podría Mejorar." El modelo crea los ítems, los marca como anónimos donde el ticket de origen lo era, y se detiene.
  2. Encontrar contexto de retros antiguas
    "¿Hemos hablado antes de la inestabilidad del CI?" La búsqueda semántica devuelve las tres retros donde apareció y los action items que salieron de ellas, en una sola llamada.
  3. Convertir discusión en action items
    "Crea action items a partir de los tres ítems más votados del tablero, asígnalos a quien escribió cada uno, con fecha para el viernes." retro_list_items seguido de unas cuantas llamadas a action_item_create . El modelo hace la asignación a partir del autor del ítem.
  4. Dar kudos por nombre
    "Dale kudos a Priya por desatascar la migración." El modelo llama a organization_list_users con una búsqueda por "Priya", y luego adjunta los kudos.
Nada de esto es una funcionalidad nueva. Cada una de esas llamadas corresponde a un endpoint REST que lleva meses en producción. La capa MCP es la diferencia entre "la API existe" y "el modelo puede usar la API".

Lo que volveríamos a hacer y lo que nos saltaríamos

Construiríamos el patrón de toggle desde el día uno. Escribiríamos las pistas con referencias cruzadas en las descripciones desde el día uno. Lanzaríamos la búsqueda semántica antes que cualquier endpoint individual de listado, porque esa es la herramienta que el modelo realmente quiere. Lo que nos saltaríamos es la tentación de hacer que MCP sea "más rico" que REST. Probamos, brevemente, a hornear auto-resúmenes dentro de la herramienta retro_get. Los modelos pasaban a resumir el resumen, y la latencia se triplicó. Ganó lo aburrido. La herramienta MCP devuelve la misma forma que devuelve el endpoint REST. La IA encima de eso es para que el usuario opte por ella vía prompt, no para que la horneemos en el protocolo. Si quieres probar esto con tus propias retros, la guía de configuración son sesenta segundos de OAuth. El contexto más profundo sobre el protocolo está en nuestro artículo sobre MCP. Y si prefieres ver cómo encaja la IA en una retro antes de conectar un modelo, nuestro generador de plantillas de retrospectiva es un buen punto de partida sin compromiso.

No. El servidor MCP es un adaptador fino sobre los mismos handlers de /api/v1/. El trabajo interesante está en las definiciones de las herramientas: nombres, agrupación, pistas y qué acciones se colapsan en un único toggle. La lógica de backend es compartida.

Sí. retro_create_item acepta un flag anonymous, y retro_create_item_comment también. Cuando se activa, la respuesta omite el id del usuario autor, igual que hace la interfaz. El anonimato se aplica a nivel del handler, no en la descripción.

La descripción de la herramienta retro_update avisa de que eliminar una columna también elimina todos los ítems que contiene. Confiamos en que el modelo se lo plantee al usuario antes de llamarla, igual que un desarrollador leyendo la documentación se fijaría en el aviso. No hay un paso de confirmación aparte dentro del protocolo.

No. El consentimiento se divide por categoría en el momento del OAuth. Puedes dar acceso solo a retros, o cualquier combinación de retros, standups, planning poker, action items y búsqueda. Los tokens se pueden revocar desde tus ajustes de Kollabe.