- Aunque se afirma que la conexión de herramientas mediante MCP es el “futuro”, en la práctica sigue siendo más eficiente escribir código directamente debido a limitaciones como la falta de composabilidad y el consumo excesivo de contexto
- Incluso en la era de los LLM, para automatización y tareas repetitivas, generar y usar código sigue teniendo ventaja en términos de confiabilidad y verificación
- Los LLM destacan más en la generación de código y su ejecución repetida que en la automatización basada en inferencia; los procesos basados en código sobresalen para detectar problemas, verificar y escalar
- Algunas herramientas como Playwright (en modo MCP) aumentan la incertidumbre y la dificultad de depuración en cada paso “basado en inferencia”, mientras que generar/modificar scripts directamente en código mejora la repetibilidad, la velocidad y la confiabilidad
- En la práctica, el flujo de automatización más potente es el bucle de “código-revisión-iteración”, donde un LLM genera código y otro LLM lo revisa y explica
Con solo código basta
- Si me sigues en Twitter, probablemente ya sabes que últimamente no he sido muy positivo sobre el Model Context Protocol (MCP)
- No es porque rechace la idea en sí, sino porque MCP no funciona tan bien como se promociona
- MCP tiene dos fallas principales
- No ofrece una verdadera composabilidad (composable)
- Debido a que requiere proporcionar demasiado contexto, termina consumiendo más contexto que escribir y ejecutar código directamente
- Esto se puede comprobar con un experimento simple
- Por ejemplo, si realizas una tarea usando GitHub MCP y luego haces el mismo trabajo con la herramienta CLI
gh, la segunda usa el contexto de forma mucho más eficiente y llega más rápido al resultado deseado
But MCP is the Future! : Pero, ¿MCP no es el futuro?
- Quiero hablar del feedback que he recibido sobre esta postura mía, la de que el código es mejor
- He experimentado a fondo con MCP en el contexto de agentic coding, y lo he evaluado justo en el área donde sus limitaciones se hacen más evidentes
- Un comentario que recibí fue que “MCP realmente no es necesario para la generación de código de propósito general, porque los modelos ya son suficientemente buenos para eso”. En cambio, también me dijeron que MCP podría tener sentido en aplicaciones orientadas al usuario final dentro de dominios específicos (por ejemplo, automatización en una empresa financiera)
- Otra opinión es que en el futuro los modelos tendrán acceso a más herramientas y podrán encargarse de tareas más complejas, así que hay que fijarse en ese potencial
- Pero mi juicio actual es este: según los datos de mis experimentos y mi experiencia real, el MCP actual siempre es más difícil de usar que escribir código directamente
- La razón principal es que MCP depende de la inferencia
- Si miras hoy todos los intentos de conectar más herramientas a un LLM, al final siempre aparece una capa donde el LLM recibe todas las herramientas y luego las filtra según la tarea
- Hasta ahora no se ha propuesto una estructura o enfoque mejor que ese
- Por eso llego a esta conclusión: incluso en casos especiales como la automatización de dominios específicos para usuarios no desarrolladores, la generación de código sigue siendo siempre una mejor opción en composabilidad y reutilización
Replace Yourself With A Shellscript
- Una forma de ver este problema es esta: sin IA, para un desarrollador la herramienta para resolver problemas es el código
- Para un no desarrollador, el código es difícil, y muchas tareas que la gente hace manualmente en realidad podrían automatizarse con software
- El problema real es quién va a escribir ese código. Si estás en un entorno muy particular y no sabes programar, tampoco es fácil aprender de cero ni esperar que alguien te escriba código a la medida
- Claro, algunas tareas pueden requerir sí o sí inferencia (juicio humano/flexibilidad), pero en la práctica la mayoría de las tareas repetitivas y bien definidas se pueden automatizar con código
- Existe un viejo modismo entre desarrolladores: “reemplazarme a mí mismo con un shell script”, y este tipo de automatización viene ocurriendo desde hace mucho
- En la era de los LLM y la programación, estamos intentando reemplazarnos a nosotros mismos con un LLM en vez de un shell script, pero aquí aparecen tres problemas: costo, velocidad y confiabilidad
- Antes de resolver esos tres problemas, ni siquiera estamos en la etapa de pensar en usar herramientas como MCP
- Es decir, lo clave es garantizar primero que la automatización realmente funcione de forma correcta y escalable
Automation at Scale : la esencia de la automatización a gran escala
- La esencia de la automatización es procesar con código tareas repetitivas y reutilizables
- No hace falta automatizar algo que solo vas a hacer una vez y nunca más. La automatización empieza con las tareas que se repetirán muchas veces, donde la máquina realmente aporta una ganancia de productividad
- En la práctica, la esencia de la automatización es hacerlo manualmente una o dos veces, entender cómo funciona y luego hacer que la máquina lo repita miles de veces
- Para esta clase de automatización repetitiva, siempre es mejor usar “código”
- Si le pides al LLM que “razone” cada vez, puede salir más o menos bien en cosas pequeñas, pero el tiempo y esfuerzo de validación terminan reduciendo el beneficio de automatizar
- Ejemplo: en vez de pedirle al LLM que haga cálculos directamente, es mejor hacer que el LLM escriba código en Python y que el cálculo se haga con ese código, porque así suben tanto la confiabilidad como la escalabilidad
- Al usar código, puedes revisar la fórmula o la lógica en sí, y si hace falta puedes modificarla directamente o pedirle al LLM que revise si “este enfoque es correcto”
- No hay que preocuparse de que Python vaya a calcular mal, así que queda claro que el enfoque basado en generación de código es mejor en verificación y confiabilidad
- Esta lógica va más allá de los cálculos simples y también aplica al trabajo real de desarrollo
- Por ejemplo, hace poco convertí todo el formato de este blog de reStructuredText a Markdown
- Lo había pospuesto bastante tiempo; me daba flojera, pero además no confiaba en delegar la conversión directamente a un LLM porque podría haber omisiones sutiles, errores o distorsiones de contexto
- Así que al final no usé el LLM para ejecutar la conversión directamente, sino para generar código de conversión y procesarlo con ese código
LLM → código → LLM: cómo funciona en la práctica la automatización con validación iterativa
- En el primer paso, le pedí al LLM que generara la lógica central de conversión de reStructuredText a Markdown
- No una conversión superficial, sino una que aprovechara directamente el AST (árbol de sintaxis abstracta) para
- parsear reStructuredText a AST → convertirlo al AST de Markdown → renderizarlo a HTML
- De esta forma obtenía una etapa intermedia de conversión, lo que facilitaba comparar y verificar directamente el resultado
- En segundo lugar, también le pedí al LLM que escribiera un script para comparar el HTML anterior con el nuevo HTML
- Al analizar el diff del HTML después de la conversión, el diseño hacía correcciones automáticas antes de comparar diferencias menores (por ejemplo, espacios en blanco, forma de manejar notas al pie, etc.)
- Hice que el LLM tuviera en cuenta por sí mismo los tipos de errores aceptables durante el proceso de conversión
- Por ejemplo, aunque la representación HTML de las librerías de Markdown y reStructuredText fuera ligeramente distinta, el script debía filtrar solo las pérdidas o errores sustanciales
- En tercer lugar, le pedí además al LLM un script por lotes para analizar los resultados de cientos de archivos
- Con ese script fui recorriendo todos los archivos y haciendo mejoras iterativas (agentic loop) hasta que las diferencias se redujeron
- El proceso completo fue así:
- Al principio probé con unas 10 muestras y repetí hasta reducir bastante las diferencias
- Cuando el resultado fue satisfactorio, lo apliqué a todos los posts, y el procesamiento automático tomó alrededor de 30 minutos
- Lo importante no era que el LLM hubiera “logrado” la conversión por sí solo, sino que yo podía verificar y revisar todo el proceso como “código”, y por eso podía confiar en él
- Además, obtuve más confianza haciendo que otro LLM revisara y explicara el código generado y los cambios
- Tenía la seguridad de que la conversión se hacía de forma mecánicamente correcta y sin pérdida de datos, y era fácil revisar muestras o corregir cualquier detalle en cualquier momento
- Incluso en el peor de los casos, solo aparecerían errores menores de sintaxis Markdown, pero nunca se dañaría el contenido real del texto
- Otro punto importante es que con este método el costo de inferencia es constante, así que no hay una gran diferencia de carga entre procesar 15 archivos o 150
- En la etapa final de análisis, las diferencias triviales ya se omiten automáticamente, por lo que la carga de validación iterativa no crece demasiado ni siquiera en conversiones masivas
MCP Cannot Do That
- La idea central de toda esta explicación es que todo el pipeline de conversión y automatización funciona con “código”
- Entrada humana → generación de código → revisión por LLM → mejora iterativa; esta estructura se puede aplicar igual a tareas generales
- Un ejemplo sería Playwright, un caso representativo del enfoque MCP
- Es una herramienta de automatización para controlar el navegador de forma remota; leer la página, entenderla y pulsar botones implica repetir inferencia en cada paso
- Es cierto que este tipo de tarea no siempre puede reemplazarse por completo con un “enfoque de código”
- Pero si ya conoces la estructura de la página (por ejemplo, al probar tu propia app en desarrollo)
- Es mucho más rápido y confiable hacer que el LLM genere un script de Playwright en Python y luego ejecutarlo
- Con este método, una vez escrito el script, puede ejecutarse decenas o cientos de veces sin necesidad de inferencia adicional
- No hace falta interpretar la pantalla en tiempo real ni buscar cada vez la posición de los botones, y se puede ejecutar todo el flujo de automatización de una sola vez
- El enfoque MCP requiere llamadas abstractas a herramientas e inferencia en cada etapa, así que es muy difícil lograr que el LLM siempre actúe correctamente, y también es difícil depurarlo
- Por ejemplo, aunque quieras incrustar un cliente MCP dentro de un shell script para invocar servicios remotos de forma eficiente, en la práctica te das cuenta de que ese enfoque es muy ineficiente y complicado de implementar
- Al final, yo soy humano, no un cliente MCP.
- El código es fácil de ejecutar y depurar, pero las llamadas MCP son inciertas cada vez y no se pueden confiar del todo
- En la práctica, estoy aprovechando más bien las pequeñas herramientas que el LLM me va generando durante la creación de código (por ejemplo, snippets de Claude Code) como herramientas de largo plazo dentro de mi proceso de desarrollo
¿Hacia dónde lleva esta conclusión?
- Sinceramente, yo tampoco sé a dónde llevará todo esto. Pero justo ahora es un buen momento para pensar cómo mejorar más el enfoque de generación de código para el “agentic coding” intencional
- Puede sonar extraño, pero a veces MCP realmente funciona muy bien. Aun así, la estructura actual depende demasiado de la “inferencia” y se siente como un callejón sin salida para una automatización escalable y a gran escala
- Así que probablemente haya que encontrar una forma de separar y abstraer con más claridad las áreas donde MCP sí tiene ventajas y el papel del enfoque basado en generación de código
- Para eso también hará falta construir mejores sandboxes (entornos seguros de ejecución) y probar cambios en el diseño de APIs para que los agentes puedan razonar libremente con esquemas de fan out/fan in sobre las APIs
- Creo que lo deseable es una estructura donde todo lo que pueda resolverse con código se procese con código, y después de la ejecución masiva el LLM juzgue y revise el resultado completo
- Y si durante el proceso de generación de código se añade suficiente contexto para que el LLM pueda explicar en lenguaje natural a usuarios no desarrolladores qué hace el script generado, en el futuro incluso los no desarrolladores podrán aprovechar fácilmente este flujo de automatización
- En conclusión, recomiendo aprovechar con más decisión la capacidad de los LLM para generar código en lugar de depender de MCP, y experimentar nuevas posibilidades
- Si dejas que el LLM escriba código directamente, puedes automatizar mucho más de lo que imaginamos
Referencias
2 comentarios
Estoy de acuerdo, pero más que un problema de MCP, parece una optimización en la dirección de diseño de su implementación. Aunque haga la misma función, según qué MCP sea, internamente genera código y comandos para reducir trabajo innecesario. Si en vez de usar el MCP de GitHub se usa un MCP de
gh clio un MCP de terminal, se siguen usando tokens, pero mucho menos, y se puede lograr el mismo efecto; creo que esa parte se pasó por alto.Opiniones en Hacker News
En general, coincido en que esta es la dirección correcta. El uso de LLM a gran escala suele aprovecharse para llenar huecos entre dos interfaces robustas. La clave de la confiabilidad no viene del resultado del LLM, sino de que esas interfaces en realidad solo permiten ciertas configuraciones.
La salida del LLM a menudo se fuerza a convertirse en valores más deterministas, como tipos o claves primarias de BD. El valor del LLM cambia muchísimo según qué tan bien el código y las herramientas existentes modelen los datos, la lógica y el comportamiento de mi dominio.
Personalmente, últimamente siento que los LLM se parecen a una impresora 3D. Ambos ayudan a unir piezas rápido en el prototipado rápido, pero si quieres escalabilidad y robustez, al final un ingeniero o un LLM tiene que reemplazar esas uniones temporales con soportes deterministas como metal o código.
Igual que con las expectativas exageradas del pasado sobre las impresoras 3D, los LLM parecen como si pudieran reemplazar toda la realidad operativa, pero en verdad solo son realmente útiles cuando el modelado digital existente sirve como una base sólida
Hay algo que entendí usando herramientas con LLM. Si reduces el problema a una forma que el LLM pueda resolver dentro de un sandbox, usando herramientas de manera iterativa, entonces puedes resolverlo por fuerza bruta. La clave está en identificar ese tipo de problemas y definir el sandbox adecuado, las herramientas a usar y los criterios de éxito.
Este proceso también requiere bastante habilidad y experiencia, pero sigue siendo de un nivel mucho más alto que ir haciendo prueba y error a mano.
Me di cuenta de esto mientras hacía el "experimento Mandelbrot en ensamblador".
(Enlace del experimento: https://simonwillison.net/2025/Jul/…)
Idealmente, para que haya automatización real, necesitas un criterio de evaluación en forma de función continua, o al menos varios inputs y sus outputs esperados definidos de manera cuantitativa
Por ejemplo, los LLM son débiles con los genéricos de TypeScript, pero si puedes ejecutar el TSC real, entonces puede seguir intentando y validando con tests hasta acertar. Tal vez la mantenibilidad del código se resienta, pero en teoría es una estructura fascinante.
Además, Cursor puede ver los errores de TypeScript, así que si solo creas tests para utility types, el propio Cursor podría escribir los tests y resolver el problema por pura repetición brute force
Un repo recomendable: https://github.com/davidkimai/Context-Engineering/…
Todavía no lo reviso completo, pero me impresionó bastante
Estoy pensando si también se podría con un modelo local, o si bastaría con una suscripción como Claude Code Pro.
El experimento de Mandelbrot también fue divertido, pero la dificultad es algo distinta a la de una base de código comercial compleja del mundo real
No creo que esto sea un problema del MCP en sí. Con el nivel actual de la IA, una estructura con humano en el medio es mucho mejor.
Los LLM son buenos en ciertas tareas, pero a menudo quedan atrapados en mínimos locales. Por eso, cuando haces un loop de "créame un programa → revisar y dar pistas → probar" yendo y viniendo en una interfaz web, la calidad mejora claramente.
Puedes convertir 10,000 líneas de código desordenado en 400 líneas de código claro. Por ahora, esa es la realidad.
Claro, muchas empresas o desarrolladores querrán "reemplazar al programador como tal" con un LLM, pero en la práctica todavía no se puede.
El efecto real está en multiplicar varias veces la velocidad de trabajo del programador, o en permitir que una persona principiante haga trabajo productivo rápidamente con ayuda de un LLM. Pero el "agentic coding" todavía no funciona bien.
En la situación actual, lo correcto es usar el LLM como colega o asistente. La realidad es que hoy no es un "agente de IA" autónomo sin retroalimentación
Trabajo en un lenguaje compilado, con type safety y funcional, así que siempre tengo que leer personalmente el resultado; creo que en un lenguaje menos estricto me preocuparía todavía más.
Aun así, el ahorro de tiempo es enorme. En especial me gusta que ahora puedo dividir el trabajo y manejar objetivos grandes con más facilidad
De hecho, hice tareas reales con GitHub MCP y, cuando hago lo mismo con gh CLI, gh CLI usa el contexto de forma mucho más eficiente, así que es bastante más rápido.
Yo tengo un archivo CLAUDE.md en la carpeta "devops" (una colección compartida de comandos bash).
Cada vez que termino una tarea nueva, hago que Claude agregue un ejemplo, y después, ante consultas similares, Claude lo resuelve de una sola vez.
Contenido inicial compartido de CLAUDE.md:
(Se omiten los comandos concretos en el resumen)
Así que terminé con un software auto-reparable, agregando al comando instrucciones para probar y corregir la app cuando hay problemas
De todos los usos de MCP que he visto hasta ahora, el que más me impresionó fue clojure-mcp de Bruce Hauman.
Le da al LLM (a) bash, (b) un REPL persistente de Clojure, y (c) herramientas de edición estructural.
Gracias a eso, al editar código Clojure funciona de forma mucho más eficiente que un enfoque puro basado en diff de texto.
Si tienes una suite de tests decente, ver cómo repite editar archivos, recargar y probar se parece bastante al trabajo humano, y eso me sorprendió
Soporta funciones importantes como debug de código, evaluación de expresiones individuales y documentación de tipos de retorno de funciones.
Sentí que un lenguaje con un REPL potente tiene mucha ventaja en este tipo de capacidades, y ver el potencial de clojure-mcp cambió bastante mi impresión sobre la IA
El ejemplo de GitHub CLI no muestra todas las fortalezas de MCP.
Herramientas como gh CLI, con documentación tan accesible, son fáciles para que un LLM genere código, así que es normal que las aproveche mejor.
Pero la ventaja real de MCP aparece con herramientas internas o APIs de nicho que casi no tienen documentación en línea.
Puedes meter toda la documentación en el contexto, pero en casos así MCP suele ser más eficiente.
Si usas una herramienta MCP bien diseñada con los inputs correctos, reduces muchísimo la carga de que el LLM tenga que entender la API, manejar autenticación, edge cases, etc.
Tal vez GitHub no necesite MCP, pero en entornos como APIs internas o incompletas, una herramienta MCP preparada de antemano funciona con mucha más fuerza
Por ejemplo, en sonnet4 ya se siente el límite al pasar de 15 herramientas. Incluso el MCP oficial de Playwright ya consume bastante capacidad solo por el tamaño de las herramientas
Al final, la única ventaja de MCP podría ser reconfirmar que cuando una API se siente demasiado difícil, en realidad lo que pasaba es que simplemente estaba mal de complicada
Sobre el ejemplo de Playwright,
yo también esta semana hice un agente basado en Playwright MCP server, pero era lento, ineficiente en tokens y poco confiable, así que volví a llamar Playwright directamente.
El servidor MCP sirve para probar qué se puede hacer, pero en la práctica una llamada de API es más eficiente y estable.
Comparto un ejemplo y demo de mi agente personal de LinkedIn:
LinkedIn es famoso por ser una plataforma muy difícil de automatizar, así que me da curiosidad si encontraste dificultades o limitaciones al construir un agente personal para LinkedIn
La verdad siento que con solo un terminal basta.
Usé MCP todos los días durante varios meses, pero ahora solo uso un servidor MCP basado en iTerm2 (terminal).
Si hace falta, también hay un OpenAPI spec, pero en la práctica con shell commands y curl puedes hacer casi todo
La crítica de "se necesita demasiado contexto" en realidad se resuelve bastante bien si dejas bien configurados los valores por defecto del prompt inicial.
Todas las herramientas principales lo soportan, incluyendo Claude Code y Gemini CLI
Darle al LLM toda la lista de herramientas para que él mismo filtre cuál usar no es el mejor enfoque posible, pero
los LLM más recientes siguen mejorando, y en la práctica nunca me ha costado mucho que elijan la función MCP adecuada.
Los problemas de costo, velocidad y confiabilidad también
Ni siquiera tienes que gastar tu propio tiempo en la conversación
Como ejemplo reciente, el LLM procesó automáticamente muchas herramientas externas como Notion, Linear, git y logs de PR/CI de GitHub,
y yo solo tuve que hacer una revisión del PR.
El costo fue de menos de 1 dólar
De hecho, sumar herramientas puede hacer que se necesite todavía más información al inicio, y eso puede volverse una limitación seria
sino que todavía está parcialmente oculto, y la estructura de promociones gratis o baratas no va a durar mucho.
Por ejemplo, Cursor ya introdujo un plan de $200 al mes, y la calidad del servicio en los planes baratos ha empeorado.
Cuando se acaben las promociones gratuitas, volverá a su nivel real
Yo trabajo con Julia, y me beneficio de un entorno de sesiones de larga duración.
Como las funciones se compilan en la primera ejecución, hice un MCP para que Claude Code envíe código a un kernel persistente de Julia (Jupyter).
Ejecutar tests se volvió mucho más rápido, y CC aprovecha mucho mejor las funciones existentes de la base de código en vez de bash hecho a medida.
Según CCUsage, el uso de tokens también bajó casi un 50%.
No necesariamente tenía que ser MCP, pero el punto es que conectar una 'función específica' a la base de código es más fácil que escribir código personalizado cada vez para Claude