20 años

Cuando ya estaba por publicar el anterior artículo en el blog me di cuenta de que justo dos días antes el primer artículo de este blog había cumplido la friolera de 20 añazos el 14 de Junio. Menudo vértigo de golpe, así que intenté hacer un viaje en el tiempo haciendo memoria de por qué empecé a escribir.

¿Por qué empecé?

La época en la que tuve mis primeras experiencias laborales como desarrollador fue una en la que los blogs estaban en ebullición. Como buen junior, tenía mucha hambre por aprender, así que consumía información en webs de noticias de programación y en algunos foros. Pero poco a poco empecé a encontrar blogs de personas concretas y a empezar a usar lectores de RSS para seguirlos.

En mi segundo trabajo como programador terminé en Net2u_ (adquirida después por Everis y esta a su vez por NTT Data), entre otras cosas tuve la suerte de coincidir con Daniel Torres Burriel, cuyo blog, por entonces, era personal y en él escribía principalmente de usabilidad. Posiblemente habría tardado mucho más en plantearme escribir y publicar si no hubiera tenido algún referente cercano que ya lo hiciera.

Eso me ayudó a animarme a dedicar tiempo a escribir sobre lo que iba aprendiendo tanto en el trabajo como por mi cuenta. Para lo que compré este dominio, como tenía poca pasta contraté el hosting más barato que encontré, con PHP, pero sin base de datos, y monté un SimplePHPBlog que era la única opción que encontré en la época sin necesidad de una base de datos. Más adelante cambié a Wordpress hasta que hace unos años volví a simplificar usando Jekyll.

Y aunque había dicho en el anterior artículo que no quería andar retorciendo LLMs, la primera en la frente: estuve peloteando con Claude Code para analizar distintos puntos por los que ha pasado este blog en cuanto a frecuencia y temáticas, incluso terminó por hacer un perfil sobre mi recorrido profesional a partir de mis publicaciones.

Pero calma, me niego a hacer copy-paste de lo que me sacó.

La evolución

No recordaba el altísimo ritmo de publicación de los tres primeros años, con un pico de 89 publicaciones en 2007. Aquellas publicaciones solían ser bastante cortas, con curación de enlaces interesantes, snippets de código que me resultaban útiles, combinadas ocasionalmente con notas más personales. Mucho foco en PHP, Java y Javascript de la época.

Captura de pantalla de la Wayback Machine de Archive.org con un post sobre un mini cómic de 2007 donde salen dos ratones-humanoides: Uno a traca a otro "Your money or your life!". El otro contesta "Look... I'm a programmer", el atracador dice "so?". El programmer dice "I have no money and no life"

A partir de 2008 coincidió que estábamos trabajando en Jobsket y que me puse por mi cuenta como freelance, sobre esa época bajó el ritmo y aumentó la longitud. Por entonces, el tipo de publicaciones era más trabajado y muy centrado en tecnologías, principalmente la apuesta en Groovy y Grails, algo de Rails y Javascript… Combinaba esto con apuntes sobre el emprendimiento en Jobsket o el freelancing.

Hacia 2010 empecé a combinar ese tipo de artículos con nuevas inquietudes, como empezar a ejercer cierto activismo alrededor de la apertura de datos por parte de las administraciones públicas como punto básico para una mayor transparencia, o a organizar y participar en comunidades locales como el colectivo Cachirulo Valley o Agile Aragón, o la serie #developars.

En 2013 empecé a publicar un resumen/retro semanal para obligarme a mantener una cadencia, al principio fui constante pero al cabo de un par de años fue decayendo. Por cuestiones varias fui perdiendo la motivación de hacerlo, y acumulaba varias semanas seguidas sin publicar hasta que decidí abandonarlo en 2016.

Hasta 2016 estuve publicando casi todos los meses principalmente gracias a esa retro semanal, pero a partir de 2017 reduje mucho mi ritmo de publicación aquí. Aunque ese año y el siguiente ya que estábamos emprendiendo con Coding Stones me curré algunos para el blog que teníamos en medium, ya más enfocados en metodología que en tecnologías concretas.

