Skip to main content
Glama

check_performance

Measure page performance by checking load time, resource count, and large resources using the browser's Performance API. Call after navigating to a page.

Instructions

Measure page performance: load time, resource count, large resources.

Uses the browser's Performance API. Best called right after navigating to a page.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The check_performance() tool handler. Measures page performance using the browser's Performance API, reports load time, TTFB, DOM interactive, total requests/size, large resources (>500KB), and runs the detector to flag performance bugs.
    @mcp.tool()
    async def check_performance() -> str:
        """Measure page performance: load time, resource count, large resources.
    
        Uses the browser's Performance API. Best called right after navigating to a page.
        """
        s = _require_session()
        current_url = s.browser._page.url if s.browser._page else ""
        perf_data = await s.browser.get_performance()
        new_bugs = s.detector.process_performance(perf_data, current_url, s.steps)
    
        if new_bugs:
            ss_path = await _auto_screenshot(s, "performance", f"Perf issues on {current_url}")
            for bug in new_bugs:
                bug.screenshot_path = ss_path
        s.bugs.extend(new_bugs)
    
        nav = perf_data.get("navigation", {})
        summary = perf_data.get("summary", {})
        lines = [f"Performance for {current_url}"]
        if nav:
            lines.append(f"  Load time: {nav.get('loadTime', 0)/1000:.2f}s")
            lines.append(f"  TTFB: {nav.get('ttfb', 0)/1000:.2f}s")
            lines.append(f"  DOM interactive: {nav.get('domInteractive', 0)/1000:.2f}s")
        lines.append(f"  Total requests: {summary.get('totalRequests', '?')}")
        lines.append(f"  Total size: {summary.get('totalSize', 0)/1024:.0f} KB")
        large = perf_data.get("resources", [])
        if large:
            lines.append(f"  Large resources (>500KB):")
            for r in large:
                lines.append(f"    {r['size']/1024:.0f}KB — {r['name'][:80]}")
        lines.append(f"\nTotal bugs in session: {len(s.bugs)}")
        return "\n".join(lines)
  • JavaScript snippet (_EXTRACT_PERFORMANCE_JS) evaluated in the browser to extract navigation timing, resource sizes, and total request count using the Performance API.
    _EXTRACT_PERFORMANCE_JS = """
    () => {
        const result = { navigation: null, resources: [], summary: {} };
        try {
            const nav = performance.getEntriesByType('navigation');
            if (nav.length > 0) {
                const n = nav[0];
                result.navigation = {
                    loadTime: n.loadEventEnd - n.startTime,
                    domContentLoaded: n.domContentLoadedEventEnd - n.startTime,
                    ttfb: n.responseStart - n.startTime,
                    domInteractive: n.domInteractive - n.startTime
                };
            }
        } catch(e) {}
        try {
            const resources = performance.getEntriesByType('resource');
            result.summary.totalRequests = resources.length;
            result.summary.totalSize = 0;
            resources.forEach(r => {
                const sz = r.transferSize || 0;
                result.summary.totalSize += sz;
                if (sz > 500 * 1024) result.resources.push({name:r.name.slice(0,200),type:r.initiatorType,size:sz,duration:Math.round(r.duration)});
            });
        } catch(e) {}
        return result;
    }
    """
  • BrowserDriver.get_performance() — evaluates the _EXTRACT_PERFORMANCE_JS in the page context to get performance metrics.
    async def get_performance(self) -> Dict:
        """Extract performance metrics from the current page."""
        try:
            return await self._page.evaluate(_EXTRACT_PERFORMANCE_JS)
        except Exception:
            return {}
  • Detector.process_performance() — analyzes performance data and flags bugs: slow page loads (>3s), excessive requests (>50), and large resources (>500KB).
    def process_performance(
        self, perf_data: Dict, url: str, steps: List[str]
    ) -> List[Bug]:
        """Flag slow page loads, large resources, excessive requests."""
        bugs = []
        nav = perf_data.get("navigation")
        summary = perf_data.get("summary", {})
    
        if nav:
            load_time = nav.get("loadTime", 0)
            if load_time > 3000:
                key = f"perf:slow:{url}"
                if key not in self._seen:
                    self._seen.add(key)
                    bugs.append(Bug(
                        type=BugType.PERFORMANCE,
                        severity=Severity.MEDIUM if load_time < 5000 else Severity.HIGH,
                        title=f"Slow page load: {load_time/1000:.1f}s",
                        description=f"Page took {load_time/1000:.1f}s to load. TTFB: {nav.get('ttfb',0)/1000:.1f}s",
                        url=url, steps_to_reproduce=list(steps),
                    ))
    
        if summary.get("totalRequests", 0) > 50:
            key = "perf:too_many_requests"
            self._page_counts[key] = self._page_counts.get(key, 0) + 1
            if key not in self._seen:
                self._seen.add(key)
                bugs.append(Bug(
                    type=BugType.PERFORMANCE, severity=Severity.LOW,
                    title=f"Too many network requests ({summary['totalRequests']} on this page)",
                    description=f"Pages are making >50 network requests. First found on {url}",
                    url=url, steps_to_reproduce=list(steps),
                ))
    
        for res in perf_data.get("resources", []):
            size_mb = res.get("size", 0) / (1024 * 1024)
            key = f"perf:large:{res['name'][:100]}"
            if key not in self._seen:
                self._seen.add(key)
                bugs.append(Bug(
                    type=BugType.PERFORMANCE, severity=Severity.LOW,
                    title=f"Large resource ({size_mb:.1f}MB): {res['name'][:60]}",
                    description=f"Resource {res['name']} is {size_mb:.1f}MB",
                    url=url, steps_to_reproduce=list(steps),
                ))
    
        return bugs
  • Registration via @mcp.tool() decorator on check_performance() function. The tool is described in the mcp instructions at line 113 as an on-demand check.
    @mcp.tool()
    async def check_performance() -> str:
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must fully disclose behavior. It mentions using the browser's Performance API, indicating a read-only measurement. Lacks details on potential side effects or resource overhead, but overall acceptable for a simple measurement tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, front-loaded with the main purpose. Every sentence adds relevant information with no waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and existence of output schema, the description covers key aspects: what is measured and when to call. Could elaborate on output format or thresholds, but output schema likely fills that gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so description adds value by explaining what the tool measures and the best timing. Schema coverage is trivially 100%, description compensates adequately.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it measures page performance: load time, resource count, large resources. It uses a specific verb ('Measure') and resource ('page performance'), distinguishing it from sibling tools like check_links or get_page_state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly advises 'Best called right after navigating to a page', which provides clear context for when to use. Does not list exclusions or alternatives, but the advice is helpful for proper usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/chriswu727/argus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server