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.

Desarrollo de producto en una Scale-Up. SCPNA 2024

Más vale tarde que nunca, recopilo y comparto por aquí la charla que preparé para la Software Crafters Pamplona 2024: Desarrollo de producto en una Scale-Up

Sígueme en esta historia donde te contaré cómo pasamos en Genially de una idea, un insight a una feature 100% desplegada en producción con su Go to Market incluido. Vamos a ver todo el value-stream por el cual pasamos, los actores, viendo cómo nos organizamos, procesos que seguimos, el tooling que usamos para las diferentes fases y algunas curiosidades más. Seguro que pasamos un rato entretenido.

Esta charla la tenía apalabrada Chema Roldán, CTO de Genially, con la buena gente de Software Crafters Pamplona. Pero como finalmente tenía problemas de agenda terminé preparándola yo con su ayuda y la de algunas otras personas de la compañía.

Foto de una de las salas del evento

Después de darle varias vueltas la terminamos estructurando en 4 partes:

  • Organización: Dando contexto de la compañía, número de personas y qué equipos había en ese momento, la planificación de iniciativas por trimestre, prácticas de coordinción y herramientas que utilizamos.
  • Descubrimiento: Para explicar cómo típicamente se idean y da forma a las iniciativas, la manera en la que se aplica el modelo de diseño de doble diamante, etc.
  • Entrega: La parte técnica de cómo se construye y despliega el software, introduciendo algunos retos de trabajar con un monorepo, la branching strategy utilizada, la frecuencia de despliegue, etc. Hablando de las herramientas técnicas que se venían usando.
  • Go to Market: Donde se entraba en detalle de las estrategias de rollout de funcionalidades, cómo se comunicaba internamente al resto de la compañía y externamente a nuestros clientes, el stack de observabilidad y telemetría tanto técnico como de producto y cómo se gestionan los incidentes.

Muchos meses más tarde como parte de la cultura de mejora continua algunas cosas se han ido iterando y puliendo, pero el grueso de la charla sigue siendo válida a día de hoy.

Aquí dejo el vídeo

Y por aquí el genially de la presentación

¡Nos vemos en la edición de 2025! Esta vez como asistente, sin la presión de tener que presentar :).

Equipos multidisciplinares de producto en Mosaic

Desde hace bastante tiempo que de vez en cuando algunas personas me habían ido dejando caer lo de que me animara a publicar algo o preparar alguna charla relacionada en cómo colaborar mejor entre diseño y desarrollo en esto del desarrollo de software o producto digital. Para charla la verdad que nunca me había motivado mucho, pero en un par de ocasiones arranqué borradores con enfoques diferentes, pero al final los terminé dejando aparcados por no terminar de encontrar un hilo conductor.

Pero cuando hace unos meses me llegó la propuesta de César de escribir sobre equipos multidisciplinares de producto, con foco principalmente en quiénes tienen perfiles de desarrollo y diseño, para la revista Mosaic de la Universitat Oberta de Cataluña, me decidí a hacer un nuevo intento.

Esquema representando un flujo desde descubrimiento a despliegue y aprendizaje

Para mi era un reto combinar el darle un enfoque algo generalista, dado la variedad de audiencia que tiene la revista, con intentar que aportase algo a profesionales del sector que lleguen a leerlo. Por eso evité usar demasiados tecnicismos más allá de algunas referencias relacionadas con Lean Software Development, Design Systems/Tokens y Hot Potato Process que me servían como puntos de apoyo para desarrollar el artículo y llegar a la conclusión final:

“En el mundo de creación de proyectos o productos digitales, los equipos multidisciplinares van a seguir siendo tendencia por su mejor adaptación al actual entorno cambiante. Para que estos funcionen bien, debemos tratar de trabajarlos a nivel personal, con el resto del equipo y a nivel organizacional.

Y, en esencia, en cualquiera de los niveles, debemos buscar tres factores:

  • Tratar de que las personas que formen el equipo estén alineadas hacia una meta común. Así como que su meta esté dentro de los objetivos de la organización.
  • Tratar de que el conjunto de capacidades individuales haga viable alcanzar esa meta, o que al menos puedan llegar a capacitarse para hacerlo.
  • Tratar de que siempre haya respeto, y de conseguir que exista empatía entre las personas del equipo y del resto de la organización con las que se interactúe.

Sí, factores infinitamente más fáciles de verbalizar que de conseguir.”

Lo puedes leer en castellano: Equipos multidisciplinares de desarrollo de producto digital

També ho pots llegir en catalá: Equips multidisciplinaris de desenvolupament de producte digital

And also in english: Multidisciplinary digital product development teams

El lado estratégico de Domain-Driven Design. CommitConf 2024

Hace unas semanas estuve en Commit Conf en Madrid, evento al que no iba desde hace mucho. Estuve compartiendo la charla El lado estratégico de Domain-Driven Design, iterando ligeramente la que hice hace unos meses en La Vertical, a su vez basada en una charla más larga (y espesa) que he impartido in-company en varias ocasiones.

Foto de la sala de conferencias del track 1 del evento

En los últimos años ha crecido el interés y la adopción de Domain-Driven Design en la comunidad de desarrollo de software. Ahora es bastante habitual oír hablar del lado táctico de DDD, la mayoría de las veces acompañado del uso de ports & adapters (aka Hexagonal Architecture). Pero, al menos en castellano, no he visto hablar apenas de DDD estratégico y lo que nos puede aportar a nivel de Sociotechnical Architecture.

Así que de ahí vino buena parte de mi motivación de proponer repetirla en un evento mucho más masivo como es la Commit Conf.

La presentación está dividida en 4 bloques:

  • Introducción a DDD y específicamente a la parte estratégica
  • Resumen de las actividades estratégicas basado en el Domain-Driven Design Starter Modelling Process de DDD Crew
  • Un ejemplo práctico de DDD estratégico basado en un caso real, mostrando su división y conexión entre dominios visibilizándolo con un Context Map un tanto enriquecido con su clasificación desde diferentes puntos de vista
  • Otras consideraciones a tener a nivel de la organización de equipos

Aquí os dejo el vídeo de la charla

Y el genially que usé para la presentación