Saltar al contenido
←Proyectos
9 de octubre de 20267 min de lecturaEn desarrollo

leo-mcp - el mapa real del código para tu agente.

Un servidor MCP que da a los agentes de código el grafo de llamadas real de un repo, comprobado contra el AST de Python y el compilador de TypeScript. Ya funciona; está en beta.

PythonMCPtree-sitterAST

Un agente de código, cuando no sabe dónde está algo, hace lo que haría cualquiera sin mapa: busca por texto y lee archivos enteros. Gasta tokens en código que no necesita y, peor, responde sobre la estructura del proyecto adivinando. Si le preguntas qué se rompe al cambiar una función, te da una respuesta que suena bien, pero nadie la ha comprobado.

leo-mcp resuelve eso: le da al agente el grafo de llamadas real del repo, con el archivo y la línea de cada respuesta. Ya funciona y está en fase beta. Aquí cuento cómo está hecho, qué está probado y qué falta todavía.

De un agente propio a un servidor MCP

Empezó en mayo como mi propio agente de código, montado sobre opencode, con una forma de recuperar código que llamé KC-RAG (la expliqué en este artículo). Con el tiempo me quedé con la parte que de verdad aportaba, el mapa del código, y separé todo lo demás: lo convertí en un servidor MCP, que es el protocolo que ya entienden Claude Code, Cursor, Codex u opencode, y quité el agente.

Lo que ya funciona

El servidor da dos herramientas al agente. La primera, graph, responde preguntas sobre la estructura sin usar ningún modelo, recorriendo el grafo:

  • where: dónde está definido un símbolo.
  • who_calls: quién lo llama.
  • impact: todo lo que depende de él, directa o indirectamente. Es decir, qué se rompe si lo cambias.
  • trace: el camino de llamadas de A a B, incluido el salto de un fetch('/api/x') del frontend a la ruta del backend que lo sirve.
  • guard: lo mismo que impact, pero marcando qué partes afectadas no tienen ningún test.

La segunda, get_context, recibe una pregunta en lenguaje normal y devuelve solo el trozo del grafo que la responde: las funciones relevantes con su código, comprimidas. Cada respuesta dice cuánto se ha ahorrado frente a leer los archivos enteros, y en mis pruebas está entre un 80 y un 97% menos por consulta.

Alrededor hay una línea de comandos para indexar un repo, comprobar la instalación y añadirlo a un proyecto en un paso. El índice se guarda en la caché del usuario, nunca dentro de tu proyecto, y un vigilante del sistema de archivos vuelve a analizar solo lo que ha cambiado.

Un aviso antes de romper algo

En Claude Code, leo-mcp se engancha justo antes de cada edición. Si el agente va a tocar una función de la que dependen otras sin test, se lo dice al agente para que las revise, y a ti en una línea. El resto del tiempo no dice nada, a propósito: un aviso que salta en cada edición es un aviso que acabas desactivando.

Tarda unos 0,28 segundos por edición y nunca bloquea un cambio: no tiene forma de hacerlo, y eso está cubierto por tests. Que no avise tampoco es una garantía, y lo digo tal cual: es un grafo estático, así que una dependencia a través de una cola, un WebSocket o un nombre construido con texto no aparece.

Comprobado, no estimado

Un mapa que se equivoca es peor que no tener mapa, así que no me fío del mío: en cada cambio, la integración continua reconstruye todas las relaciones con herramientas que no son las mías y las compara una a una. Si el grafo empeora, el cambio no entra.

  • Python: comparado con el propio ast de Python en unos 100.000 símbolos y 480.000 relaciones, de este repo y de tres proyectos externos. 100% de precisión y de cobertura.
  • TypeScript y JavaScript: comparado con el compilador tsc sobre el propio repositorio de TypeScript, con 36.739 símbolos. 99,95% de precisión y 99,93% de cobertura. Lo dejo sin redondear.
  • Velocidad: con 271.493 símbolos indexados, la consulta más lenta tarda menos de 2 milisegundos.

Medido con agentes reales

Lo probé con opencode en 15 tareas repetidas tres veces, contando todos los tokens, también los de los subagentes. Con leo-mcp las respuestas salieron igual de buenas o mejores, las tareas tardaron un 14% menos y el gasto total de tokens bajó un 30% en conjunto. En una tarea normal el gasto queda casi igual; el ahorro está en las tareas pesadas.

Al principio me puse como objetivo un 40% menos de tokens de principio a fin. Probé seis configuraciones y todas salían peor o igual, así que lo descarté y me quedé con lo que sí podía demostrar.

Después lo probé en un proyecto que no era el mío, con FastAPI y Next.js. Se instaló desde cero en 6 segundos, indexó el proyecto en un segundo y no escribió ni un archivo dentro. Claude Code respondió las mismas preguntas con un 26% menos de tokens, y donde más se notó fue en las preguntas de estructura, como qué se rompe al cambiar un tipo. Esa prueba también me sirvió para encontrar y arreglar varios fallos que habría sufrido cualquiera que lo instalara.

Lo que falta

Todavía no está publicado en npm ni en PyPI, así que de momento se instala desde el repositorio. Está en beta y el repositorio ya tiene una plantilla para recoger el feedback de quien lo pruebe. Python y TypeScript se analizan con su árbol sintáctico completo; Go, Java, Rust, PHP y otros lenguajes, de forma aproximada.

Lo que aprendí

Que un número sin medir no vale nada. Habría sido fácil poner "un 40% menos de tokens" en el README. Medirlo me obligó a quitarlo, y lo que quedó es más pequeño, pero cada cifra se puede reproducir con los comandos que hay en el repositorio.

Construido porIsmael Manzano LeónFull Stack Developer · leo/ · leosoftware.dev
Ver en GitHub→ (se abre en una pestaña nueva)