Entre 2019 y 2021 volví a tener un pico de frecuencia, manteniendo el enfoque más metodológico e intentando aportar cierta profundidad en los temas. Cosas como DDD, arquitectura de software, producto, testing, devops, equipos, etc. En buena parte, las restricciones por la pandemia hicieron que le volviera a dedicar más tiempo a escribir

Y a partir de 2022 hubo una caída en picado, pero combiné pequeñas píldoras muy técnicas con otros más trabajados y con foco más metodológico. Con un repunte en 2025, empezando por el artículo para Mosaic y compartiendo experiencias con un pequeño experimento .

How it started vs. How it’s going

Al escribir esto, me vino a la mente el meme How it started vs. How it’s going.

How it started: Escribir para aprender. How it’s going: Escribir para no olvidar lo aprendido.

Pero en el fondo, sigue siendo lo mismo: un sitio para intentar ordenar mis ideas.

Intentando recuperar rutina

Llevo unos meses en los que a ratos me entran ganas de publicar algo, pero luego me lío con otras cosas y lo voy dejando pasar, así llevo desde Octubre. En su momento quería escribir algo sobre mi incorporación a Mito como team contributor, pero como fui dejando pasar el tiempo fue perdiendo momentum para mi.

No pretendo escribir cosas hiper curradas, sólo intentar obligarme a ordenar ideas y plasmarlas por escrito intentando comunicarlas razonablemente bien. Y todo esto sin torturar ningún LLM, más allá de que me revise algún error gramatical o me dé feedback para ir mejorando mi redacción. Porque writing is thinking.

Foto de un escritorio donde hay un teclado, un ratón, un taco de post its, un par de cuadernos pequeños y un boli

Voy a seguir publicando aquí frente a plataformas de terceros por eso de la web abierta y tal. Porque aunque en alguna ocasión del pasado me he currado mucho un artículo y eso a mi ego le gusta que tenga alcance, prefiero hacerlo bajo mi dominio aún a sabiendas de que va a tener infinitamente menos tráfico que los substacks, linkedins o mediums de turno

Como siempre en este blog mi intención es seguir publicando sobre temas relacionados con el mundillo del desarrollo de productos de software. Tengo algunos borradores empezados, algunos desde hace muchísimo y otros razonablemente recientes. De cualquier modo se aceptan sugerencias.

Viviendo en el péndulo. Hasta la vista Genially

Tras casi 4 años, esta fue mi última semana en Genially. Una decisión que me costó mucho tomar tanto por motivos personales, con un ambiente de compañerismo en la compañía que creo que no es habitual en otros lugares que tienen cierta escala y haber construido lazos con un buen puñado de personas; como por motivos profesionales, con unos cuantos desafíos que se venían a corto y medio plazo en los que sé que hubiera disfrutado y aprendido.

En este tiempo, mi rol en la empresa se fue transformando poco a poco casi sin darnos cuenta, primero influenciando solo a nivel de tecnología y terminando haciéndolo a nivel de producto, negocio y operaciones. Hubo algo que fue una constante: vivir en el péndulo entre individual/team contributor y el management.

Incorporación

Entré casi por casualidad. Conocí a Chema, CTO de Genially, unos años antes en una Pamplona Crafters y mantuvimos el contacto vía redes sociales (cuando tuiter aún molaba). Tiempo después, hablamos por otro tema y me propuso explorar si tenía sentido incorporarme. La compañía venía de crecer mucho y vieron que podía asumir un rol que resultase complementario.

Justo era un momento en el que empezaba a sentir que necesitaba un cambio profesional, pero quería estar seguro de mi siguiente paso. Así que tras haber hecho el proceso de selección, nos tomamos un par de meses y tuvimos varias conversaciones hasta que finalmente me incorporé a la compañía.

