pagespeed-insights-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| PAGESPEED_API_KEY | No | Overrides the stored API key for anyone who would rather keep it in their own secret manager. | |
| PAGESPEED_CONFIG_DIR | No | Moves the configuration directory (settings.json) wherever you like. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| analyse_pageA | Use to measure a page in the lab and find what to fix (scores with their spread, failing audits ranked by what fixing them is worth, real-user data beside them, and a page to send on); for real-user data alone use get_field_data, which is fast, and for "did that change help" use compare_to_baseline. include picks the parts, "scores", "issues", "field_data" and "html", default all four. ONE MEASUREMENT SERVES EVERY PART, so asking for more costs no extra API calls, while asking in separate calls measures again. SLOW, several minutes. It reports the MEDIAN of several DISTINCT analyses with the min-max spread, so the number comes with its uncertainty. A single Lighthouse run is noise, Total Blocking Time swings threefold between runs on an unchanged page, so runs=1 is fast but its score is not a reliable figure. Google re-analyses a URL only about once a minute and replays the cached result in between, so this keeps asking until it has genuinely different analyses rather than the same one several times. That means runs=5 takes roughly 150 seconds and asking harder will NOT speed it up. Reports fewer analyses honestly if time runs out. Anything that will not fit inside one tool call returns a JOB ID instead and keeps working: collect it with get_job_result, polling about every 15 seconds. Only runs=1 on a single URL with include ["scores"] answers immediately, and that is the noisy single run described above. ISSUES are what is FAILING on the page, from Google's own audit findings and remediation text. Only a fault that failed in EVERY distinct analysis is reported, because audits are as noisy as scores and a one-off failure is the instrument moving rather than a fact about the page. Estimated savings carry their median and spread for the same reason. Ranked by what actually moves the score: the performance score is five metrics and every other performance audit weighs zero, so a big estimated saving on an unweighted diagnostic is not the first thing to fix. Savings do NOT add up, they overlap, so the order is meaningful and the sum is not. FIELD_DATA is real-user data if Google has any. HTML is a complete self-contained page carrying all of it, made to be saved as a file the user can open or forward, because several of the largest findings are usually hosting or third-party decisions that the person running the check cannot fix alone. Set html false if they only want the answer in conversation. TO SAVE IT AS A FILE, pass directory, a folder on the user's own machine that the report is written into. The server writes into whichever existing folder directory names and does not check where that path came from. The folder is checked BEFORE the measurement starts, which takes minutes, so a folder that does not exist or cannot be written to is refused at once. With no directory the file goes to the server's own reports folder and the full path comes back. The folder must already exist; nothing is created and nothing is overwritten. Saved files keep their embedded fonts and are about 150KB; the copy returned in conversation drops them to stay small, so a saved file is the fuller of the two. Returns a readable report and the same figures as JSON. |
| get_field_dataA | Use for what real Chrome users actually experienced, with no lab measurement, so it answers in seconds rather than minutes; for lab scores and what to fix use analyse_page, and for which phase owns a slow LCP use explain_lcp. From the Chrome UX Report, the only evidence here about real visitors and the only thing Google ranks on. Set history for the weekly p75 time series, which shows whether a site has been getting slower for real people over months. Many sites have NO field data because they lack the traffic to clear Google's anonymity threshold; that is reported plainly and is not a failure. |
| explain_lcpA | Use when Largest Contentful Paint is the problem, to find which part of the load owns it; for the LCP figure alone use get_field_data, and for lab scores and what to fix use analyse_page. Breaks a slow LCP into the four phases it is made of: server response, then the delay before the browser starts fetching the largest image, then the download, then the delay before it is painted. FAST, one Chrome UX Report call, no Lighthouse runs and no noise to average away. TWO THINGS NOT TO GET WRONG, both reported in the output: the phases are each a separate 75th percentile so they do NOT sum to the LCP (measured gaps range from -421ms to +2616ms across twelve real origins, in both directions) and the shares are of the phase total, never of the LCP; and they are measured ONLY over visits whose largest element was an image, which on some sites is a small minority, so the output gives the image share alongside them. Needs an API key and real-user data, which many small sites do not have. |
| compare_to_baselineA | Use to answer "did that change actually help"; for a one-off measurement with nothing to compare against use analyse_page. Measures now and compares against a saved baseline for the same URL and strategy. THE FIRST CALL ON A URL RECORDS THE BASELINE and compares nothing, which is the correct answer before anything has changed, and a call after the change compares against it. A verdict is only given where the two min-max ranges do NOT overlap: on an unchanged page the performance score has been measured running 27 to 37 and Total Blocking Time 824ms to 3.05s, so comparing medians alone reports improvements that are just the instrument moving. Where a change is real it reports both the difference in medians and the smaller figure the ranges actually guarantee, and the guaranteed one is the figure the measurement supports. Also reports which findings stopped and started failing, and flags a Lighthouse version change, which moves scores without the page moving. Does NOT compare field data, which is a 28-day window and cannot show a change made this week. SLOW, several minutes: it returns a JOB ID and you collect the verdict with get_job_result. |
| get_job_resultA | Use to collect a measurement that analyse_page or compare_to_baseline handed back as a job id, calling it about every 15 seconds until it reports done. Anything longer than about a minute cannot be answered inside one tool call (clients enforce a hard wall-clock limit and progress notifications do not extend it), so those tools return a job id and keep working. When done it returns exactly what the tool would have returned. ALWAYS answers immediately. Omit job_id for the most recent job. Starting the same measurement again while one is running does not make it arrive any sooner, because the wait is Google re-analysing the URL about once a minute. |
| check_setupA | Use first when anything looks wrong, to tell a configuration problem apart from a slow or failing page before committing to a full check. Reports what is configured and what actually works right now (key present, PageSpeed reachable, Chrome UX Report permitted) without disclosing the key. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 6 tools
The tools are mostly distinct: lab measurement, CrUX field data, LCP phase diagnosis, baseline comparison, setup diagnostics, and async result retrieval each have a clear role. Some overlap remains because analyse_page can return field_data and explain_lcp also uses CrUX/LCP data, but the descriptions explicitly route between them.
All tool names follow a consistent snake_case verb_object pattern: get_job_result, check_setup, get_field_data, analyse_page, explain_lcp, compare_to_baseline. There is no mixed casing or conflicting verb style.
Six tools is well scoped for a PageSpeed Insights server, covering setup, lab analysis, field data, LCP explanation, baseline comparison, and async job retrieval. No tool appears to be filler.
The surface covers the core PSI workflows: configuration check, lab measurement, real-user field data, LCP diagnosis, regression comparison, and job collection. Minor lifecycle gaps exist, such as no job cancellation/listing or baseline reset/delete, but agents can mostly work around them.