v8-cpu-profile-decoder-mcp
Decodifica perfiles de CPU de V8 en resúmenes de flame graph y hotspots para agentes de IA
Documentación
v8-cpu-profile-decoder-mcp 🐸⚡
Un servidor MCP que decodifica perfiles de CPU de V8 en resúmenes de cuellos de botella eficientes en tokens para agentes de IA.
Tu aplicación Node.js es lenta. Ejecutaste --cpu-prof. Ahora tienes un archivo .cpuprofile de 20MB — y tu agente de IA es completamente ciego a él.
🤔 El Problema
Los perfiles de CPU de V8 son masivos. Un .cpuprofile típico de una aplicación Node.js en producción es de 5 a 50MB de JSON crudo — millones de líneas que mapean direcciones de memoria, conteos de ticks y secuencias de ejecución en microsegundos. Se ve así:
{
"nodes": [
{ "id": 1482, "callFrame": { "functionName": "processRequest", "url": "file:///app/dist/server.js", "lineNumber": 847 }, "hitCount": 3241, "children": [1483, 1490] },
...
],
"samples": [1482, 1483, 1482, 1490, 1482, ...],
"timeDeltas": [120, 98, 115, 102, ...]
}
Un agente de IA que intente leer este archivo colapsa instantáneamente su ventana de contexto y falla. Incluso si pudiera leerlo, no puede ejecutar los algoritmos de agregación necesarios para calcular los tiempos de CPU inclusivos/exclusivos a través del árbol de llamadas.
Entonces, cuando le preguntas a tu agente:
- 🙈 "¿Qué función está consumiendo más CPU?"
- 🙈 "¿Qué está llamando a mi consulta de base de datos lenta?"
- 🙈 "¿De qué archivo TypeScript proviene realmente el cuello de botella?"
...está adivinando. No tiene acceso a los datos de perfilado.
v8-cpu-profile-decoder-mcp soluciona eso. Decodifica el perfil localmente y entrega al agente un resumen semántico de 10 líneas en lugar de un archivo de 50MB.
🛠️ Herramientas
extract_hottest_functions
Analiza el .cpuprofile y devuelve las N funciones principales clasificadas por tiempo de CPU exclusivo (tiempo propio).
Filtra los internos de V8 y los componentes integrados de Node.js — solo código de usuario.
{
"profile_path": "/app/profiles/CPU.20260516.cpuprofile",
"top_n": 5,
"min_self_percent": 1.0
}
[
{
"rank": 1,
"functionName": "hashPassword",
"url": "file:///app/dist/auth/crypto.js",
"lineNumber": 42,
"selfTimeMs": 1842.5,
"totalTimeMs": 1842.5,
"selfPercent": 61.32,
"totalPercent": 61.32,
"hitCount": 3241
},
{
"rank": 2,
"functionName": "parseJsonBody",
"url": "file:///app/dist/middleware/body.js",
"lineNumber": 18,
"selfTimeMs": 412.1,
"totalTimeMs": 412.1,
"selfPercent": 13.71,
"totalPercent": 13.71,
"hitCount": 724
}
]
analyze_call_tree_path
Encuentra todos los llamadores de una función específica y muestra con qué frecuencia cada uno la invocó. Acepta coincidencia parcial de nombres de funciones sin distinción de mayúsculas/minúsculas.
{
"profile_path": "/app/profiles/CPU.20260516.cpuprofile",
"function_name": "hashPassword",
"top_callers": 3
}
{
"targetFunction": "hashPassword",
"matchedNodes": 2,
"totalSelfTimeMs": 1842.5,
"totalPercent": 61.32,
"callers": [
{
"functionName": "loginHandler",
"url": "file:///app/dist/routes/auth.js",
"lineNumber": 94,
"callCount": 2180,
"selfTimeMs": 240.1
},
{
"functionName": "validateSession",
"url": "file:///app/dist/middleware/auth.js",
"lineNumber": 31,
"callCount": 1061,
"selfTimeMs": 116.8
}
]
}
correlate_source_code
Mapea los cuellos de botella de JS compilado de vuelta a sus ubicaciones originales en código fuente TypeScript usando archivos .js.map.
Se degrada elegantemente a ubicaciones de JS compilado si no se encuentra un mapa de origen.
{
"profile_path": "/app/profiles/CPU.20260516.cpuprofile",
"top_n": 5
}
{
"resolved": [
{
"rank": 1,
"generatedUrl": "file:///app/dist/auth/crypto.js",
"generatedLine": 42,
"source": {
"originalFile": "src/auth/crypto.ts",
"originalLine": 38,
"originalColumn": 2,
"originalFunction": "hashPassword"
},
"selfTimeMs": 1842.5,
"selfPercent": 61.32
}
],
"sourcemapErrors": []
}
analyze_gc_pressure
Informa la sobrecarga de recolección de basura como porcentaje de la duración del perfilado, desglosada por tipo de GC. Señala cuando el GC excede un umbral configurable y proporciona una recomendación específica.
{
"profile_path": "/app/profiles/CPU.cpuprofile",
"threshold_percent": 10
}
{
"gc_ticks": 184,
"total_ticks": 1240,
"gc_percentage": 14.84,
"gc_type_breakdown": {
"scavenger": 122,
"mark_sweep": 0,
"mark_compact": 0,
"incremental": 62,
"generic": 0
},
"exceeds_threshold": true,
"threshold_percent": 10,
"verdict": "GC consumed 14.84% of CPU — exceeds the 10% threshold. Dominated by Scavenger (short-lived object pressure). Consider object pooling, reusing buffers, or reducing closure captures."
}
diff_profiles
Compara dos archivos .cpuprofile (antes/después de una optimización) y devuelve los deltas de tiempo de CPU por función,
normalizados contra la duración total de cada perfil. Los marcos se emparejan por coordenadas de marco de llamada, no
por IDs de nodo transitorios, por lo que la alineación es estable entre sesiones de perfilado.
{
"before_profile_path": "/app/profiles/before.cpuprofile",
"after_profile_path": "/app/profiles/after.cpuprofile",
"top_n": 5
}
{
"before_duration_ms": 5000,
"after_duration_ms": 4800,
"total_execution_delta_ms": -200,
"total_execution_delta_percent": -4,
"top_improvements": [
{
"function_name": "hashPassword",
"url": "file:///app/dist/auth/crypto.js",
"line_number": 42,
"before_ms": 1842.5,
"after_ms": 620.1,
"absolute_diff_ms": -1222.4,
"relative_diff_percent": -66.34
}
],
"top_regressions": [],
"only_in_before": [],
"only_in_after": []
}
analyze_async_bottlenecks
Detecta la sobrecarga del bucle de eventos identificando marcos internos de V8 que representan maquinaria asíncrona —
procesamiento de cola de microtareas, saturación de nextTick y callbacks de temporizadores/inmediatos.
{
"profile_path": "/app/profiles/CPU.cpuprofile",
"threshold_percent": 10
}
{
"total_ticks": 1240,
"async_ticks": 186,
"event_loop_overhead_ms": 372,
"event_loop_overhead_percent": 15.0,
"dominant_async_patterns": [
{ "pattern": "promise_chains", "ticks": 142, "percent": 11.45 },
{ "pattern": "nexttick_saturation", "ticks": 44, "percent": 3.55 }
],
"verdict": "Event-loop overhead is 15.0% of CPU — exceeds the 10% threshold. Promise chain overhead is visible in the profile. Consider batching microtasks, using Promise.all() to parallelise I/O, or offloading CPU-bound continuations to worker threads."
}
🚀 Instalación
npx v8-cpu-profile-decoder-mcp
O instalar globalmente:
npm install -g v8-cpu-profile-decoder-mcp
Generar un perfil de CPU en Node.js
# Single run
node --cpu-prof your-script.js
# With custom output dir
node --cpu-prof --cpu-prof-dir ./profiles your-script.js
O programáticamente a través de Chrome DevTools → pestaña Performance → Record.
Configuración de Claude Desktop
{
"mcpServers": {
"v8-cpu-profile-decoder-mcp": {
"command": "npx",
"args": ["-y", "v8-cpu-profile-decoder-mcp"]
}
}
}
💡 Ejemplos de Prompts para Agentes
"Aquí está mi perfil de CPU en
/app/profiles/CPU.cpuprofile— ¿qué función está consumiendo más CPU?"
"Encuentra qué está llamando a
processRequesten este perfil y con qué frecuencia"
"Mapea las 10 funciones más calientes de vuelta a sus archivos TypeScript originales"
"Mi API de Node.js es lenta bajo carga — el perfil está en
/tmp/CPU.cpuprofile, encuentra el cuello de botella"
"¿Es el GC el cuello de botella? Revisa el perfil en
/tmp/CPU.cpuprofiley dime qué tipo de asignación lo está causando"
"Compara estos dos perfiles antes y después de mi optimización — ¿qué funciones mejoraron y cuáles empeoraron?"
"¿Está esta aplicación gastando demasiada CPU en sobrecarga asíncrona y maquinaria del bucle de eventos?"
🔗 Proyectos Relacionados
- playwright-trace-decoder-mcp — decodifica trazas de Playwright para análisis de causa raíz de fallos en CI
- playwright-network-chaos-mcp — simula fallos de red y latencia en sesiones de navegador
- flakiness-knowledge-graph-mcp — grafo de conocimiento de patrones de pruebas inestables
- ast-impact-mapper-mcp — encuentra pruebas afectadas por cambios de código mediante AST de TypeScript
- playwright-spatial-layout-mcp — conciencia espacial geométrica de diseños web
📄 Licencia
MIT © vola-trebla