@perfonext/profiler-mcp
v0.4.0
Published
MCP server for loading and analyzing V8 and Chrome CPU profiles for GitHub Copilot and other MCP clients
Maintainers
Readme
perfonext-profiler-mcp
perfonext-profiler-mcp is an MCP server for loading and analyzing V8 and Chrome CPU profiles. It gives GitHub Copilot and other MCP clients structured performance data they can reason over instead of forcing the model to ingest multi-megabyte profile dumps.
What It Does
- loads
.cpuprofilefiles and Chrome trace exports that contain CPU profile data - identifies the hottest functions by self time, annotated with the originating npm package
- explains caller and callee relationships for a selected function
- reads actual source code for hot functions and annotates each line with V8 sample counts (v0.2.0)
- aggregates CPU self-time per npm package to find expensive third-party dependencies (v0.3.0)
- compares two profiles to surface regressions and improvements
- returns deterministic optimization suggestions for common hotspots
- summarizes loaded profiles so an MCP client can keep context tight
Tools
| Tool | Description |
|------|-------------|
| load_profile | Parse and load a .cpuprofile file or Chrome trace export from disk |
| get_hotspots | Find top functions by self-time. Each entry includes a package field identifying the npm package or (user code) |
| explain_function | Explain a function's timing, callers, and callees. Pass includeSource: true to attach annotated source lines |
| read_source_context | Read the actual source file for a hot function and annotate each line with tick counts from positionTicks |
| get_package_costs | Aggregate CPU self-time by npm package — shows which dependencies are most expensive |
| compare_profiles | Compare two profiles and highlight regressions |
| suggest_optimizations | Generate structured, multi-pattern optimization suggestions for hot functions. Detects high fan-in, recursion, dominant callers, and V8-specific patterns. Deduplicates functions split across multiple call sites |
| get_profile_summary | Summarize one profile or list all loaded profiles |
read_source_context details
// Input
{ "profileId": "<id>", "functionName": "myFn", "contextLines": 10 }
// Output (per line)
{
"lineNumber": 42,
"content": " for (let i = 0; i < items.length; i++) {",
"ticks": 18, // V8 samples that landed on this line
"isHot": true // true when ticks >= 50% of peak ticks for this function
}Only files inside the current working directory can be read. file:// URLs and absolute paths are both handled; http://, node: builtins, and paths outside the project root are rejected.
suggest_optimizations details
// Input
{ "profileId": "<id>", "limit": 5 }
// Output (per function)
{
"function": "processData",
"file": "file:///app/src/processor.js",
"line": 10,
"selfPercent": "18.2%",
"patterns": [
{
"pattern": "high-fan-in",
"detail": "Called from 6 distinct call sites (e.g. renderRow, buildTree, …)",
"suggestion": "This function is a shared hot path. Ensure it is well-optimised and monomorphic …"
},
{
"pattern": "hot-caller",
"detail": "84% of calls come from \"renderRow\"",
"suggestion": "Focus optimisation effort on \"renderRow\" rather than this function …"
}
],
"topSuggestion": "This function is a shared hot path …"
}Patterns detected (multiple can fire for the same function):
| Pattern | Trigger |
|---|---|
| gc-pressure | Function name matches GC/Scavenge/MarkCompact |
| json-serialization | JSON.parse / JSON.stringify |
| regex-cost | RegExp / exec / test calls |
| v8-deopt | Compile / Recompile / Optimize / Deoptimize |
| high-fan-in | ≥ 3 distinct parent call sites |
| recursion | Function appears in its own descendant sub-tree |
| hot-caller | One caller accounts for ≥ 80% of call-site occurrences |
| cpu-bound | Fallback when no other pattern matches |
Functions that appear at multiple call sites are automatically merged before ranking so the same logical function is only reported once.
get_package_costs details
// Input
{ "profileId": "<id>", "limit": 10 }
// Output (per package)
{
"rank": 1,
"package": "lodash",
"selfTime": "42.3ms",
"selfPercent": "14.1%",
"totalTime": "58.0ms",
"totalPercent": "19.3%",
"topFunctions": [
{ "function": "chunk", "selfTime": "28.0ms", "selfPercent": "9.3%" }
]
}Scoped packages (@babel/core, @next/env, etc.) are handled correctly. User code and native builtins (no node_modules in the path) are excluded.
Install
Run directly with npx:
npx -y @perfonext/profiler-mcpOr install globally:
npm install -g @perfonext/profiler-mcpThe executable command remains perfonext-profiler-mcp after installation.
MCP Configuration
Add this server to VS Code settings.json:
{
"mcp": {
"servers": {
"perfonext-profiler": {
"command": "npx",
"args": ["-y", "@perfonext/profiler-mcp"]
}
}
}
}Example Copilot Prompts
- "Load the CPU profile at
./profile.cpuprofileand show me the top hotspots." - "Which npm packages are consuming the most CPU in this profile?"
- "Explain why
processDatais expensive in the loaded profile." - "Show me the actual source lines for
processDataand mark which lines are hottest." - "Explain
transformResultand include the annotated source code." - "Compare my baseline and current CPU profiles and tell me what got slower."
- "Suggest optimizations for the top three hotspots."
Development
npm install
npm run build
npm testThe repository already includes sample fixtures under tests/fixtures/ for local validation.
Generating a CPU Profile
Node.js:
node --cpu-prof your-script.jsChrome DevTools:
- Open DevTools and go to the Performance tab.
- Record the scenario you want to inspect.
- Stop recording and save the result as a
.cpuprofileexport.
License
MIT
