mya11yreport-mcp
v1.0.4
Published
Offline MCP server: axe-core accessibility audits + agentic browser interaction (Playwright) over stdio.
Maintainers
Readme
MyA11yReport MCP server
What continuous accessibility monitoring? Check out MyA11yReport MyA11yReport is an automated accessibility scanner that uses AI to filter out false positives and explain genuine WCAG issues in plain English, featuring a centralized dashboard to track active issue counts, severities, and site progress over time.
About this MCP
An open-source Model Context Protocol server that gives AI agents real accessibility-auditing abilities. It runs axe-core audits and drives a real browser through Playwright (navigate, click, type, check/uncheck, scroll, screenshots, aria snapshots, page JavaScript), plus page reviews for alt text, structure and tab order, and a session-free WCAG 2.2 color-contrast checker.
Built for agents: sessions are explicit, every action is logged, and audit history is keyed by URL. It speaks MCP over stdio and needs no account, no API key and no network service of its own.
What you get
- Automated audits —
run_a11y_auditruns axe-core on the current page and accumulates results per URL. - Browser control —
navigate,click,type,press_key,check,uncheck,select_option,scroll_by,screenshot,get_page_snapshot,evaluate,get_viewport_size,get_scroll_position. - Page reviews —
list_images(alt text),get_structure(landmarks, headings, lists, frames),get_tab_order(focus order). - Contrast maths —
check_color_contrastcomputes the WCAG 2.2 ratio for any two colors, with no session or browser. - Audit guide —
get_audit_guidereturns the full step-by-step audit workflow as markdown, including which checks must be done by a human.
Requirements
- Node.js 20 or newer (
node --version) - Chromium, installed once with one command (see below). It is ~150 MB.
- For
headless: falsesessions, a machine with a real display.
Install
From npm (recommended)
npm i -g mya11yreport-mcp
mya11yreport-mcp install chromiumThe second step downloads the Chromium build that matches the server's Playwright version. It is a separate step rather than a post-install script because some machines block npm lifecycle scripts. If you skip it, the server still starts and simply tells you to run the command the first time a browser tool is used.
Prefer not to install globally? Use npx:
npx -y mya11yreport-mcp install chromiumTo confirm the server starts on your machine:
echo '{}' | mya11yreport-mcpIt should exit cleanly; EOF on stdin closes the server.
From source
Clone the repository and build it locally:
git clone <repository-url> mya11yreport-mcp
cd mya11yreport-mcp
npm install
npm run build
node dist/index.js install chromiumThen run the server from the checkout:
node /path/to/mya11yreport-mcp/dist/index.jsOptionally put the mya11yreport-mcp command on your PATH with npm link, so
you can use it anywhere:
npm link
mya11yreport-mcp install chromiumConnect it to your MCP client
Point your MCP client at the server over stdio. In
opencode, add it to your project opencode.json or your
global ~/.config/opencode/opencode.json.
After a global install or npm link:
{
"mcp": {
"mya11y-audit": {
"type": "local",
"command": [
"mya11yreport-mcp"
],
"enabled": true
}
}
}Without a global install, use npx:
"command": [
"npx",
"-y",
"mya11yreport-mcp"
]When running from a local checkout, point at the built entry file directly:
"command": [
"node",
"/path/to/mya11yreport-mcp/dist/index.js"
]Other MCP clients use the same idea — run the server executable with no arguments over stdio. Restart the client after changing its configuration.
Using the server
You do not call tools yourself: once the server is connected, your agent does. The typical flow is:
get_audit_guide— needs no session: returns the full step-by-step audit workflow as markdown (sitemap enumeration, the automated pass, the structure/tab-order/images/contrast reviews, report format, and the human-only checks). Call it before a full audit. The same guide is published at https://mya11y.report/mcp/auditor-skill.start_session— returns asessionId(pass an optional free-form alias, max 225 chars, sanitized to[A-Za-z0-9_-]; omit for a hex id). Also picksheadless: true|false.- Pass
sessionIdto every call:navigate,click,type,press_key,check,uncheck,scroll_by,screenshot,get_page_snapshot,evaluate,get_viewport_size,get_scroll_position,run_a11y_audit,list_images,get_structure,get_tab_order. - Targets are
{"selector": "#id"}or{"fn": {"name": "getByRole", "args": ["button", {"name": "Sign in"}]}}(getByRole | getByText | getByLabel | getByPlaceholder | getByAltText | getByTitle). run_a11y_auditaudits the current session page (or navigates tourlfirst) and returns the session's audit history:{pages: string[], audits: [{pageId, audit}]}— one hexpageIdper URL, audits accumulate per page.evaluateruns a JavaScript expression or function in the page viapage.evaluateand returns the serialized value (non-serializable orundefinedresults come back asnullwithserializable: false). Use it to read computed styles, geometry or custom element state.check_color_contrastneeds no session and no browser: pass two colors (hex orrgb()/rgba()) and optionallyfontSizePx/fontWeight, and it returns the WCAG 2.2 ratio, the AA/AAA grades, and whether the pair counts as large text.list_imagesreturns every<img>/ inline<svg>with its accessible name and source,src/currentSrc, sanitized SVG markup, a decorative flag and derivedmissingAlt/longAltflags plus counts. Filter withfilter: all | decorative | missing-alt | has-alt.get_structurereturns landmark regions, headings, nested lists and iframes, plus a heading outline grouped by region with skipped-level / repeated-H1 flags. Regions and headings also carry their rawariaLabel/ariaLabelledbyattributes. Narrow withinclude: [...].get_tab_orderreturns the Tab order (positivetabindexfirst, then document order) with each stop's tag, accessible name (text), effectivetabindex, shadow-piercing selector, rawariaLabel/ariaLabelledby,nameSource,hasLabelandoutOfOrderflags.close_sessionwhen done.
The three review tools (list_images, get_structure, get_tab_order) inspect
the top frame and open shadow roots only. get_tab_order uses the same
tabbable engine, vendored into the build.
Sessions and logs
- Sessions auto-close after 5 minutes of inactivity.
- Every session writes an action history to
.mya11yreport-mcp/logs/<sessionId>/<sessionId>.json. Screenshots land in the same directory as<actionId>.png. - Nothing is sent off your machine; the logs are plain local files you can inspect or delete at any time.
Configuration
| Variable | Default | Purpose |
|----------------------------|--------------------------------|-----------------------------------------|
| MYA11Y_MCP_IDLE_CLOSE_MS | 300000 (5 min) | Idle auto-close delay (min 1000) |
| MYA11Y_MCP_LOG_DIR | <cwd>/.mya11yreport-mcp/logs | Session log directory |
| PLAYWRIGHT_HEADLESS | true | Default headless mode (param overrides) |
headless: false needs a real display on the host machine.
Troubleshooting
- "Run
mya11yreport-mcp install chromium" — you have not installed the browser yet. Run that command once. - Timeouts or "element not found" — the target was not actionable in time.
Ask the agent to call
get_page_snapshotto discover targets, or retry with a largertimeoutMs. - Server exits immediately — that is expected when stdin closes (for example in the smoke test above). It is not an error.