Plataforma y organización

Entré con un rol de Platform Lead, por lo que mi responsabilidad iba a ser ayudar a los equipos de producto a que pudieran enfocarse en tener impacto, tratando de mejorar la experiencia de desarrollo y la efectividad de los equipos. Como bonus, también iba a echar una mano en cuestiones más organizativas.

Aunque este era un rol de liderazgo, no había un equipo dedicado, de modo que iba a tener que influir, colaborar con distintos equipos y empujar algunas iniciativas por mi cuenta.

Sobre el trabajo de plataforma

Una vez hecho el onboarding, empezar a tener algunas iniciativas ya lanzadas y conociendo más la compañía, traté de aterrizar una serie de metas:

Las iniciativas y actividades de plataforma deben facilitar la Developer Experience y ayudar a los equipos en distintos aspectos:

  • Reducir su carga cognitiva, que se enfoquen en complejidad intrínseca y no en la extrínseca, potenciando la germana (generando aprendizaje, construyendo esquemas o automatizando su uso)
  • Habilitar actitudes data-informed en la toma de decisiones
  • Aportar la mayor autonomía y empoderamiento posibles
  • Tratar de ser lo más eficientes en cuestiones de costes económicos
  • Dar fiabilidad, que las herramientas apenas fallen

Metas que traté de tener en cuenta, definiendo e implantando prácticas, procesos y herramientas, automatizando tareas, creando documentación… Y darles seguimiento unas veces de manera cuantitativa y otras de forma cualitativa.

Algunas de las iniciativas más relevantes fueron estas:

  • Actuar como puente entre el equipo de infraestructura y los equipos de producto para acelerar la implantación del stack de observabilidad de Grafana (Loki, Mimir, Tempo).
  • Formalizar la redacción de postmortems blameless tras incidencias que afecten al servicio junto a CTO y VP de ingeniería, para fomentar el aprendizaje sistémico.
  • Apoyar al equipo de Design System con distintas actividades.
  • Ayudar en la introducción de Snowplow + Amplitude para la instrumentación de producto colaborando con el equipo de data y los primeros equipos de producto involucrados.
  • Introducir el uso de Turborepo en el monorepo para simplificar el proceso de build.

A nivel organizativo

Durante esos primeros meses se estaba planteando una reorganización del área de desarrollo de producto bastante importante. Básicamente era pasar de una estructura de squads que se organizaba de forma recurrente a una basada en líneas de trabajo que tuvieran continuidad en el tiempo.

Esto fue algo en el que me involucraron aún sin tener mucho contexto junto al resto de managers de tech y producto, en parte venía bien tener a alguien con mirada limpia aunque en ocasiones pudiera pecar de ingenuo, para cuestionar supuestos y detectar disonancias.

En aquel entonces me resultó muy útil que alguna de la gente involucrada en la reorganización estuviera hablando en términos de Team Topologies, porque nos ayudaba a tener un lenguaje común. Eso lo terminamos enfrentando con un ejercicio de Context Mapping (en un par de eventos charlé sobre ello), donde representamos buena parte del funcionamiento de la compañía para ver el encaje de equipos respecto a la situación actual.

Este ejercicio sirvió para completar la foto real a la que íbamos, e incluso permitió detectar potenciales problemas de bounded contexts en los que había muchas manos y algunas en las que había muy pocas. Así que cuando con el paso del tiempo surgieron algunos problemas relacionados, no nos pilló tan por sorpresa.

Además, institucionalizamos el dar seguimiento a lo que surgía de las retros de los equipos, ya que se estableció como práctica que se documentase por escrito al menos lo más destacado de ellas y las acciones que surgieran. Esta práctica se mantiene a día de hoy, y resulta muy útil a la capa de management como complemento a los 1:1s para detectar fricciones y puntos de mejora.

Mucho de esto y algunas cosas más, las compartí en la charla Desarrollo de producto en una Scale-Up precisamente en la Pamplona Crafters 2024.

