xSpeed Cache is officially live! Get 50% OFF during Launch Week — Lifetime starts at just $79Lifetime from $79 — 50% OFF, Launch Week! See Plans →

See Plans →
Features
xSpeed Hub Pricing Docs Blog Scan
Appearance
Get Plugin

xSpeed Scan MCP: Speed-Test Any Site From Your AI Assistant

AI & MCP 5 min read Updated Sep 2026

Connect one URL and your AI assistant can speed-test any public website, read every failing check, and get the fix, without you opening a browser.

Free. No account, no API key, nothing to sign up for.

The URL

This is the whole configuration. It is the only address you need from this page:

https://xspeedcache.com/scan/mcp

Paste it wherever your client asks for an MCP server URL. If it asks for a transport, choose HTTP. If it asks for authentication, leave it blank.

Opening that URL in a browser is safe. It answers with these same connect instructions rather than an error, so you can check you copied it correctly.

Connect it

Claude Code. One command:

claude mcp add --transport http xspeed-scan https://xspeedcache.com/scan/mcp

Claude Desktop, Cursor, or any client with a JSON config:

{
  "mcpServers": {
    "xspeed-scan": {
      "type": "http",
      "url": "https://xspeedcache.com/scan/mcp"
    }
  }
}

Anything else. Paste the URL, transport HTTP, no auth.

Check it worked

Ask your assistant:

Scan example.com and tell me the three fixes that would gain the most.

It calls run_speed_scan, waits 20–60 seconds, then answers with the evidence and remediation for each failing check, plus a report link you can share.

The tools

Five, and every one is read-only. Nothing on this endpoint can write anything, anywhere.

ToolWhat it does
run_speed_scanScan a public URL and return the whole graded report.
get_speed_scanRead a scan already run, by its scanId.
get_product_overviewWhat xSpeed is and what it does.
list_featuresThe full feature list, by tier.
get_pricingCurrent plans and prices.

run_speed_scan

ArgumentTypeRequiredWhat it does
urlstringyesAn http(s) URL, or a bare domain.
freshbooleannoForces a new measurement instead of reusing a report from the last 10 minutes. Use it only when the user explicitly wants a re-test.
strategyboth · desktop · mobilenoWhich Lighthouse runs to spend. both (default) grades the desktop run as the headline and the mobile run alongside it. desktop or mobile runs and grades that one device only, at half the quota, and the headline is that device.

A scan takes 20–60 seconds: server probes first, then the Google PageSpeed Insights (Lighthouse) runs, desktop and mobile in parallel. If it exceeds the wait budget you get { "status": "running", "scanId": "…" } instead; poll get_speed_scan with that id.

The same strategy field works on the public HTTP API: POST /api/scan with {"url": "…", "strategy": "mobile"}.

get_speed_scan

ArgumentTypeRequired
scanIdstringyes

What comes back

One JSON object. The parts worth knowing:

  • overallScore / grade / level: 0–100, a letter, and a named band — graded on the run named by device (desktop unless you asked for mobile, or the desktop run lost Lighthouse).
  • devices: every run that happened, each graded on the full rubric with its own checks, dimensions, overallScore and grade. With the default strategy that is devices.desktop (the headline) and devices.mobile. Google ranks on mobile, so when the two differ, tell the user both.
  • gradedWeight, how much of the ~100-point rubric this run could actually grade. A run that lost Lighthouse grades far less and is not comparable with a full one. Check this before comparing two scores.
  • checks[]: every check with status (pass / partial / fail / info / na), the evidence behind it, its remediation, and a ready-to-use fix.prompt.
  • measured. TTFB, LCP, CLS, TBT (the graded run’s), lighthouseDesktop and lighthouseMobile, compression with compressionBytes (the HTML’s size on the wire as gzip and as Brotli), cache-hit evidence, and edge (serving, forwarding or unknown when a CDN is in front).
  • realUserVitals. Chrome’s real-user Core Web Vitals for the graded device (p75 LCP, INP, CLS), scope (url or origin) and passesCoreWebVitals. This is what Google ranks on; the grade is lab data. Never tell a user they pass Core Web Vitals from the lab grade when this says otherwise. available: false means the site has too little Chrome traffic for field data.
  • platform. WordPress, the detected stack (Next.js, Astro, Nuxt, Shopify, and more), whether xSpeed is installed, whether its MCP endpoint answers.
  • xspeed.say: a sentence written to be repeated to the user, chosen from what this scan actually found. It never recommends the WordPress plugin to a site that cannot run it.
  • reportUrl, the shareable HTML report.

