yardstick
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@yardstickCritique http://localhost:3000 against stripe.com and linear.app"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
yardstick
Measure a web page from the DOM and compare the numbers with two or three sites you admire.

Agent-built pages look generic and nobody can say why in terms the agent can act on. "Make it feel more like Stripe" is not a fix. "Your h1 is 36px over 18px body, Stripe holds 3.0 and Linear 4.9, set the h1 to 60px" is. Yardstick produces the second kind of sentence, and it never calls a model: fonts, type scale, spacing grid, palette, contrast pairs, hero geometry, and layout come from computed styles in headless Chromium, and every standard comes from the references you name, not from anyone's memory of what good looks like.
yardstick critique http://localhost:3000 --vs stripe.com,linear.appWhat it prints
A landing page I built with a coding agent, critiqued against stripe.com and linear.app, both captured live:
counts:
sev3: 1
sev2: 2
sev1: 0
first_change: "K1: Darken the text or lighten the background until the pair reaches 4.5:1; keep the hue, move lightness"
table[23]{metric,mine,stripe.com,linear.app}:
mode,light,light,dark
heading font,Bricolage Grotesque,sohne-var,Inter Variable
body font,Public Sans,sohne-var,Inter Variable
h1 px,58,48,64
body px,17,16,13
h1/body,3.41,3,4.92
h1 line-height,1.03,1.15,1
body line-height,1.62,1.4,1.54
measure ch,63.75,50.67,58.5
on-grid %,39.5,86.2,80.6
accent,#c4400a,#533afd,#e4f222
gradient hero,false,false,true
contrast fails,1,3,1
radii,0/8/999,0/4/5/6/10,0/6/8/9/12/16/22/9999
hero align,left,left,left
hero CTAs,1,2,3
...
findings[3]:
- id: K1
severity: 3
standard: "WCAG 1.4.3 needs 4.5:1 for body text and 3:1 for large text"
gap: "#64584c on #16110d measures 2.72:1 (\"Illustrative ledger, shortened for the page. Every entry is \")"
fix: "Darken the text or lighten the background until the pair reaches 4.5:1; keep the hue, move lightness"
region[4]: 295,831,850,21
- id: T2
severity: 2
standard: "Two families at most (stripe.com: 1, linear.app: 2)"
gap: "3 families carry text: Public Sans, IBM Plex Mono, Bricolage Grotesque"
- id: S1
severity: 2
standard: "References keep stripe.com 86%, linear.app 81% of spacing values on a 4px grid"
gap: "Yours is 40% on-grid; frequent values are 18, 14, 20, 22, 12"
shots:
mine: ~/.local/share/yardstick/shots/_critique/127.0.0.1-index/hero.png
stripe.com: ~/.local/share/yardstick/shots/stripe.com/hero.png
linear.app: ~/.local/share/yardstick/shots/linear.app/hero.pngThe contrast finding is real: the italic caption under the dark ledger is 2.72:1, and the region points at it. A deliberately sloppy page (Inter everywhere, purple gradient hero, nine identical rounded cards, 95-character lines) draws 3 severity-3 and 6 severity-2 findings against the same two references; the two hand-made good pages in tests/fixtures draw no severity-3 against each other. That pair is the test suite's positive and negative check.
Every finding is the shape designers validated in the UICrit study: the expected standard, the gap, how to close it, the evidence, and a rectangle on your hero screenshot when it is about an element. The screenshots are on disk so the agent driving the tool can read them and do the subjective half itself.
Related MCP server: mcp-ux-vision
Install
uv tool install git+https://github.com/matthewvilaysack/yardstick # or: uv build && uv tool install dist/*.whl
yardstick setup # installs headless Chromium once
yardstick seed # 1,160 domain pointers for `search`, optionalFor hacking on it: git clone, uv sync, uv run pytest -q, and bin/yardstick runs from the checkout.
Claude Code can use the CLI as is, with the skill linked so /yardstick loads the loop, or the MCP shim, which returns the same text plus the hero images as image blocks:
ln -s ~/code/yardstick/skill ~/.claude/skills/yardstick
claude mcp add --transport stdio yardstick --scope user -- ~/.local/bin/yardstick mcpThree ways to use it
CLI, for you and for coding agents that live in a terminal (the skill in
skill/SKILL.mdteaches Claude Code the loop).MCP server,
yardstick mcp, five tools (discover,search,show,measure,critique) for Claude Code, Cursor, Codex, or any MCP client; hero screenshots come back as images.Local app,
yardstick app, a one-screen interface on localhost: describe what you are building, pick the references it finds, run, read findings with the region outlined on your own screenshot, run again after fixes. History is kept on disk.