Foto donde hay algo más de 100 personas de pie posando para la foto, fondo con árboles y suelo adoquinado

Volviendo a hacer producto (interno)

Tras un año, mi foco cambió a ser algo más todoterreno. Por un lado, ya tenía bastante controladas las dinámicas en el área de desarrollo de producto y a nivel de plataforma había aún puntos de mejora en los que iba trabajando, pero estábamos ya más en una fase de mejora continua y constante, además el equipo de infraestructura seguía introduciendo grandes mejoras. Mientras tanto, en otras áreas de la compañía se identificaban problemas mayores con los que creíamos que podía aportar más.

Ventas

Uno que terminó surgiendo fue en el equipo de ventas, al que había que buscarle solución de forma prioritaria, ya que ninguna de las líneas de trabajo a priori tenía foco en ese tema. Teníamos un proceso interno ineficiente y propenso a errores que terminaban sufriendo clientes High Touch de gran tamaño: muchos emails y llamadas de coordinación, uso de spreadsheets de gestión, tiempos de espera por parte de clientes y account managers, etc.

Para solventar el problema se decidió montar un squad específico moviendo a algunos perfiles técnicos desde algunas líneas de trabajo, y como no queríamos sacar de foco a product managers terminé involucrado en la fase de discovery para abordarlo.

Así que tocó entender los problemas que el equipo de ventas se estaba encontrando y, junto a compañeras de customer experience, entrevistarnos con clientes y gente del área de ventas. A partir de ahí, documentar el impacto que estaba teniendo, definir un primer alcance del MVP usando un user story map y preparar un kick-off para tener tanto al squad, stakeholders y el resto de la compañía alineados.

El squad trabajó en una herramienta que diera mayor autonomía a esos clientes de gran tamaño, permitiendo a account managers mantener el control y darles seguimiento. Y en mi caso, aunque no tiré ni una línea de código y que luego me quedase acompañando al squad de lejos casi como un stakeholder más, me lo pasé como un enano volviendo a participar en hacer producto en fases iniciales.

Creativo

Tiempo más tarde, nos encontrarnos otro problema importante en el área de creativo. Uno de los valores que ofrece Genially a las personas usuarias son las plantillas diseñadas por este equipo. Nos encontramos con un problema de atasco en la publicación de nuevas plantillas y cambios en las existentes que antaño no ocurría, el producto había evolucionado de un modo en el que terminó afectando en la operativa diaria de este equipo.

Esto es porque una vez diseñadas, existía un cuello de botella en el proceso de publicación tanto en el producto como en la web pública. Esta ineficiencia en el Go to Market provocaba tardar más tiempo en recuperar la inversión, era propenso a errores y frustraba a las personas de ese equipo.

Al final era un problema para el que la perspectiva Lean encajaba como anillo al dedo: Identificar el valor, mapear el flujo de trabajo, mantener un flujo continuo, aplicar sistema pull y buscar la mejora continua. Para lo cual se decidió crear de nuevo un squad que se enfocara en esta área.

Una vez analizado y mapeado el journey principal que queríamos resolver, habiendo identificado los distintos hand-offs y limitaciones de las herramientas, planteamos crear un nuevo backoffice diseñado para habilitar mayor autonomía y que simplificase su proceso. De ese modo podríamos sustituir de forma incremental el backoffice legacy, un CMS y un par de spreadsheets de gestión.

Para acelerar el proceso de publicación introdujimos: soporte i18n, gestión de estados, uso de IA generativa, mejoras en las validaciones… Además de crear un servicio que pudiera consumirse desde el producto y la web, cosa que evitaba el uso de herramientas externas y, a nivel técnico, simplificaba la infraestructura y la mantenibilidad futura.

Una vez eliminado ese cuello de botella, que con la combinación del trabajo del squad con el equipo creativo pasó de un retraso de 4 meses a estar al día, nos centramos en mover y mejorar el resto de procesos que se soportaban aún en el legacy en esta nueva herramienta, y en el camino colaborar con uno de los equipos de producto para introducir algunas mejoras conjuntamente.

