mya11yreport-mcp
An MCP server that gives AI agents browser-based accessibility auditing and Playwright browser-control tools.
Start and close isolated browser sessions with auto-close, local action logs, and screenshots.
Navigate pages and interact via click, type, press key, check/uncheck, select option, and scroll.
Capture viewport screenshots and YAML accessibility-tree snapshots.
Run axe-core audits per URL with violation counts/details, tag filters, and optional full JSON.
Review alt text/images, page structure, headings, landmarks, lists, frames, and tab order.
Check WCAG 2.2 color contrast without a browser or session.
Evaluate arbitrary page JavaScript to inspect DOM, styles, geometry, or custom state.
Get viewport size and scroll position.
Retrieve a step-by-step audit guide, including human-only checks.
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., "@mya11yreport-mcp Run an accessibility audit on this page and summarize WCAG 2.2 issues."
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.
MyA11yReport MCP server
Want 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.
Related MCP server: mcp-a11y-tools
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 |
|
| Idle auto-close delay (min 1000) |
|
| Session log directory |
|
| 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.
Available Tools
21 toolscheckCheck checkbox/radioA
Checks a checkbox or radio input in the session page. No-op if already checked. Targets support selectors or getBy* locators (e.g. getByRole with name).
Inputs: target (required), sessionId (required), timeoutMs.
check_color_contrastCheck color contrastA
Computes the WCAG 2.2 contrast ratio between two colors and which of the four AA/AAA thresholds they clear. Accepts hex or rgb()/rgba() colors. Needs no session and no browser. Pass fontSizePx and fontWeight to also classify the pair as WCAG large text.
Inputs: background (required), foreground (required), fontSizePx, fontWeight.
clickClick elementA
Clicks an element in the session page. Auto-waits for the element to be visible, stable, and actionable. Targets support CSS selectors or accessibility-first locators (getByRole, getByText, getByLabel, ...).
Inputs: target (required), sessionId (required), timeoutMs.
close_sessionClose sessionA
Stops a session and terminates its browser context (page state and cookies are gone; the session's history file is finalized with a closedAt timestamp). Returns closed:false plus the active sessions when the id is unknown. A closed session can be started again later; its previous history is archived, not overwritten.
Inputs: sessionId (required).
evaluateEvaluate JavaScriptA
Evaluates a JavaScript expression or function in the session page via Playwright page.evaluate and returns its value. Use it to inspect the live DOM (computed styles, geometry, custom element state) when get_page_snapshot is not enough. The result must be serializable across the Playwright boundary; non-serializable or undefined values come back as null with serializable:false. This runs arbitrary page JavaScript — only evaluate code you intend to run.
Inputs: sessionId (required), expression (required), arg.
get_audit_guideGet audit guideA
Returns the step-by-step accessibility audit workflow for agents as markdown: how to enumerate URLs from a sitemap, run the automated axe-core pass, the structure/tab-order/images/contrast reviews, the output-report format, and exactly which checks (keyboard navigation, screen-reader compatibility, image meaning) must be done by a human. Call this before starting an audit. Needs no session or browser. Also published at https://mya11y.report/mcp/auditor-skill.
Inputs: no named parameters.
get_page_snapshotGet page snapshotA
Returns a YAML accessibility-tree snapshot of the session page (roles, names, states). Use it to discover roles/names to target with getByRole/getByText/getByLabel in click/type/check.
Inputs: sessionId (required).
get_scroll_positionGet scroll positionA
Returns the current scroll position of the session page plus document scroll dimensions and the viewport size — useful for planning further scroll_by deltas.
Inputs: sessionId (required).
get_structureGet page structureA
Reads the page structure: landmark regions, headings, lists (nested) and iframes, each with a shadow-piercing selector. A heading outline grouped by region with skipped-level and repeated-H1 flags is included when both regions and headings are returned. Top frame only, open shadow roots only.
Inputs: sessionId (required), include.
get_tab_orderGet tab orderA
Lists the page's tab stops in the order the Tab key reaches them, using the tabbable algorithm: positive tabindex values first (ascending), then everything else in document order. Each stop reports its position, tag, label, effective tabindex, shadow-piercing selector and an outOfOrder flag when tabindex is positive. Top frame only; hidden/disabled/inert elements are excluded.
Inputs: sessionId (required).
get_viewport_sizeGet viewport sizeA
Returns the session page's viewport size in CSS pixels.
Inputs: sessionId (required).
list_imagesList images and alt textA
Lists every and inline on the session page with its accessible name, the source that name came from (aria-label, aria-labelledby, alt, title, desc or none), its src/currentSrc and sanitized SVG markup, a decorative flag, and a shadow-piercing selector. Derived flags mark genuinely missing alt text and overly long alt text (>250 chars). Top frame only, open shadow roots only.
Inputs: sessionId (required), filter.
press_keyPress keyA
Presses a key or chord (Enter, Tab, Escape, arrows, Space, Shift+Tab, Control+A, ...) in the session page. With a target, focuses that element and sends the key to it; without one, sends the key to the currently focused element. Use it for keyboard navigation, submitting a form with Enter, closing a dialog with Escape, or exercising keyboard-only interactions.
Inputs: key (required), sessionId (required), target, timeoutMs.
run_a11y_auditRun accessibility auditA
Runs an axe-core accessibility audit on the session page (or on url if provided, navigating first). Returns the session audit history: pages (hex ids, one per URL) and audits ({pageId, audit} entries) including the fresh result. Each audit contains violation counts by impact, per-violation details (rule id, help, selectors, failure summaries), and pass/incomplete rule counts.
Inputs: sessionId (required), url, tags, detail, +1 more.
screenshotTake screenshotA
Captures the current viewport of the session page (what is on screen after scrolling — not the full page). Saved as .png inside the session log directory; returns the file path plus the scroll position and viewport at capture time.
Inputs: sessionId (required).
scroll_byScroll pageA
Scrolls the session page window by the given deltas (window.scrollBy) and returns the new scroll position. For lazy-loaded content, scroll then re-run get_page_snapshot.
Inputs: sessionId (required), x, y, behavior.
select_optionSelect optionA
Selects an inside a element on the session page, matched by the option's value attribute. Waits for the element to be actionable. Targets support selectors or getBy* locators, same as type.
Inputs: value (required), target (required), sessionId (required), timeoutMs.
start_sessionStart sessionA
Starts a browser session and returns its sessionId — pass that sessionId to every subsequent tool call (navigate, click, type, run_a11y_audit, ...). Each session is an isolated page with its own cookies, audit history, and action log. Sessions auto-close after 5 minutes of inactivity (MYA11Y_MCP_IDLE_CLOSE_MS overrides).
Inputs: alias, headless.
typeType textA
Types text into an element (input, textarea, contenteditable). By default replaces the current value; set clear:false to append. Targets support selectors or getBy* locators.
Inputs: text (required), target (required), sessionId (required), clear, +2 more.
uncheckUncheck checkboxB
Unchecks a checkbox in the session page. No-op if already unchecked.
Inputs: target (required), sessionId (required), timeoutMs.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 21 tools
The tools split into clear lifecycle, inspection, and interaction groups, and each inspection tool targets a distinct artifact (a11y tree, landmarks, tab stops, images). A few minor overlaps exist, such as get_viewport_size and get_scroll_position both returning viewport dimensions, and get_page_snapshot versus get_structure both describing page structure, but descriptions clarify the intended use.
Most tools follow a verb_noun snake_case pattern (start_session, get_tab_order, run_a11y_audit). The interaction tools deviate as bare verbs (navigate, click, type, check, uncheck, evaluate, screenshot) and scroll_by uses a preposition, so the pattern is not uniform, but the categories are still readable and predictable.
21 tools is on the heavy side for a single server, landing in the 16-25 range that feels bloated at first glance. That said, the count is justified by the combination of browser automation, page inspection, session management, and audit functionality; it is broad but not redundant.
The surface covers the full accessibility audit loop: session lifecycle, navigation, automated axe-core audits, contrast checks, structural inspection, and keyboard/form interactions for manual checks. Minor gaps remain, such as no explicit viewport resizing, hover action, or full-page screenshot option, but agents can work around them with evaluate or scrolling.
Maintenance
Related MCP Connectors
Free WCAG 2.2/ADA/508 accessibility MCP: scan, AI fixes, verify, vision audit, localhost tunnel
Run WCAG accessibility scans on websites, list each issue with its element, and triage from chat.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
Read-only web QA agent: scans a site in a real browser and returns evidence-backed findings
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI agents to perform comprehensive accessibility audits on websites using Playwright and axe-core against WCAG standards. Provides detailed compliance reports with violation summaries and remediation guidance across multiple browsers.3MIT
- AlicenseNot gradedqualityDmaintenanceProvides AI agents with web accessibility analysis tools via MCP, enabling checks for alt text, heading hierarchy, color contrast, ARIA validation, and form accessibility.46 npmMIT
- FlicenseNot gradedqualityDmaintenanceEnables browser automation through the MCP protocol, allowing AI agents to control a real browser using accessibility snapshots and natural language commands.-
- AlicenseAqualityDmaintenanceExposes axe-core accessibility auditing as MCP tools so any MCP-compatible agent can audit HTML for structural and semantic issues.3MIT