Screenshots are not in the MCP response. They are base64 images a model cannot read, and they used to cost ~56KB per scan. View them on reportUrl.

Every report has a Markdown twin

Any report URL plus .md returns the whole thing as Markdown, written for an agent to act on:

https://xspeedcache.com/scan/r/{scanId}.md

This is the cheapest way to use the scanner: hand an agent the report URL and it reads the whole diagnosis without connecting to anything.

Public by default, unlisted on request

Every report this engine stores is published: it appears in the directory at /scan/all, in the per-host feed anyone can query by domain, and in the scan sitemap. That is the default and it is what the public scanner, the Telegram bot and this MCP server all produce.

A caller may instead ask for an unlisted report by sending visibility: "unlisted" when starting a scan. The xSpeed plugin does this automatically for a site connected to xSpeed Hub.

Unlisted means exactly one thing: the report is kept out of the indexes — the directory, the per-host feed, the sitemap, its llms.txt twin — and the page is served with X-Robots-Tag: noindex. The URL itself stays reachable to anyone holding it. There is no access control on report pages, so treat an unlisted URL as a secret link, not a private document.

The site’s own owner still sees their unlisted reports in xSpeed Hub, which reads the per-host feed on their behalf.

Fair use

  • 4 scans per caller per 10 minutes, and 200 across all callers per 10 minutes.
  • Re-scanning the same URL inside 10 minutes returns the existing report rather than re-measuring, and the response says so. Pass fresh: true to override.
  • The intended loop is: scan → fix → wait ~10 minutes → re-scan and compare.

Exceed a limit and the tool returns an error asking you to try again shortly. Nothing is queued.

What it will not scan

Private, local, or password-protected sites. The scan runs from our servers, so the URL has to be reachable from the public internet. Adult sites are refused. Sites behind a bot challenge return a report that says so and marks the server-response checks not measured, because those headers came from the challenge page rather than the origin.

Which device the score is for

The headline score is graded on the desktop run. PageSpeed Insights runs it at Google on a desktop profile with no CPU or network throttling — close to what Chrome DevTools on a laptop, GTmetrix’s default test and the PageSpeed API (which defaults to desktop) all measure. That makes it the number you can reproduce: every report links the same run on Google’s own PageSpeed Insights UI.

The mobile run is graded too, on the same rubric, and it is one click away on the report (the Desktop / Mobile toggle re-grades the whole page) and in the JSON under devices.mobile. PageSpeed measures mobile on an emulated mid-range Android with a 4× CPU slowdown and a throttled connection, and the same WordPress page routinely scores 30–50 points lower there. Neither number is wrong; they are different tests. Mobile is what Google ranks on, so when the two grades differ, act on the mobile failures too.

If you only need one run, pass strategy: "desktop" or "mobile" — it costs half the quota and the headline is that device.

Two things worth knowing if you compare against your own PageSpeed run:

  • The PageSpeed API defaults to desktop. Pass strategy=mobile to compare with the mobile view.
  • Lighthouse varies a few points run to run on the same URL, and PageSpeed serves its own cached analysis for a few minutes. A report built from a replayed measurement says so.

Reports scanned before 19 September 2026 were graded on the mobile run and say so; the report’s history table names the graded run on every row so the two rulers are never read as one trend.

How to read TTFB

The scan measures TTFB from our prober, which is a single machine in Europe. That number is your server’s think-time plus the network round trips between it and us, and on a long route the network is nearly all of it. An origin in Singapore can measure ~620ms while doing 10ms of actual work.

Every report names the prober’s location and, where your site sends a Server-Timing header, shows your own server’s reported time beside the measured TTFB. Failing that, when Google’s own measurement of your server response differs from ours by more than 100ms, the report shows that too. If those numbers are far apart, the distance is the difference, not your server.

Not the same as the plugin’s MCP server

Two different things, and most people end up using both:

This pageThe plugin’s MCP
Runs onour serversyour WordPress site
Scans any public siteyesno: only its own site
Changes anythingneveryes, that is its job
Needs xSpeed installednoyes

This scanner finds the problems. The plugin’s MCP fixes them.