Operaciones y tech

Aproximadamente el último año en Genially mi rol terminó pivotando de manera oficial a trabajar con foco en las operaciones internas de la compañía. Esto significaba estar en un punto medio entre tecnología, producto, negocio, organización y su potencial impacto en la operativa diaria de cualquier área de la compañía. Esto implicaba mucha amplitud y normalmente menor profundidad, mucha comunicación, intentar promover iniciativas que tuvieran sentido o frenar las que aparentemente necesitasen reflexionarse más, identificar posibles problemas entre áreas de forma prematura, moverme todavía más habitualmente entre diferentes grados de abstracción, etc.

Siempre con una perspectiva de desarrollo de producto, durante ese tiempo tuve oportunidad de trabajar de nuevo y esta vez mucho más involucrado con el área de ventas y desarrollo de negocio; además de empezar a hacerlo también con las de financiero, personas, soporte y comunidad.

Trabajando con más áreas

Con el área de ventas empezamos a trabajar en hacer crecer el MVP que arrancamos antaño, soportando nuevas casuísticas primero y luego acercando e integrando esta herramienta con el CRM que se usa en la compañía. En mi caso había estado involucrado en el día a día de la línea de trabajo que lo evoluciona, con un rol de facilitador y ocasionalmente de desatascador.

Junto a las áreas de financiero y personas hicimos pequeñas iniciativas coordinadas con líneas de trabajo de producto, aunque algunas más ambiciosas se quedaron en el tintero porque el coste de llevarlas a cabo las hacían inviables al menos en el medio plazo.

Con soporte empecé a trabajar muy de cerca, ya que había una tormenta perfecta de cambios en el producto, iteraciones de negocio, atasco en los tiempos de respuesta y degradación de la experiencia de cliente.

Lanzamos varias acciones para solventar la situación: mejorar flujos en el chatbot, rehacer la integración con la herramienta de soporte para enriquecer la información de clientes y mejorar la gestión de colas, introducir automatizaciones, contratar e integrar a un proveedor para pasar a tener un chat basado en agentes de IA que escalase sólo casos complejos, etc. Una vez recuperada una situación de normalidad pudimos entrar en un modo de mejora continua en soporte, y poder dedicar más tiempo a iniciativas relacionadas con comunidad.

Y en medio de todo esto apoyar en ajustes organizacionales, tanto a nivel de desarrollo de producto como en el resto de áreas; y en iniciativas transversales, por ejemplo y para sorpresa de nadie, últimamente con foco en un par relacionadas con IA generativa.

Foto donde aparecemos 12 personas posando de pie, sucios y con barro en el suelo tras haber estado limpiando una casa en las afueras de Álora, Málaga, tras la DANA 2025 que también afectó a esa zona

Conclusión

Aunque al inicio costó un poco ver cómo gestionar ese tipo de rol pendular en el que a veces era difícil manejar la cantidad de cambios de foco y de niveles de abstracción, se me dio siempre confianza y autonomía. Finalmente me sentí muy cómodo con ese tipo de responsabilidades.

Me permitió poder influir a nivel organizativo como un manager primero a nivel de área y luego tratar de hacerlo a nivel de compañía, aunque sin las responsabilidades de gestión de personas. Y de vez en cuando poder ejecutar trabajo directamente por ejemplo programando, documentando o investigando de forma autónoma o colaborando con más personas en equipo.

Tras tener la oportunidad de trabajar con tanta gente diferente y variedad de áreas en el contexto de una scale-up, cierro esta etapa en Genially habiendo crecido mucho profesionalmente y con un montón de aprendizajes: técnicos, organizativos, de personas, de negocio… y siendo un fan de la marca y la compañía.

Y ahora ¿qué?

