MCP server
The CLI includes a Model Context Protocol (opens in a new tab) server, so an AI agent calls the snippets as tools instead of reading their source or writing its own measurement code. It opens the page in a headless Chromium, runs the published snippet and returns the object the snippet returns, which follows the result contract (opens in a new tab).
npx -y webperf-snippets mcpThe server runs over stdio: the client starts this command and talks to it through its standard input and output. It is listed in the MCP Registry (opens in a new tab) as io.github.nucliweb/webperf-snippets.
Install
The server needs Node.js 20.12 or later and the Chromium of Playwright, which npx does not download:
npx playwright install chromiumWithout it, the tools answer with that same command, and an agent with a terminal can run it and call the tool again.
Claude Code
claude mcp add webperf -- npx -y webperf-snippets mcpOr install the webperf plugin, which adds the same server with the major version of the CLI pinned, so a breaking release does not reach it:
/plugin install webperf --marketplace nucliweb/webperf-snippetsOn Claude Code versions before 2.1.275, add the marketplace first with /plugin marketplace add nucliweb/webperf-snippets, then run /plugin install webperf@webperf-snippets.
Cursor, Claude Desktop, Gemini CLI and Antigravity
These clients read a JSON file with an mcpServers object:
| Client | File |
|---|---|
| Cursor | .cursor/mcp.json in the project, or ~/.cursor/mcp.json for every project |
| Claude Desktop | claude_desktop_config.json, opened from Settings → Developer → Edit Config |
| Gemini CLI | .gemini/settings.json in the project, or ~/.gemini/settings.json |
| Antigravity | .agents/mcp_config.json in the workspace, or ~/.gemini/config/mcp_config.json; in the editor, MCP Servers → Manage MCP Servers → View raw config |
{
"mcpServers": {
"webperf": {
"command": "npx",
"args": ["-y", "webperf-snippets", "mcp"]
}
}
}VS Code
.vscode/mcp.json in the workspace, or the mcp.json of the user profile, names the object servers and requires the transport:
{
"servers": {
"webperf": {
"type": "stdio",
"command": "npx",
"args": ["-y", "webperf-snippets", "mcp"]
}
}
}Tools
| Tool | What it does |
|---|---|
list_snippets | Lists the snippets with their category, title, short aliases and whether they track interactions. Takes an optional category. |
run_snippet | Opens a URL in a headless Chromium, runs one snippet and returns the object it returns. Takes url, snippet (name, alias or Category/Name), and optional viewport and waitMs. |
run_workflow | Runs a workflow (core-web-vitals, audit, loading, interaction) and the follow-ups of its decision tree, such as LCP-Subparts when LCP is over 2.5 s. Takes url, workflow, and optional viewport and waitMs. |
get_crux | Returns the CrUX p75 of LCP, CLS and INP for a URL, or for its origin. Takes url and an optional formFactor (phone, desktop, tablet). |
open_page | Opens a URL in a page that stays open between calls and installs tracking snippets (track, such as INP). Returns a sessionId. |
interact | Runs steps on an open page: click, type, hover, scroll or wait. |
read_results | Returns what the tracking snippets of an open page have recorded. |
close_page | Closes an open page. |
The snippets that record interactions (INP, Interactions, Input-Latency-Breakdown) run on a page opened with open_page: the agent installs them, clicks or types with interact and reads them with read_results. At most three pages are open at a time, a page closes after 10 minutes without use, and every page and Chromium close when the client disconnects.
Resources and prompts
The resources are documents a client can attach to the context:
| Resource | What it has |
|---|---|
webperf://schema | The contract every snippet result follows: base shape, statuses, how to read a result. |
webperf://schema/{snippet} | The fields one snippet returns, with an example. |
webperf://workflows/{category} | The workflows and the decision tree of a category. |
The prompts chain the tools for a common task, each with a url argument: audit_lcp, debug_inp and audit_page. In Claude Code they run as /mcp__webperf__audit_lcp.
CrUX field data
get_crux needs a CrUX API key (opens in a new tab), free in the Google Cloud console, in the CRUX_API_KEY variable of the server. It goes in the configuration of the client, never in a tool argument:
claude mcp add webperf -e CRUX_API_KEY=<key> -- npx -y webperf-snippets mcpThe server of the plugin reads CRUX_API_KEY from the environment of Claude Code: export it in your shell before you start Claude Code.
{
"mcpServers": {
"webperf": {
"command": "npx",
"args": ["-y", "webperf-snippets", "mcp"],
"env": { "CRUX_API_KEY": "<key>" }
}
}
}In VS Code, an input keeps the key out of .vscode/mcp.json: VS Code asks for it the first time the server starts and stores it.
{
"inputs": [
{ "type": "promptString", "id": "crux-api-key", "description": "CrUX API key", "password": true }
],
"servers": {
"webperf": {
"type": "stdio",
"command": "npx",
"args": ["-y", "webperf-snippets", "mcp"],
"env": { "CRUX_API_KEY": "${input:crux-api-key}" }
}
}
}An app opened from the Dock or the Start menu does not get the variables of your shell. If CRUX_API_KEY is only exported in your shell profile, set it in env. Keep a file with the key out of version control.
The other tools work without the key.
MCP server or Chrome DevTools MCP
The server measures a page in its own headless Chromium, with a fresh profile: no login, no extensions and no cache from earlier visits. To measure a page as you see it in your browser, with your session, use the Agent Skills with Chrome DevTools MCP (opens in a new tab), which run the same snippets in your Chrome.
Further reading
- Model Context Protocol (opens in a new tab) | modelcontextprotocol.io
- CLI | The same snippets and workflows from the command line and CI
- Result contract of the snippets (opens in a new tab) | GitHub
- Why the server is a subcommand of the CLI (opens in a new tab) | ADR 0002