Finding references for an intent
yardstick discover "neighborhood dinner club that seats strangers together weekly" -n 5Providers run in order and the first one to name a site wins: live web search (DuckDuckGo through ddgs, no key), the seeded catalog of 1,160 design-described domains, then any command you add. A command is how a subagent, an agent CLI, or a paid search API plugs in without touching this code: it gets the intent on stdin and prints a JSON list of {domain, why}.
# ~/.config/yardstick/providers.toml
[providers.claude]
command = "claude -p --output-format text 'Name 5 real websites whose design a $(cat) should learn from. Reply with a JSON list of {domain, why} only.'"
timeout = 120--providers web,claude picks and orders them per call. --add captures every candidate as a reference in one go, so discover then critique --vs is the whole loop.
Commands
yardstick discover "<intent>" [-n 5] [--providers web,pointers,...] [--add]
yardstick app [--port 7878] [--no-open]
yardstick add <url> [--name n] capture, measure, store a reference
yardstick list stored references
yardstick search "<text>" [-n 5] references and seeded pointers, with the matched facets as "why"
yardstick show <name> [--full] measurement and screenshot paths
yardstick measure <url> measure without storing (localhost works)
yardstick critique <url> --vs a,b[,c] table, findings, first change, screenshot paths; --html <path> writes a standalone report
yardstick rm <name>
yardstick seed [--file README.md] load domain pointers (MIT catalog from scroobius-pip/fudge-design-md)
yardstick setup [--dry-run] install the headless browser
yardstick mcp stdio MCP serverOutput is TOON; add --json after the subcommand for JSON. Errors are structured on stdout: exit 1 for usage, exit 2 when a capture fails, with the stage named.
Checks
id | fires when |
K1 | a text/background pair fails WCAG AA, verified against screenshot pixels; unverifiable pairs are counted, not reported |
T4 | body paragraphs run outside 40 to 80 characters per line |
H2 | no button-styled action above the fold while every reference has one |
T1 | h1/body ratio below 75% of the references' minimum or above 150% of their maximum |
T2 | more than two families carry text, or headings use Inter, Roboto, Arial, Helvetica, system-ui, Poppins when no reference does |
T3 | h1 line-height above 1.3, or body line-height outside 1.4 to 1.75 |
S1 | share of spacing values on a 4px grid more than 20 points under the references' minimum |
C1 | gradient hero background when no reference has one |
C2 | chromatic hue count above the references' maximum plus two |
P1 | one radius on eight or more boxed elements while the references vary theirs |
H1 | h1 pixel size more than 15% outside the references' range |
H3 | dark versus light differs from every reference (informational) |
There is no 0 to 10 score. Counts by severity are honest; a score without calibration data is not.
Layout
src/yardstick/walk.js one page.evaluate: raw records per visible element (rect, text, computed type, colors, spacing, radius, shadow, parent)
src/yardstick/capture.py Playwright: load, scroll to settle, remove cookie banners, run the walk, hero + full screenshots, sample pixels behind text
src/yardstick/measure.py raw records -> measurement (pure Python, unit-tested without a browser)
src/yardstick/critique.py measurement + references -> table, findings, first change
src/yardstick/store.py SQLite with FTS5 over facets and pointers
src/yardstick/cli.py subcommands, TOON output, exit codes
src/yardstick/mcp_server.py five tools over the CLI, hero images as image blocks
src/yardstick/discover.py reference discovery: web, catalog, and command providers (providers.toml)
src/yardstick/app.py + app.html the local one-screen app over a small JSON API
src/yardstick/report.py standalone HTML report with outlined crops
tests/fixtures/ editorial.html, dark.html (good, different), slop.html (deliberately bad)
docs/design.md the design; docs/research.md the day of research it rests onData lives in ~/.local/share/yardstick/: refs.db and shots/<name>/. Captures are private on disk, nothing is redistributed, and yardstick rm is the takedown.
Tests
uv run pytest -q # 86 passed; the browser tests take about 30 secondsFor teams and products
Everything runs on the machine that runs it: no accounts, no uploads, no model calls. If you sell websites built with AI, the MCP is the piece your agents call before and after they build, and the app is the piece your clients can look at. The MIT license lets you bundle it; the provider file lets you swap in your own search or your own agent as the discovery step.
Not in this version
Mobile and dark-scheme captures, embeddings, a numeric score, a hosted service, DESIGN.md or Tailwind export, font similarity. Each is a slice once the critique has been used on a few real pages.
Available Tools
5 toolscritiqueA
Critique a URL against comma-separated reference names or domains (domains are captured on the fly). Returns a side-by-side table, findings with standard/gap/fix/evidence/region, the first change to make, and hero images (yours first).
| Name | Required | Description | Default |
|---|---|---|---|
| vs | Yes | ||
| url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full transparency burden. It discloses useful behavioral details, including that domains are captured on the fly and that hero images are returned 'yours first,' but it does not mention side effects, whether the URL is modified, or any prerequisites such as authentication.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense, well-structured sentence that front-loads the core action and then compacts the return format efficiently. No filler or redundant repetition of the schema is present.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Because there is no output schema, the description compensates by listing the main return components: side-by-side table, findings fields, first change, and hero images. It is complete enough for a simple two-parameter tool, though it omits error behavior and explicit exclusions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It does: it clarifies that 'url' is the target URL and that 'vs' takes comma-separated reference names or domains. For a two-parameter tool, this is sufficient semantic guidance.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific action ('Critique'), a resource ('a URL'), and a target ('against comma-separated reference names or domains'), making the tool's purpose unambiguous. The detailed return-value summary further differentiates it from sibling tools like search, discover, show, and measure.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use the tool: whenever a URL needs to be compared against reference names or domains. However, it does not explicitly state when not to use it or name alternative sibling tools for related tasks, leaving some routing decisions to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
discoverA
Find reference sites for what the user is building, e.g. 'neighborhood dinner club landing page' or 'fintech dashboard for accountants'. Providers run in order (local catalog, live web search, then any configured command such as a subagent); one entry per site with a short why. Pass the domains to critique as --vs.
| Name | Required | Description | Default |
|---|---|---|---|
| n | No | ||
| intent | Yes | ||
| providers | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden. It usefully discloses that providers run in order (local catalog, live web search, then configured commands), returns one entry per site with a short rationale, and expects downstream usage with critique. It omits details like side effects or limits, but covers the main execution behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and every sentence adds useful information. It avoids filler and fits the tool's complexity well.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description gives a useful orientation and even references downstream critique usage, and an output schema exists. However, it leaves important gaps such as the meaning of 'n' and provider input format, and it does not explain how this tool relates to the sibling 'search' tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for parameter meaning. It explains the 'intent' parameter well with examples and hints at 'providers' by describing provider ordering, but it says nothing about the 'n' parameter or how to format the providers value.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Find reference sites for what the user is building,' with concrete examples. It conveys the tool's purpose clearly, though it does not explicitly distinguish itself from the sibling 'search' tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context: use it to discover reference sites based on the user's building intent, and then pass the resulting domains to critique. It does not explicitly state when not to use it or contrast it with alternatives, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
measureB
Measure any URL (localhost works) without storing it: fonts, type scale, spacing grid, palette, contrast, hero, layout.
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description must carry the behavioral burden. It does disclose a key trait: 'without storing it', which signals a privacy-conscious read operation, and 'localhost works' indicates local URL support. However, it omits other behaviors such as whether the URL is fetched live, how long measurement takes, or any rate limits. The disclosure is partial but not contradictory.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence. It leads with the core action ('Measure any URL'), immediately states the privacy trait, and lists the measured aspects in a compact enumeration. Every word contributes to the tool's utility; there is no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, no output schema, no annotations), the description is largely sufficient. It explains what the tool measures, notes that it does not store the URL, and supports localhost. It could clarify what the agent receives as a result (e.g., a report or scores), but that is not critical for invoking the tool. Overall, it covers the essential context for correct use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must explain the parameter. It states the tool measures 'any URL' and explicitly mentions localhost, giving the agent useful context about accepted values. It does not specify protocol requirements (e.g., HTTP/HTTPS) or encoding, but the single parameter is straightforward. The description adds minimal but adequate semantics for the URL parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool measures any URL and enumerates specific design aspects (fonts, type scale, spacing grid, palette, contrast, hero, layout). The verb 'measure' is distinct from siblings like search, discover, show, and critique, though it does not explicitly name an alternative. The purpose is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention any exclusion criteria, prerequisites, or situations where another sibling would be more appropriate. The usage is only implied by the action itself, which is insufficient for an agent to make a confident selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
searchC
Find stored references and seeded domain pointers by text, e.g. 'dark serif fintech landing'.
| Name | Required | Description | Default |
|---|---|---|---|
| n | No | ||
| text | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden for behavioral disclosure. It indicates a read-style search but does not state return format, pagination, or the effect of the optional 'n' parameter. No mention of safety or side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, front-loaded sentence with an illustrative example. Every word earns its place, and it is easily scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with two parameters and an output schema, the description is incomplete. It does not explain the meaning or effect of 'n', nor what 'seeded domain pointers' implies. While the output schema may cover return values, parameter semantics and usage context are insufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It explains that the 'text' parameter is used for searching ('by text'), but provides no information about the 'n' parameter, which remains undocumented. The example hints at the text format but leaves the other parameter unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Find') and the resource ('stored references and seeded domain pointers') with a concrete example. It does not explicitly differentiate from siblings, but the purpose is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives a typical query example but provides no guidance on when to use this tool versus alternatives like 'discover' or 'show'. No exclusions or conditions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
showC
Measurement summary and hero screenshot of a stored reference.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, yet it only lists outputs. It does not state that the operation is read-only, what happens if the name does not match a stored reference, or whether any cached data is regenerated. For a tool named show this is a notable gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The single sentence is compact and front-loads the key outputs. It earns its place, though a second sentence explaining the 'name' parameter would improve utility without harming concision.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter tool with no output schema and no annotations, the description should cover what 'name' refers to, whether the call is read-only, and what the response contains. It only partially covers the response (summary and screenshot) and omits the rest, leaving an agent to guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% and the description never explains the required 'name' property: what it refers to, how it maps to a stored reference, or expected format. The description therefore adds no semantic value for the only parameter.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description identifies a clear deliverable — a measurement summary and hero screenshot for a stored reference — which distinguishes it from search/discover/measure/critique sibling tools. It lacks an explicit verb like 'retrieve' or 'display' but the noun phrase conveys a display/read action well enough.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call show versus a sibling, no prerequisites such as having measured the reference first, and no mention of alternatives. The phrase 'stored reference' implies the item must already exist, but that is left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.2.0- First observed
critique - First observed
discover - First observed
measure - First observed
search - First observed
show
TDQS
Scored across 5 tools
Search and discover both return reference sites, but search targets stored items via text while discover finds new sites from a project description, so the intent is mostly clear. Show, measure, and critique are each distinct and unambiguous.
All five tool names are single lowercase verbs following a consistent action-first pattern (search, discover, show, measure, critique), which is predictable and easy to follow.
Five tools is well-scoped for a design reference, measurement, and critique server. Each tool represents a meaningful, distinct action without excess or redundancy.
The server covers searching, measuring, and critiquing reference sites, but there is no tool to store or manage new references, which leaves a notable lifecycle gap. Agents can work around it by using domains on the fly, but the stored-reference workflow feels incomplete.
Maintenance
Related MCP Connectors
Score any URL against a real design contract — 42 checks, A-F grade, token + motion validation.
Read, screenshot, diff, verify and audit any URL: SEO, links, sitemaps, schema, a11y.
Scores website pages for communication quality, tracks regressions, surfaces a fix queue.
Capture screenshots, detect visual regressions between page versions, and analyze with AI.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables rapid analysis of landing pages for SEO compliance, conversion structure, color contrast accessibility, and performance metrics with automated optimization suggestions and code snippets.6 npm1MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI-powered visual analysis of webpages for UI/UX assessment, including screenshot capture, element detection, accessibility auditing, and comprehensive JSON reporting.1-
- AlicenseAqualityAmaintenanceAnalyzes and extracts design tokens, assets, and layout from live websites to enable AI clients to faithfully replicate them, with tools for screenshotting, component inspection, and pixel-diff verification.148 npmMIT

uxlintofficial
AlicenseAqualityBmaintenanceAudits any site's UX the way a design-literate reviewer would — contrast, tap targets, type scale, colour discipline, scan patterns, copy — and returns the rule, the source line and the exact fix.4Apache 2.0