Toca arrancar una aventura nueva que no esperaba, uno de esos trenes que sientes que son una gran oportunidad que tienes que tomar, pero eso lo cuento un poco más adelante en otro post.

Jugando con MCP protocol. Añadiendo bus, bizi y geocoding a MCP DNDzgz

Tras mis primeras pruebas jugando con MCP sólo con la información del tranvía de Zaragoza, decidí dar el siguiente paso y añadir los otros servicios que históricamente ha soportado DNDzgz: autobús urbano y el servicio bizi, el alquiler de bicicletas municipal. Y con eso completar el soporte de los tres servicios públicos de movilidad más esenciales y usados en el día a día de las personas que viven o visitan la ciudad.

El soporte al servicio de bus en DNDzgz llevaba roto desde un cambio de contrata, por el que un scraper llevaba tiempo sin funcionar. Eso lo descubrí usando la versión web móvil en una de mis últimas visitas a Zaragoza, pero no le había dedicado tiempo hasta ahora. Una vez resuelto ese problema, volví a jugar con las tools de MCP usando Cursor para ir modificando y probando.

Añadiendo el soporte de bus y bizi, encontrando límites

La implementación fue bastante directa, al ser algo tan sencillo le iba pidiendo al agente de Cursor que me generase el código para las tools de servicio de bizi y bus, tanto traer las posiciones como obtener la respuesta de los datos de estimación o disponibilidad en tiempo real.

Captura con el agente de Cursor respondiendo estimaciones en la parada de Plaza San Francisco

Sobre la marcha se me ocurrió que ya que el API de DNDzgz tiene información geolocalizada, podría estar bien un modo de conocer la ubicación rápidamente, así que añadí una nueva tool para que genere un enlace a google maps usando las coordenadas.

Captura del agente de Cursor dando enlace a google maps para llegar a una estación de bizi y la disponibilidad de bicis

El problema apareció con el servicio de autobuses, que daba un error por terminar siempre con una conversación excesivamente larga. Esto se debía a que esta llamada devolvía una respuesta con un array JSON con unos pocos miles de objetos, cosa que tampoco es lo ideal pensando en los costes que tienen asociados estos LLMs con el consumo de tokens. Y como las pruebas siempre las he ido haciendo con cuentas gratuitas, esto se hizo evidente con este escenario.

Por ejemplo por parte de Cursor no encontré documentación del límite pero la respuesta está clara. “Your conversation is too long”

Captura con error al obtener paradas de bus con el agente de Cursor

Mientras Claude Desktop daba un error más raro, sobre que la respuesta fue interrumpida. Pero en su caso sí lo tienen documentado: How large is Claude’s Context Window?

Captura con error al obtener paradas de bus en Claude Desktop

Tratando de reducir el tamaño de respuesta

Así que para salir del paso empecé a pensar cómo aligerar el tamaño de respuesta intentando no tener que tocar nada del API de DNDzgz, limitando los cambios al MCP server.

Como primer paso traté de ajustar la respuesta a lo mínimo necesario. Quitar el único atributo de la respuesta que no se usaba y filtrar resultados de paradas que sabía que no tienen realtime, ya que son del transporte metropolitano y no del urbano. Esto se podía intentar identificar con las líneas en cada parada al seguir esta patrones diferentes en su nomenclatura.

Eso era un poco cutre y aún así el tamaño de respuesta se mantenía muy alto. Debía intentar encontrar una manera de afinar lo máximo posible lo que devolvía MCP DNDzgz para evitar responder con cientos o miles items en las peticiones recibidas.

Con eso en la cabeza lo dejé reposar durante unos días, finalmente se me ocurrieron otras 2 soluciones:

En un primer momento pensé en la posibilidad de tratar de montar un filtro sobre texto para devolver el mínimo de estaciones o paradas posible. Dada la interfaz conversacional tenía la sensación que todo lo que no fuera una búsqueda de vectores para hacerlo de un modo semántico podía resultar una experiencia de usuario mediocre. Como es algo con lo que ya he experimentado un poco en otras pruebas de concepto, sé que podría haber jugado con el vector store en memoria de LangChaning y usar para los embeddings un proveedor externo o incluso añadir dependencia a Ollama.

