What 19 MCP tools look like when you design them as a pipeline
Cuando instalas un MCP server y ves "19 tools active" en el cliente, la primera reacción es "son demasiadas". Esa fue la mía. Tres meses después, mirando cómo las usaba el agente, me di cuenta de que mapeaban uno-a-uno a un pipeline que ya existía — y que ahora era navegable por el agente sin que yo lo explicara.
La decisión de diseño detrás de esas 19 no fue "expongamos todo lo que hace la lib". Fue "identifiquemos los stages reales del workflow y demos una herramienta por stage". Esa diferencia es la que vuelve la API consumible o ilegible. Y la lección, en retrospectiva, es que el número de tools importa menos de lo que parece — lo que importa es la estructura.
El error común: tools como endpoints CRUD
La intuición por defecto, cuando uno expone una API a un agente, es modelar las tools como verbos REST sobre las entidades del modelo: list_archetype, get_archetype, create_archetype, update_archetype, delete_archetype. Cinco tools por entidad. Si tienes seis entidades, ya vas en treinta. Si tienes diez, en cincuenta. La progresión es aritmética y deprimente.
El problema no es el número — es lo que pasa cuando el agente intenta hacer un workflow real. Para validar un PR con la rúbrica completa, el agente termina haciendo cinco o seis llamadas: lista arquetipos, obtiene uno, lista sus dimensiones, obtiene sus criterios, evalúa, agrega. Cinco roundtrips para una operación que conceptualmente es una. Cada roundtrip es overhead de tokens, latencia, y posibilidad de error.
El contexto se infla con respuestas intermedias que sólo sirven para encadenar la siguiente llamada. La latencia se acumula. Y peor: el agente, al tener que componer el workflow desde primitivas crudas, se equivoca. Salta pasos. Llama tools en orden incorrecto. Inventa parámetros porque la documentación de cada tool individual no transmite cómo se compone con las otras. La composición se vuelve un ejercicio de razonamiento que el agente puede o no resolver bien.
Hay una falla más sutil: las tools CRUD reflejan tu data model, no la intención del usuario. El agente termina razonando sobre tu schema de base de datos en vez de sobre el problema que el usuario quiere resolver. Esa es exactamente la abstracción equivocada — el usuario quiere validar un PR, no navegar entidades.
El switch: tools como stages del pipeline
La alternativa es modelar las tools como stages del workflow real, no como operaciones CRUD del data model. Cada tool corresponde a un paso conceptual del proceso que el usuario realmente ejecuta. El agente llama una tool por stage en vez de cinco. La cardinalidad cae, el contexto se mantiene compacto, la composición se vuelve obvia.
El output tipado de cada tool es el input tipado de la siguiente. Esto es exactamente el mismo patrón que aplica el pipeline interno de agentguard-lib — los stages skeleton → contracts_and_wiring → logic → validate operan con contratos tipados entre uno y otro. Cuando expones esos stages como MCP tools, la composición es trivial para el agente porque la estructura está hecha para ser compuesta. El agente está siguiendo un grafo, no inventándolo.
La diferencia es enorme en práctica. El agente compone, no inventa. La latencia agregada baja. El contexto se mantiene compacto. Y los errores son localizables — falló este stage, con este input — en vez de "algo en algún lado del workflow". Para quien tiene que debuggear cuando un usuario reporta un caso raro, esa propiedad sola justifica el rediseño.
Hay un beneficio adicional que sólo aparece después de operar el sistema un tiempo: las tools como stages son estables. Las CRUD cambian cada vez que cambias tu data model. Los stages cambian cuando cambia tu workflow, lo cual es mucho menos frecuente. Esto reduce la cantidad de breaking changes que pasas a clientes externos.
Las 19, agrupadas
Las 19 tools se agrupan en cinco categorías funcionales que reflejan la estructura del workflow completo.
Discovery: list_archetypes, get_archetype. Sirven para que el agente vea qué arquetipos existen — los built-in (api_backend, library, cli_tool, react_spa, web_app, script) y los que estén instalados del marketplace — y obtenga el detalle del que va a usar. Es la entrada al sistema. El agente típicamente las llama una sola vez al principio de la sesión y cachea internamente el resultado.
Generation: agentguard_skeleton, contracts_and_wiring, logic. Son los tres stages de generación expuestos como tools individuales. El agente los compone en orden — output del anterior alimenta al siguiente — y produce el código. La granularidad por stage permite al agente decidir, por ejemplo, regenerar sólo logic() si el skeleton ya está bien.
Evaluation: get_challenge_criteria, validate, digest. El primer tool entrega los criterios que el cliente LLM tiene que aplicarse a sí mismo (el patrón AgentNativeEvaluator). Validate corre la evaluación. Digest produce el reporte legible. La separación entre obtener criterios y evaluar permite que el agente cliente — que tiene su propio LLM — haga el juicio sin depender de credenciales del server.
Benchmark: benchmark, benchmark_evaluate. Son dos tools por una razón específica que vale la pena explicar aparte. La separación responde a una restricción operacional concreta, no a un capricho de diseño.
Platform: auth, marketplace_install, marketplace_list, y similares. Operaciones meta: autenticación opcional, instalar arquetipos del marketplace, gestionar la cuenta. Son las menos llamadas pero las que sostienen el resto.
Por qué dos-pasos en benchmark
El MCP server no tiene API key para el LLM del cliente. Esa es la realidad operacional: el cliente — Cline, Claude Desktop — está corriendo con su propia credencial, y el server MCP no la ve ni debe verla. La seguridad por compartmentación es importante; mezclar credenciales sería una mala práctica que además sería difícil de explicar a cualquier auditor. Pero un benchmark necesita un LLM para generar respuestas a los prompts, y ese LLM es el del cliente.
La solución fue partir benchmark en dos tools. benchmark() genera los prompts que componen el benchmark y los devuelve al cliente. El cliente — el LLM del usuario — produce las respuestas a esos prompts en su propio espacio, con su propia key, su propio modelo, su propia capacidad. Después, benchmark_evaluate() recibe las respuestas y aplica el scoring. La separación es operacional, no conceptual. El benchmark es un solo concepto desde la vista del usuario; son dos tools desde la vista del transporte.
Es un patrón generalizable. Cuando el caller es dueño del LLM y tú no, separa "qué preguntar" de "qué evaluar". El primer paso es información — el caller la usa con su propio modelo. El segundo paso es scoring — el caller te trae las respuestas y tú devuelves el juicio. Funciona para benchmarks, para evals, para cualquier flow donde necesites inferencia que no controlas. La asimetría "yo defino el qué, tú ejecutas el cómo" es robusta a un montón de configuraciones de despliegue distintas.
El protocolo detallado de cómo funcionan esos benchmarks está en paper §3. El paper desarrolla el método incluyendo cómo se construyen los prompts representativos y cómo se garantiza la comparabilidad entre arquetipos distintos.
Lo que no funcionó al principio
La primera versión que probé fue una tool muy genérica: validate(everything). El agente se perdía. No sabía qué pasarle, no sabía cómo interpretar lo que volvía, terminaba haciendo llamadas con parámetros vacíos o cargados en exceso. Demasiado polimórfico para ser útil. La tool intentaba ser todo y terminaba siendo nada — un patrón anti que ya conocíamos de diseño de APIs convencionales y que igual cometí en este contexto nuevo.
La segunda versión fue el extremo opuesto: tools muy específicas, una por dimensión. validate_type_safety, validate_observability, validate_testability, una por cada uno de los 13 ejes. Explosión combinatoria — el agente tenía que hacer 13 llamadas para validar y nunca elegía bien cuáles. El contexto se llenaba con metadata de tools que no usaba. Cada tool tenía una descripción casi idéntica a la siguiente, lo que volvía aún más confuso para el modelo distinguir cuándo usar cuál.
El sweet spot fue: una tool por stage del pipeline, parametrizable cuando hace falta granularidad. validate() toma parámetros opcionales para limitar qué dimensiones evaluar, pero por default evalúa todas. Una sola tool, pero compuesta con el resto del pipeline de forma que el agente entiende. El loop de iteración fue "genérico → específico → estructural", y la lección es que la respuesta no estaba en ningún extremo del trade-off; estaba en encontrar la unidad correcta de abstracción.
Esta misma lección se aplica a diseño de APIs en general — pero en MCP el costo de equivocarte es más visible, porque cada tool extra es ruido en el contexto del agente, y cada call extra es latencia perceptible.
Transferable Principle
Si vas a exponer tools a un agente, mapéalas a tu pipeline, no a tu data model. El pipeline refleja la intención del usuario. El data model refleja cómo guardas las cosas. Esas dos cosas no son la misma — y el agente compone mucho mejor sobre la primera. Esta es la diferencia entre diseñar una API que le sirve a un sistema y diseñar una API que le sirve a una persona (o a un agente que actúa como proxy de una persona).
Las tools son la API de tu agente. Diséñalas con la misma disciplina con la que diseñarías una API pública: versionada, tipada, documentada, con contratos explícitos entre operaciones, con descripciones que comunican intención no sólo signature. "Es para un agente" no es excusa para diseño laxo — es exactamente lo opuesto, porque el agente no va a leer comentarios sueltos en el README ni a preguntar al author cuando algo no le queda claro. Lo que está escrito en las descripciones es todo lo que tiene.
Menos tools profundas le ganan a más tools shallow. El agente compone, no inventa. Una tool que cubre un stage completo y deja parámetros opcionales para granularidad le sirve más que diez tools que cubren cada subcaso. La regla práctica que terminé usando: si dos tools se llamarían siempre juntas o nunca, probablemente son una sola tool mal cortada.
Pregunta para comentarios: si tu equipo expone tools a un agente hoy, ¿estás modelando el pipeline real o el CRUD que hay debajo?
#AI #GenAI #DeveloperExperience #Architecture #OpenSource