Agent Accessibility Scorer
Click on "Install 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., "@Agent Accessibility ScorerAnalyze https://myapp.com and give me agent accessibility score"
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.
Agent Accessibility Scorer
Score how usable your website is for AI browser agents — and let Claude Code fix it in a loop.
AI agents don't look at screenshots. Claude Code driving Playwright MCP, and most agent harnesses like it, read your page's accessibility tree as text and act on nodes by reference. Pixels never enter the loop.
So a site can look perfect and be unusable to an agent:
Renders fine | What the agent receives |
An icon button with a crisp SVG |
|
|
|
Three pricing cards, each "Learn more" | three identical |
A styled custom dropdown | no combobox role, no open/closed state |
axe and Lighthouse score for screen readers. They overlap, but they don't answer can an agent complete a task here — three links named "Learn more" pass axe cleanly and break agents constantly.
This does two things:
Web app — paste a URL, get a 0–100 score, prioritized fixes, and a side-by-side view of your page next to the text an agent actually gets.
MCP server — the same analysis as agent-callable tools, so a coding agent can run the improve loop.
The improve loop
This is the part that makes it more than a linter. A coding agent connects over MCP, gets a report, edits your source, redeploys, and calls back to check whether it actually worked:
flowchart LR
A["analyze_page(url)"] --> B["report <br/>score · findings · fixes <br/>+ runId"]
B --> C["agent edits <br/>your source"]
C --> D["redeploy"]
D --> E["compare_runs <br/>(baselineRunId)"]
E -->|"introduced > 0, or below target"| C
E -->|"clean"| F["done"]
style A fill:#1e3a5f,stroke:#5b9dff,color:#e6eaf0
style E fill:#1e3a5f,stroke:#5b9dff,color:#e6eaf0
style F fill:#14401f,stroke:#51cf66,color:#e6eaf0There is no loop code in this repo. The agent is the loop — it uses its own editing and deploy tools. What we provide is the four things that make each iteration meaningful:
Where | |
A report specific enough to act on — exact selectors, not "add a label" | |
Persistence, so a baseline survives a redeploy | |
Stable finding identity, so the agent learns which defect it fixed | |
The diff: fixed / persisting / introduced |
introduced is the guardrail. A rising score can hide a brand-new critical failure — which is exactly how unsupervised optimization against a metric goes wrong. Findings are keyed by a hash of rule id + selector with :nth-of-type(N) stripped, so they survive unrelated markup churn instead of looking "fixed" every time you insert a sibling.
Here's the loop running for real, against the fixture pair — bad.html edited into good.html, same rendered UI, fixed semantics:
analyze_page → 34/100 (F) runId=cc488273 20 findings
compare_runs → 100/100 (+66) fixed 20 · persisting 0 · introduced 0
reachability 60→100 · nameability 24→100 · forms 4→100Related MCP server: PixelCheck
Quick start
pnpm install # also fetches Chromium
pnpm build
pnpm dev # api :8787, web :5173Open http://localhost:5173 and paste a URL.

The panel that tends to land hardest is the side-by-side — your page on the left, the exact text an agent receives on the right, with unaddressable nodes highlighted. Most people have never seen the second one for their own site:

