- 1 - oxidegate-lens, cuánto pesa cada servidor MCP en cada petición.
- 2 - Qué es, y sobre todo qué no es.
- 3 - Instalación y arranque.
- 4 - La tabla.
- 5 - Tres bloques que nunca se mezclan.
- 6 - Por qué ¿SE PUEDE QUITAR? nunca mira si las herramientas están diferidas.
- 7 - Y tampoco mira quién dice ser el cliente.
- 8 - Cuando faltan servidores, lo dice y se para.
- 9 - Cuatro casos raros que el reporte distingue.
- 10 - La válvula.
- 11 - Y no se aplica hasta que lo apruebes.
- 12 - Degradar sin romperse.
- 13 - Por qué existe esa suite de tests.
- 14 - Cuándo usar esta lente.
oxidegate-lens, cuánto pesa cada servidor MCP en cada petición.
En el capítulo de las palancas vimos que desconectar tres servidores MCP que no usábamos ahorraba 55.399 bytes por petición. Fue el ahorro más grande del catálogo.
La pregunta obvia es cómo averiguas eso sin ponerte a leer JSON crudo del endpoint de peticiones. Y para eso está oxidegate-lens.
Qué es, y sobre todo qué no es.
oxidegate-lens muestra cuántos bytes pesa cada servidor MCP en cada petición. Lee esos datos de OxideGate y nunca mide nada por su cuenta.
Esa segunda parte es toda la arquitectura, y merece que nos paremos en ella:
OxideGate (proxy en Rust) oxidegate-lens
ve el tráfico real GET solo LEE y MUESTRA
entre cliente y proveedor ───────▶ oxidegate-savings → la tabla
mide bytes por servidor /stats
/requests
El dato solo fluye del proxy hacia las lentes, nunca al revés. Las lentes interpretan, agrupan y presentan. Ninguna mide.
¿Por qué tanta insistencia? Porque es lo que hace que un desacuerdo entre dos vistas sea siempre un bug de presentación, y nunca dos mediciones que compiten. Si la lente midiera por su cuenta, tendrías dos números y ninguna forma de saber cuál creer.
Y hay una razón de fondo todavía más simple: un plugin dentro del agente vería la intención del agente, no el tráfico real. El proxy ve los bytes exactos en la red. Duplicar la medición desde dentro perdería precisión sin ganar absolutamente nada.
Instalación y arranque.
brew install pichu2707/tap/oxidegate-lens
Instala el comando oxidegate-savings. Cero dependencias externas: solo necesita Node 24 o superior, porque usa fetch y AbortSignal.timeout nativos.
Y necesita a OxideGate corriendo, que es quien mide.
El camino completo son cuatro pasos:
| Paso | Comando | |
|---|---|---|
| 1 | Enciende OxideGate | OXIDEGATE_PORT=8899 oxidegate |
| 2 | Apunta tu agente al proxy | export ANTHROPIC_BASE_URL=http://127.0.0.1:8899 |
| 3 | Úsalo un rato y pide el reporte | oxidegate-savings |
| 4 | Lee la tabla | ↓ |
Dos notas sobre los pasos.
El paso 3 no es opcional. OxideGate solo puede medir lo que ha visto pasar. Si pides el reporte sin haber hecho ninguna petición a través del proxy, la tabla sale vacía. Y eso no es un fallo: es que no hay nada que medir todavía.
Al reporte no hace falta decirle el puerto. Lo busca solo: mira la variable de la lente, luego la del proxy, luego lo que el propio OxideGate declara en su log, y por último los puertos habituales. En todos los casos comprueba que quien contesta es OxideGate de verdad antes de creerle — que algo responda en un puerto no lo convierte en el proxy. Un OXIDEGATE_PORT viejo apuntando a otro servicio hace que la lente siga buscando y te avise de que lo ha ignorado, en lugar de escribirte un reporte a partir de las respuestas de un desconocido.
La tabla.
Esto es lo que sale. Caso real, Claude Code hablando con Anthropic a través del proxy, con los cuatro servidores MCP disponibles llegando los cuatro:
SERVIDOR KIND TOOLS BYTES % TOOLS ¿SE PUEDE QUITAR?
claude_ai_Google_Drive mcp 1 161 B 25.2% sí, desconectándolo
(native) native 2 158 B 24.7% no, sólo con --tools
claude_ai_Google_Calendar mcp 1 111 B 17.4% sí, desconectándolo
plugin_engram_engram mcp 1 111 B 17.4% sí, desconectándolo
claude_ai_Gmail mcp 1 91 B 14.2% sí, desconectándolo
overhead (corchetes/comas) - - 7 B -
ahorro por petición desconectando los 4 servidores MCP: 474 B (74.2% de los tools)
Columna a columna:
| Columna | Qué es |
|---|---|
SERVIDOR | Quién aporta esas herramientas. (native) es el propio agente |
KIND | mcp = servidor conectado; native = superficie del agente |
TOOLS | Cuántas herramientas declara |
BYTES | Cuánto pesan sus esquemas en el cuerpo de cada petición |
% TOOLS | Qué porción del total representa |
¿SE PUEDE QUITAR? | mcp → siempre sí. native → solo con --tools |
Y hasta el overhead de corchetes y comas está contado, porque serializar un array también cuesta bytes y omitirlo sería redondear a favor.
Tres bloques que nunca se mezclan.
Aquí es donde este reporte se separa de cualquier dashboard al uso. La salida son tres bloques independientes, nunca fundidos en un solo veredicto:
1. La tabla. Bytes. Cada servidor mcp que aparece ahí ya está en el cuerpo: sus bytes viajaron, punto.
2. Disponibles frente a llegados. Una resta, sin causa. Cuántos servidores MCP tienes disponibles en tu máquina contra cuántos llegaron al cable en esta petición.
3. Tokens de contexto. Otra moneda, aparte. Si el esquema, además de viajar en el cuerpo, ocupa también el contexto del modelo por adelantado. Nunca cambia un byte de la tabla.
La tentación de fundir los tres en un “ahorro estimado total” es enorme. Quedaría mejor. Sería un número más vendible. Y sería mentira, porque son tres unidades distintas.
Por qué ¿SE PUEDE QUITAR? nunca mira si las herramientas están diferidas.
Este es el error que este reporte existe para no cometer, y ya lo adelantamos en el capítulo de las palancas.
Es tentador pensar que un servidor cuyas herramientas están marcadas como diferidas “ya pesa poco” en el cuerpo. No es así.
El marcado de carga diferida es un flag sobre una definición que el proveedor sigue necesitando completa en el cuerpo. La búsqueda de herramientas corre en el servidor del proveedor y busca sobre lo declarado en la petición: si la definición no está ahí, no hay nada que buscar.
Diferido ahorra contexto. Nunca ahorra cable.
Por eso toda fila mcp de la tabla es siempre “sí, desconectándolo”, sin excepción: si tiene fila, llegó al cable completa. Una fila con todas sus herramientas diferidas pesa, en bytes, exactamente lo mismo que una sin diferir ninguna.
Y tampoco mira quién dice ser el cliente.
Una versión anterior del reporte usaba la cabecera de agente de usuario para decidir si matizar una fila.
Siete rondas de revisión adversarial encontraron, cada una, un caso real donde esa inferencia se equivocaba.
La corrección no fue escribir una regla mejor. Fue dejar de inferir. Esa cabecera es contenido que manda el propio cliente, sin forma de verificarlo desde el servidor: cualquier proceso puede decir que es Claude Code sin serlo. Hoy solo se imprime, informativa, en la línea de origen. Nunca decide nada.
Cuando faltan servidores, lo dice y se para.
Este es el caso donde algunos de los servidores disponibles no llegaron al cable:
Tienes 4 servidores MCP disponibles. En esta petición llegaron 1.
Los otros 3 (claude_ai_Google_Drive, claude_ai_Google_Calendar, plugin_engram_engram)
no viajan ahora mismo.
Puede ser que tu harness los esté reteniendo, o que todavía no hayan conectado —
ninguna de las dos causas se puede confirmar desde esta sola petición.
Nombra los que faltan y ahí se detiene. No elige entre “tu harness los retiene” y “todavía no conectaron”, porque las dos son causas reales y una sola petición no alcanza para distinguirlas.
Eso no es prudencia decorativa: está medido. En un caso real, un conector remoto estuvo ausente en la petición número 1 y presente, sin marcar, en la número 3, siete segundos después, sin que nadie hiciera nada.
Cuatro casos raros que el reporte distingue.
Y aquí es donde nueve rondas de revisión adversarial dejaron su huella. Cada uno de estos casos fue un defecto real que daba una conclusión falsa.
No se pudo leer tu configuración. Si el comando que lista tus servidores no está disponible, falló o devolvió algo con otro formato, el reporte lo dice explícitamente. Nunca se muestra igual que “0 servidores disponibles”. Confundir esas dos cosas fue exactamente el defecto que este reporte existe para no repetir.
Dos nombres que colisionan al normalizar. La función que limpia nombres de servidor no es inyectiva: "foo bar" y "foo_bar" acaban los dos en foo_bar. Cuando eso pasa entre dos servidores conectados, no hay forma de saber a cuál corresponde una fila. El reporte nombra la colisión y saca esos nombres del conteo, en lugar de fusionarlos en silencio. Antes de arreglarlo, un servidor entero desaparecía sin aviso.
El bucket (others). El proxy trackea hasta 32 servidores distintos de forma individual por petición; el resto se sigue contando pero se funde en un único cubo sin nombre. Si un servidor disponible no tiene fila propia y la petición trae ese cubo, el reporte no dice “no viajó”: dice que no se puede confirmar si está dentro. Medido en vivo con 33 servidores, donde el trigésimo tercero sí viajaba y una versión anterior del reporte aseguraba que no.
El propio medidor contamina la medida. En tráfico hacia Anthropic el reporte siempre imprime un aviso: algunos harnesses difieren sus esquemas MCP por defecto, pero ese diferido se cae a carga completa detrás de un base URL que no sea del proveedor. Y OxideGate es exactamente eso. Parte de los bytes de la tabla podrían ser un artefacto de tener el proxy en medio.
El reporte no lo decide por ti. Te dice cómo comprobarlo: repite la misma petición apuntando directo al proveedor y compara.
La válvula.
Además del reporte, hay un segundo comando, oxidegate-mcp, que es un selector interactivo para decidir qué servidores siguen conectados entre reinicios.
Un proyecto puede declarar su propia política:
{
"disableByDefault": true,
"protectedMcpServers": ["engram"]
}
Ese archivo reemplaza a la configuración global en lo que declara, no se fusiona. Callar sobre una clave no es declararla vacía: un proyecto que solo toca el interruptor no borra la lista de nadie.
La precedencia completa, de más fuerte a más débil:
variables de entorno > proyecto (si está aprobado) > global > por defecto
Y no se aplica hasta que lo apruebes.
Este detalle me parece el más importante de toda la herramienta.
Un archivo de configuración dentro de un repositorio que clonaste es código ajeno. Puede desconectar servidores MCP que querías conservar o, peor porque es silencioso, marcar como protegido uno que querías apagar.
Así que no se aplica solo:
oxidegate-mcp --approve
Te enseña el archivo antes de aprobarlo, porque aprobar a ciegas no es consentir.
Y la aprobación es del contenido, no de la ruta — el modelo de direnv. Si el archivo cambia, por una edición tuya o por un git pull, vuelve a pedirse. Aprobar una ruta para siempre dejaría que el repositorio cambiara el archivo bajo tus pies sin que nadie se enterase.
Degradar sin romperse.
Compatibilidad entre versiones:
| oxidegate-lens | OxideGate | Qué pasa |
|---|---|---|
0.2.x | >= 0.2.0 | Todo, incluido el bloque de tokens de contexto |
0.2.x | < 0.2.0 | No se rompe. Los campos nuevos no existen, así que se dan por DESCONOCIDOS y lo dice |
Un dato ausente nunca se muestra como un cero. Y esa degradación no es una promesa en un README: está cubierta por tests. Si alguien la rompe, la suite se pone roja.
Por qué existe esa suite de tests.
Cierro con esto porque es la parte que más dice sobre cómo se construyó la herramienta.
Este reporte pasó por nueve rondas de revisión adversarial. Se encontraron nueve defectos. Los nueve los encontró una persona o un agente leyendo y midiendo la salida a mano. Ninguno lo encontró una máquina, porque hasta ese momento no había ninguna mirando.
Los invariantes que sobrevivieron están escritos en comentarios de código. Pero un comentario no detiene a nadie: la siguiente persona que toque ese archivo puede romper cualquiera de ellos y nada se lo va a decir.
Así que cada uno de los nueve defectos se convirtió en un test que falla si vuelve a aparecer. No es cobertura por cobertura: es protección de regresión para una lista específica, conocida y cara de bugs.
La suite completa corre en menos de dos segundos y es hermética: levanta su propio servidor HTTP en un puerto efímero para simular al proxy, y un comando falso en un PATH propio para simular la lectura de configuración. Nunca toca un proxy real ni la configuración real de la máquina.
Cuándo usar esta lente.
- Antes de recortar servidores MCP, para saber cuál pesa y cuánto, en lugar de desconectar por intuición.
- Después de instalar un plugin nuevo, para ver qué peaje añadió a cada petición.
- Cuando la tabla de OxideGate te dice que las herramientas son el 70% del cuerpo y quieres saber de quién es ese 70%.
- Al entrar en un proyecto ajeno, para ver qué trae conectado antes de aceptar su configuración.
Y si la tabla sale vacía, es por una de tres razones, en este orden: el proxy está apagado, el puerto no es el que crees, o todavía no ha pasado ninguna petición con MCP por él.
No hay una cuarta.
En el siguiente capítulo vamos a la tercera herramienta del ecosistema, mcp-savings, que ataca el mismo problema desde el lado contrario. Y que acabó enseñándonos por qué ese lado era el equivocado.
¿Listo para hacer crecer tu negocio?
Analicemos tu proyecto y definamos la estrategia perfecta para alcanzar tus objetivos
Solicitar consultoría gratuita