Mcp Accessibility Scanner — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited Mcp Accessibility Scanner (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
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-scannerA 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 Code
claude mcp add mcp-accessibility-scanner -s user -- docker run -i --rm justasmonkev/mcp-accessibility-scannerTo 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-scannerWithout the -v mount, output files only exist inside the container and are lost when it exits.
#### Docker Compose
docker compose up -d#### Build from source
docker build -t mcp-accessibility-scanner .#### Docker smoke test
npm run test:dockerInstall 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 --extension interactive.
list-tools subcommand)To print every tool name and its description:
npx mcp-accessibility-scanner list-toolsNote: Tool names likebrowser_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"]
}
}
}#### Configuration Options
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.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, and --cdp-launch-startup-timeout.
#### HTTP Heartbeat
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_page Performs 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-media#### audit_site Crawls 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_matrix Runs 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_keyboard Audits 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_navigate Navigate to a URL.
url (string)#### browser_navigate_back Go back to the previous page.
#### browser_navigate_forward Go forward to the next page.
#### browser_snapshot Capture accessibility snapshot of the current page (better than screenshot for analysis).
#### browser_click Perform click on a web page element.
element (description), ref (element reference), doubleClick (optional)#### browser_type Type text into editable element.
element, ref, text, submit (optional), slowly (optional)#### browser_hover Hover over element on page.
element, ref#### browser_drag Perform drag and drop between two elements.
startElement, startRef, endElement, endRef#### browser_select_option Select an option in a dropdown.
element, ref, values (array)#### browser_press_key Press a key on the keyboard.
key (e.g., 'ArrowLeft' or 'a')#### browser_evaluate Evaluate 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_screenshot Take a screenshot of the current page.
raw (optional), filename (optional), element (optional), ref (optional)#### browser_pdf_save Save page as PDF.
filename (optional, defaults to page-{timestamp}.pdf)#### browser_close Close the page.
#### browser_resize Resize the browser window.
width, height#### browser_tab_list List all open browser tabs.
#### browser_tab_new Open a new tab.
url (optional)#### browser_tab_select Select a tab by index.
index#### browser_tab_close Close a tab.
index (optional, closes current tab if not provided)#### browser_console_messages Returns all console messages from the page.
#### browser_network_requests Returns all network requests since loading the page.
#### browser_wait_for Wait for text to appear/disappear or time to pass.
time (optional), text (optional), textGone (optional)#### browser_handle_dialog Handle browser dialogs (alerts, confirms, prompts).
accept (boolean), promptText (optional)#### browser_file_upload Upload files to the page.
paths (array of absolute file paths)#### browser_screen_capture Take a screenshot for coordinate-based interaction.
#### browser_screen_move_mouse Move mouse to specific coordinates.
element, x, y#### browser_screen_click Click at specific coordinates.
element, x, y#### browser_screen_drag Drag from one coordinate to another.
element, startX, startY, endX, endY#### browser_screen_type Type text (coordinate-independent).
text, submit (optional)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 state1. 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_requests1. Open a new tab with browser_tab_new
2. Navigate to different pages in each tab
3. Switch between tabs using browser_tab_select
4. List all tabs with browser_tab_list1. Navigate to a page
2. Use browser_wait_for to wait for specific text to appear
3. Interact with the dynamically loaded contentNote: 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 installMIT
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.