Más tarde se me ocurrió otra opción, la búsqueda semántica es buena opción si sabes más o menos qué andas buscando. Pero dada la naturaleza de geolocalización de los servicios de movilidad lo más importante es el dónde lo andas buscando. Así que tal como están los datos expuestos en DNDzgz, veía que tenía más sentido ir por el camino de añadir una nueva tool que resuelva localizaciones y luego hacer búsquedas por posición. Esto parecía tener mucho sentido y estaba alieneado con el comportamiento que había visto en varias ocasiones de Claude, en el que el modelo me iba ofreciendo estimaciones en posiciones cercanas.

Solución desde la experiencia de uso de DNDzgz

Parece que tiene bastante sentido pedir cosas como “¿Dónde puedo coger el 30 en la zona de Paseo de la Independencia?”, “Estoy en el Parque Bruil, ¿dónde tengo bicis disponibles cerca?” a un asistente con interfaz conversacional. Al final son los tipos de respuestas que intentamos responder ya en tiempos del AbreDatos 2010 con una interfaz pensada para usarse en un teléfono móvil.

Con esta idea tiré por lo ya conocido, el API de Google Maps para geocoding, aunque podría haber tirado también por cualquier otro proveedor. Y exponerlo como otra tool, intentando forzar que siempre busque concatenando al valor recibido Zaragoza, Spain.

Tras eso las respuestas eran ya prometedoras, ya que parece que estos modelos trabajan bastante bien con posiciones geolocalizadas. Por ejemplo preguntándole sobre paradas de bicis cerca de la Avenida Madrid decía esto.

Captura de Claude Desktop devolviendo paradas de Bizi por Avenida Madrid

Todavía en este momento se devolvían las más de 100 estaciones de bizi que hay disponibles, y en el caso de los buses eran más de 1000. Lo siguiente era pasar la posición dada a partir de una dirección a las tools que traen las ubicaciones con sus respectivas posiciones, comprobar la distancia entre posiciones usando una implementación de la fórmula de Harversine, ordenarlas por cercanía y devolver un top razonable para que los LLMs hagan lo suyo.

Una vez implementado eso, dejando el límite a 10, se acotan mucho los resultados y la experiencia aparentemente era algo mejor. Ahora ordenando por distancia entre los puntos e informa sobre ello, además se ofrecen otras opciones indicando lo lejos del punto de referencia.

Captura de Claude Desktop devolviendo paradas de Bizi por Compromiso de Caspe

A partir de ahí el problema del tamaño del bus dejó de serlo.

Captura de Claude Desktop responidendo sobre los tiempos de la línea 22 en plaza Aragón dirección a Las Fuentes

Durante mis pruebas me encontré que Claude intenta llamar varias veces a las tools en ocasiones donde considera que las distancias son alejadas o cuando no consigue obtener datos del estado en tiempo real, está claro que no le gusta quedar mal 🙂. Por ejemplo con esta prueba preguntando sobre una línea de bus en una dirección.

Captura de Claude Desktop tratando de responder con estimaciones del 30 en Plaza San Miguel intentando corregir errores del API

También para variar y ver más comportamientos, hice alguna prueba con GitHub Copilot y GPT-4o en modo agente, con los que la experiencia a priori me resultó bastante similar.

Captura de GitHub Copilot preguntando sobre el Circular 2 en camino de las Torres

Hay otras tools que podrían llegar a ser muy útiles y serían complementarias, por ejemplo para cubrir casuísticas de recomendar de cómo llegar de un punto a otro de la ciudad en transporte público. Ya que los datos con los que fueran entrenados los modelos pueden haber quedado desactualizados o puede que se los estén inventando.