Production — the API serves the built frontend:
pnpm build && node apps/api/dist/server.js # http://localhost:8787Use it from Claude Code
claude mcp add agent-a11y -- node /absolute/path/to/packages/mcp/dist/stdio.jsThen:
Analyze https://staging.example.com with agent-a11y, fix the critical findings in this repo, redeploy, and compare against the baseline.
Four tools:
Tool | What it does |
| Load, capture, score. Returns a markdown report with selectors and fixes. |
| Just the raw accessibility snapshot — what you'd be operating on. |
| Structured JSON, filterable by category and severity. |
| Re-analyze and diff a baseline: fixed / still present / newly introduced. |
compare_runs is what closes the loop. It tracks findings by stable instance id, so it reports which problem you fixed — and what you broke.
Deployed remotely instead? The same server is mounted at POST /mcp (Streamable HTTP).
What it measures
Six weighted categories, 0–100 each:
Category | Weight | Question |
Snapshot reachability | 25 | Can the agent perceive it at all? |
Element nameability | 25 | Can it unambiguously address what it sees? |
Form comprehensibility | 20 | Can it understand and complete the inputs? |
Structure & navigability | 15 | Can it orient itself in the page? |
State & feedback | 10 | Can it tell what happened after acting? |
Agent access hygiene | 5 | Is it blocked or slowed before it starts? |
33 rules. Each finding comes with the exact selectors, an explanation written for agent failure modes rather than generic a11y boilerplate, and a copy-pasteable fix.
A finding becomes points like this — categories are scored independently and never bleed into each other, so the report can tell you your structure is fine, your forms are the problem:
flowchart LR
F["finding <br/>severity + instances"] --> W["severity weight <br/>× instanceFactor <br/>saturating"]
W --> P["category penalty <br/>100 − Σ, floored at 0"]
P --> O["overall <br/>Σ score × weight / 100"]
O --> G["grade <br/>A ≥90 · B ≥80 · C ≥70 · D ≥60 · F"]
style F fill:#3d1f1f,stroke:#ff6b6b,color:#e6eaf0
style G fill:#14401f,stroke:#51cf66,color:#e6eaf0The saturation matters: the first instance of a problem costs half the rule's ceiling, and further instances taper off. Without it an icon grid with sixty unnamed buttons would zero its category and drown out every other signal on the page — the score would stop being informative exactly when it's most needed.
How it works
Three capture channels, correlated, so the analyzer can spot what's missing rather than only what's malformed. Detecting an absence requires knowing what should have been there:
flowchart TD
P["page in headless Chromium"]
P --> A["A · ariaSnapshot() <br/>the verbatim text <br/>an agent receives"]
P --> B["B · CDP getFullAXTree <br/>computed role + name, <br/>name sources, <br/>ignoredReasons"]
P --> C["C · DOM inventory <br/>the counterfactual: <br/>what a human can <br/>see and click"]
B --> J{"join on <br/>backendNodeId"}
C --> J
J --> Q["visible and looks clickable — <br/>what does the agent get?"]
Q --> R["33 rules"]
R --> S["findings → score"]
A --> D["shown verbatim in the UI <br/>and get_agent_snapshot"]
style A fill:#1e3a5f,stroke:#5b9dff,color:#e6eaf0
style B fill:#1e3a5f,stroke:#5b9dff,color:#e6eaf0
style C fill:#1e3a5f,stroke:#5b9dff,color:#e6eaf0
style Q fill:#4a3a12,stroke:#ffd43b,color:#e6eaf0Four answers to that question, in descending severity: absent from the tree → present but role generic → correct role, no name → correct role, ambiguous name.
ignoredReasons is the most valuable field in the whole capture — when Chrome drops a node it tells you why (notRendered, ariaHiddenSubtree, uninteresting), which is a direct answer to "why can't the agent see this button" and isn't available any other way.
Full engineering reference: docs/DESIGN.md.
Architecture
flowchart LR
U["person"] --> W["apps/web <br/>React + TS"]
CC["coding agent <br/>(Claude Code)"] -.->|"MCP stdio"| M["packages/mcp <br/>4 tools"]
CC -.->|"MCP over HTTP"| API
W -->|"JSON"| API["apps/api <br/>Fastify <br/>REST + /mcp"]
API --> M
M --> AN
API --> AN["packages/analyzer <br/>analyze() <br/>capture → rules → score"]
AN --> CR["headless Chromium <br/>Playwright + CDP"]
AN --> ST[("run store <br/>baselines for <br/>compare_runs")]
style AN fill:#1e3a5f,stroke:#5b9dff,color:#e6eaf0
style CC fill:#4a3a12,stroke:#ffd43b,color:#e6eaf0packages/analyzer/ the engine — URL in, scored result out. No HTTP, no React.
packages/mcp/ MCP server (stdio + Streamable HTTP)
apps/api/ Fastify — REST + /mcp + static hosting
apps/web/ Vite + React + TypeScriptThe web app, the REST API, and every MCP tool call one analyze() function. There is no second code path — if the web report and the MCP report ever disagree, that's a bug, not a config difference.
Tests
pnpm test # 65 testsThe headline is the paired fixture test: bad.html and good.html render identically and differ only in semantics. Analyzed in a real browser, bad scores 34/100 (F), good scores 100/100 (A), and every finding in bad is absent from good.
59 of the 65 need no browser — captures serialize to JSON, so the whole rule engine tests against fixtures in milliseconds.
Configuration
Variable | Default | |
|
| |
|
| run storage |
|
| parallel browsers |
|
| requests/min/IP |
| unset | permit private addresses (dev only) |
URLs are checked against private address ranges after DNS resolution, and again after redirects.
License
MIT.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseAqualityDmaintenanceAn accessibility expert MCP server that provides AI coding assistants with real-time access to WAI-ARIA patterns, code review, contrast checking, and WCAG guidance for writing accessible code from the start.4MIT
- Alicense-qualityAmaintenanceAn MCP server that gives AI agents real browser capabilities including screenshotting, action execution, data extraction, and multi-persona auditing for frontend validation.4536MIT
- Alicense-qualityAmaintenanceAn MCP server that lets an AI agent scan a web page for WCAG accessibility issues and get back findings it can act on.221MIT
- AlicenseAqualityBmaintenanceAn MCP server for web accessibility testing that enables scanning, auditing, and fixing WCAG, ADA, and other compliance issues directly from your IDE, with free local scans, AI-generated framework-aware fixes, and verification capabilities.14145MIT
Related MCP Connectors
SEO MCP server: crawl your site, find AI-visibility gaps, and ship the fix from your coding agent.
MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.
Website QA for your coding agent: audit SEO, performance, security, accessibility over MCP.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/noahberry01123/agent-accessibility-scorer'
If you have feedback or need assistance with the MCP directory API, please join our Discord server