loading…
Search for a command to run...
loading…
A Model Context Protocol (MCP) server for performing automated accessibility scans of web pages using Playwright and Axe-core
A Model Context Protocol (MCP) server for performing automated accessibility scans of web pages using Playwright and Axe-core
MseeP.ai Security Assessment Badge
A powerful Model Context Protocol (MCP) server that provides automated web accessibility scanning and browser automation using Playwright and Axe-core. This server enables LLMs to perform WCAG compliance checks, interact with web pages, manage persistent browser sessions, and generate detailed accessibility reports with visual annotations.
✅ Full WCAG 2.0/2.1/2.2 compliance checking (A, AA, AAA levels)
📄 Detailed JSON reports with remediation guidance
🎯 Support for specific violation categories (color contrast, ARIA, forms, keyboard navigation, etc.)
🖱️ Click, hover, and drag elements using accessibility snapshots
⌨️ Type text and handle keyboard inputs
🔍 Capture page snapshots to discover all interactive elements
📸 Take screenshots and save PDFs
🎯 Support for both element-based and coordinate-based interactions
📑 Tab management for multi-page workflows
🌐 Monitor console messages and network requests
⏱️ Wait for dynamic content to load
📁 Handle file uploads and browser dialogs
🔄 Navigate through browser history
You can install the package using any of these methods:
Using npm:
npm install -g mcp-accessibility-scanner
A pre-built image is available on Docker Hub. The image includes Chromium and is pre-configured for containerized use — no extra flags needed.
Pull from Docker Hub:
docker pull justasmonkev/mcp-accessibility-scanner
claude mcp add mcp-accessibility-scanner -s user -- docker run -i --rm justasmonkev/mcp-accessibility-scanner
To persist screenshots and reports on your host, add a volume mount:
claude mcp add mcp-accessibility-scanner -s user \
-- docker run -i --rm -v /tmp/mcp-output:/app/output justasmonkev/mcp-accessibility-scanner
Without the -v mount, output files only exist inside the container and are lost when it exits.
docker compose up -d
docker build -t mcp-accessibility-scanner .
npm run test:docker
Install the Accessibility Scanner in VS Code using the VS Code CLI:
For VS Code:
code --add-mcp '{"name":"accessibility-scanner","command":"npx","args":["mcp-accessibility-scanner"]}'
For VS Code Insiders:
code-insiders --add-mcp '{"name":"accessibility-scanner","command":"npx","args":["mcp-accessibility-scanner"]}'
The scanner can run in two modes depending on how you use it.
When launched without a subcommand, the process starts an MCP server that communicates over stdio. This is the mode used by MCP clients such as Claude Desktop, VS Code, and Claude Code -- you should never need to run it by hand.
npx mcp-accessibility-scanner # starts the MCP server (stdio)
All of the MCP client configuration examples in this README already use this default mode.
interactive subcommand)For manual terminal use, the interactive subcommand starts a readline REPL where you can call any tool directly:
$ npx mcp-accessibility-scanner interactive
Interactive mode. Type "<tool-name> <json>" to call a tool. Ctrl+D to exit.
> browser_navigate {"url": "https://example.com"}
> scan_page {"violationsTag": ["wcag21aa"]}
> audit_keyboard {"maxTabs": 30}
Each line is <tool-name> <json-arguments>. Omit the JSON to pass {}.
Global browser connection flags still apply here, for example npx mcp-accessibility-scanner --headless interactive.
list-tools subcommand)To print every tool name and its description:
npx mcp-accessibility-scanner list-tools
Note: Tool names like
browser_navigateandscan_pageare MCP tool identifiers (and REPL commands in interactive mode). They are not shell subcommands -- you cannot runnpx mcp-accessibility-scanner browser_navigate.
Here's the Claude Desktop configuration:
{
"mcpServers": {
"accessibility-scanner": {
"command": "npx",
"args": ["-y", "mcp-accessibility-scanner"]
}
}
}
You can pass a configuration file to customize Playwright behavior:
{
"mcpServers": {
"accessibility-scanner": {
"command": "npx",
"args": ["-y", "mcp-accessibility-scanner", "--config", "/path/to/config.json"]
}
}
}
Create a config.json file with the following options:
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"headless": true,
"channel": "chrome"
},
"cdpLaunch": {
"command": "open",
"args": ["-a", "Slack", "--args", "--remote-debugging-port={port}"],
"startupTimeoutMs": 30000
}
},
"timeouts": {
"navigationTimeout": 60000,
"defaultTimeout": 5000
},
"network": {
"allowedOrigins": ["example.com", "trusted-site.com"],
"blockedOrigins": ["ads.example.com"]
}
}
Available Options:
browser.browserName: Browser to use (chromium, firefox, webkit)browser.launchOptions.headless: Run browser in headless mode (default: true on Linux without display, false otherwise)browser.launchOptions.channel: Browser channel (chrome, chrome-beta, msedge, etc.)browser.cdpEndpoint: Attach to an already-running Chromium-family app with CDP enabledbrowser.cdpHeaders: Map of HTTP headers to send with the CDP connect request, e.g. { "Authorization": "Bearer <token>" }, for endpoints that require header-based authenticationbrowser.cdpTimeout: Maximum time in milliseconds to wait when connecting to the CDP endpoint (default: 30000)browser.cdpLaunch: Launch a Chromium-family desktop app with CDP enabled, wait for the endpoint, and manage the child process lifecycletimeouts.navigationTimeout: Maximum time for page navigation in milliseconds (default: 60000)timeouts.defaultTimeout: Default timeout for Playwright operations in milliseconds (default: 5000)network.allowedOrigins: List of origins to allow (blocks all others if specified)network.blockedOrigins: List of origins to blockCLI equivalents are also available: --cdp-launch-command, --cdp-launch-args, --cdp-launch-cwd, --cdp-launch-port, --cdp-launch-startup-timeout, --cdp-endpoint, --cdp-header (repeat for multiple headers, e.g. --cdp-header "Authorization: Bearer <token>"), and --cdp-timeout. The CDP headers and timeout can also be set via the PLAYWRIGHT_MCP_CDP_HEADERS (one Name: Value entry per line) and PLAYWRIGHT_MCP_CDP_TIMEOUT environment variables.
When the server runs with --port, it sends MCP heartbeat pings for Streamable HTTP sessions. Set PLAYWRIGHT_MCP_PING_TIMEOUT_MS to override the default 5000 ms timeout. Set it to 0 or any negative value to disable heartbeat pings for clients or proxies that do not answer server-initiated pings.
The MCP server provides comprehensive browser automation and accessibility scanning tools:
scan_pagePerforms a comprehensive accessibility scan on the current page using Axe-core.
Parameters:
violationsTag: Array of WCAG/violation tags to checkSupported Violation Tags:
wcag2a, wcag2aa, wcag2aaa, wcag21a, wcag21aa, wcag21aaa, wcag22a, wcag22aa, wcag22aaasection508cat.aria, cat.color, cat.forms, cat.keyboard, cat.language, cat.name-role-value, cat.parsing, cat.semantics, cat.sensory-and-visual-cues, cat.structure, cat.tables, cat.text-alternatives, cat.time-and-mediaaudit_siteCrawls and scans multiple internal pages, then aggregates violations across the site.
links, nav, sitemap, and provided URL strategiesaudit-site-{timestamp}.json)Example flow:
1. Navigate to your site homepage with browser_navigate
2. Run audit_site with maxPages: 25 and maxDepth: 2
3. Review the report path returned by the tool (written to the MCP output directory)
scan_page_matrixRuns Axe scans on the same page across viewport/media/zoom variants and compares deltas against baseline.
scan-matrix-{timestamp}.json)Example flow:
1. Navigate to a page state you want to validate
2. Run scan_page_matrix with defaults (or provide custom variants)
3. Review per-variant deltas and open the generated JSON report path
audit_keyboardAudits real keyboard focus behavior by pressing Tab (and optional Shift+Tab) with practical heuristics.
screenshotOnIssue)audit-keyboard-{timestamp}.json)Example flow:
1. Navigate to the target page and let it fully load
2. Run audit_keyboard with maxTabs: 50
3. Review focus findings and open the generated JSON report path
browser_navigateNavigate to a URL.
url (string)browser_navigate_backGo back to the previous page.
browser_navigation_timeoutSet default navigation timeout for existing tabs.
timeout (in ms; 30000-300000)browser_default_timeoutSet default operation timeout for existing tabs.
timeout (in ms; 30000-300000)browser_snapshotCapture accessibility snapshot of the current page (better than screenshot for analysis).
Large data: URL payloads in snapshot output are truncated to their media type prefix.
browser_clickPerform click on a web page element.
element (description), ref (element reference), doubleClick (optional)browser_typeType text into editable element.
element, ref, text, submit (optional), slowly (optional)browser_hoverHover over element on page.
element, refbrowser_dragPerform drag and drop between two elements.
startElement, startRef, endElement, endRefbrowser_select_optionSelect an option in a dropdown.
element, ref, values (array)browser_fill_formFill multiple fields with one call.
fields (array of objects with name, type, ref, and value)browser_press_keyPress a key on the keyboard.
key (e.g., 'ArrowLeft' or 'a')browser_evaluateEvaluate a JavaScript expression on the page, or on a specific element when a ref is provided. The function's return value is serialized back as the result.
function (e.g., () => document.title or (element) => element.textContent), element (optional), ref (optional)browser_take_screenshotTake a screenshot of the current page.
filename (optional), type (png or jpeg), scale (css or device, default css), fullPage (optional), element/ref pair (for element screenshots)scale: device captures a high-resolution screenshot using device pixels (accounts for the device pixel ratio); scale: css keeps the image sized in CSS pixels.browser_pdf_saveSave page as PDF.
filename (optional, defaults to page-{timestamp}.pdf)This tool requires --caps pdf in the CLI.
browser_installInstall the configured browser engine (use when browser executable is missing).
browser_closeClose the page.
browser_resizeResize the browser window.
width, heightbrowser_tabsManage browser tabs in one tool.
action (list, new, close, select) and optional index (for close and select).browser_console_messagesReturns all console messages from the page.
Large data: URL payloads in console messages are truncated to their media type prefix.
browser_network_requestsReturns all network requests since loading the page.
Large data: URL payloads in request URLs are truncated to their media type prefix.
browser_wait_forWait for text to appear/disappear or time to pass.
time (optional), text (optional), textGone (optional)browser_handle_dialogHandle browser dialogs (alerts, confirms, prompts).
accept (boolean), promptText (optional)browser_file_uploadUpload files to the page.
paths (array of absolute file paths)browser_verify_element_visibleVerify an element by ARIA role/name.
role, accessibleNamebrowser_verify_text_visibleVerify text visibility.
textbrowser_verify_list_visibleVerify list items at a snapshot reference.
element, ref, items (array)browser_verify_valueVerify an element value or checked state.
type, element, ref, valueThese verification tools require --caps verify:
These tools require --caps vision:
browser_mouse_move_xyMove mouse to specific coordinates.
element, x, ybrowser_mouse_click_xyClick at specific coordinates.
element, x, ybrowser_mouse_drag_xyDrag from one coordinate to another.
element, startX, startY, endX, endYCoordinate-based tools require element descriptions for permission checks, but the coordinates themselves are used for action targeting.
1. Navigate to example.com using browser_navigate
2. Run scan_page with violationsTag: ["wcag21aa"]
1. Use browser_navigate to go to example.com
2. Run scan_page with violationsTag: ["cat.color"]
1. Navigate to example.com with browser_navigate
2. Take a browser_snapshot to see available elements
3. Click the "Sign In" button using browser_click
4. Type "[email protected]" using browser_type
5. Run scan_page on the login page
6. Take a browser_take_screenshot to capture the final state
1. Navigate to example.com
2. Use browser_snapshot to capture all interactive elements
3. Review console messages with browser_console_messages
4. Check network activity with browser_network_requests
1. Open a new tab with `browser_tabs` and `{"action":"new"}`
2. Navigate to different pages in each tab
3. Switch to a tab with `browser_tabs` and `{"action":"select", "index": 1}`
4. List all tabs with `browser_tabs` and `{"action":"list"}`
1. Navigate to a page
2. Use browser_wait_for to wait for specific text to appear
3. Interact with the dynamically loaded content
Note: Most interaction tools require element references from browser_snapshot. Always capture a snapshot before attempting to interact with page elements.
Clone and set up the project:
git clone https://github.com/JustasMonkev/mcp-accessibility-scanner.git
cd mcp-accessibility-scanner
npm install
MIT
Run in your terminal:
claude mcp add accessibility-scanner -- npx -y mcp-accessibility-scannerYes, Accessibility Scanner MCP is free — one-click install via Unyly at no cost.
No, Accessibility Scanner runs without API keys or environment variables.
Self-hosted: the server runs locally on your machine via the install command above.
Open Accessibility Scanner on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.
Browser automation, scraping, screenshots
by MicrosoftBrowser automation and web scraping.
by modelcontextprotocolPlugin-based MCP server + Chrome extension that gives AI agents access to web applications through the user's authenticated browser session. 100+ plugins with a
by opentabs-dev1,500+ developer infrastructure deals, free tiers, and startup programs across 54 categories. Search deals, compare vendors, plan stacks, and track pricing chan
by robhunterNot sure what to pick?
Find your stack in 60 seconds
Author?
Embed badge for your README
Browse similar
All browse MCPs