Por ejemplo, al preguntarle cómo llegar de Plaza Aragón a Arcosur en tranvía me decía correctamente que a Arcosur no llega el tranvía y que tendría que hacer transbordo tras la última parada. Pero me ofrecía como alternativa sin trasbordo la posibilidad de la línea de bus 59 desde Plaza de España, al pedirle las estimaciones terminó dándose cuenta que esa opción no existe por sí mismo.

Captura de Claude Desktop equivocándose con la línea 59 y posteriormente corrigiéndose a sí mismo

Conclusiones

Este experimento con tools de MCP para darles capacidades extra a los LLMs me ha resultado muy entretenido. En esta evolución he intentado darle un enfoque de solución un poco más de producto y no quedarme meramente en probar el protocolo.

He buscado soluciones pensando en las personas usuarias, aunque he hecho 0 investigación, sí he hecho memoria de feedback y críticas recibidas sobre las aplicaciones móviles de DNDzgz durante estos años.

Algunos pensamientos al respecto de este side-project:

  • Las tools mucho mejor si envían respuestas ligeras, por cuestiones de eficiencia de red, coste, consumo energético, tiempos de respuesta, etc.
  • Tratar de dar buenas descripciones a las tools para facilitar que los LLMs tengan más claro cuando usarlo respecto a las intenciones de las personas usuarias.
  • Eat your own dog food como para cualquier side-project, salvo que sólo quieras cacharrear con la tecnología y luego olvidarte.
  • Que alguien más lo pruebe te va a ayudar a mejorarlo, aunque no hagas test con personas usuarias al uso viene bien tener otros puntos de vista.
  • Al usar directamente estos LLMs con estos clientes tratan de quedar bien, a veces eso significa que puedan alucinar. Así que lo suyo es facilitarles tools que puedan ayudarles a no hacerlo en los temas que nos competen.
  • Como se van a buscar la vida para dar una respuesta, esto significa que pueden hacer muchas llamadas a su aire a nuestras tools sin que la persona que le ha pedido algo intervenga.
  • Por esto último, ahora mismo me daría un poco de miedo el exponer acciones destructivas en una tool que no se puedan deshacer: Borrar documentos, sobreescribir información sin versionado, etc.
  • Supongo que montando un chatbot especializado, con prompts de sistema para los LLMs y que actúe como cliente MCP, son potenciales problemas que se pueden solventar. A corto plazo dudo que me meta en ese fregao 😀.

Podéis ver el código de mcp-dndzgz en github con los cambios comentados en el artículo.

Jugando con MCP protocol. Introducción.

Llevo unas semanas leyendo un poco sobre el hype de Model Context Protocol, hay mucho escrito ya sobre MCP y en mi caso sólo me he asomado a este protocolo muy tímidamente, pero comparto algunas referencias que me han parecido muy interesantes:

Mientras he ido leyendo fui pensando en qué pequeño pet-project podía hacer para experimentar un poco y me acordé de DNDzgz.

Y aunque el preguntarle a Claude Desktop o a Cursor las estimaciones de llegada del tranvía a plaza Aragón para ver si sales ya del estudio o del coworking en un día de cierzo 🥶 a mi tampoco me parece una killer feature. Pensé que podía ser una casuística fácil de implementar pedirle los tiempos de llegada del tranvía, que son datos que se requiere tener en tiempo real.

En la captura se pregunta ¿Cuándo llegará el tranvía a la parada de Romareda? y luego se ve la respuesta de Claude

Técnicamente no tiene mucho misterio:

  • El MCP server está implementado con Node y el transport Standard Input/Output, así que los MCP Hosts se encargan de arrancarlo.
  • Se hacen llamadas fetch al API de DNDzgz, a los endpoints que devuelven todas las paradas del tranvía y el tiempo estimado en cada parada.
  • Y esto se expone como dos diferentes Tools para que los modelos lo llamen tras que la persona que lo usa de el ok.

Podéis ver el código de mcp-dndzgz en github.