原始内容
Accessibility Scanner CLI Skill
Use the local CLI when you want direct automation without attaching an MCP client.
For AI agents using this skill: always launch the interactive REPL with npx mcp-accessibility-scanner interactive and send tool calls there. Do not use the default MCP server mode from this skill.
For Electron apps, prefer launching them through this CLI with --cdp-launch-command instead of using a separate automation layer.
CLI Modes
Interactive REPL
Start a readline prompt for tool execution. This is the required mode for AI agents using this skill. Type <tool-name> <json> to call tools.
npx mcp-accessibility-scanner interactive
npx mcp-accessibility-scanner --headless interactive
REPL example session:
> browser_navigate {"url":"https://example.com"}
> scan_page {"violationsTag":["wcag2aa"]}
> audit_keyboard {}
> browser_close {}
List Tools
Print all available tools and their descriptions.
npx mcp-accessibility-scanner list-tools
npx mcp-accessibility-scanner --caps vision,pdf list-tools
MCP Server (do not use from this skill)
Running the CLI without a subcommand starts the MCP server over stdio for MCP clients. This skill does not use that mode.
npx mcp-accessibility-scanner
npx mcp-accessibility-scanner --headless --browser chrome
Global CLI Options
| Option | Description |
|---|---|
--browser <browser> |
Browser to use: chrome, firefox, webkit, msedge |
--headless |
Run browser in headless mode (headed by default) |
--caps <caps> |
Comma-separated extra capabilities: vision, pdf, verify |
--viewport-size <size> |
Browser viewport, e.g. "1280, 720" |
--device <device> |
Device emulation, e.g. "iPhone 15" |
--output-dir <path> |
Directory for output files (reports, screenshots) |
--config <path> |
Path to configuration file |
--user-data-dir <path> |
Browser profile directory |
--isolated |
Keep browser profile in memory only |
--storage-state <path> |
Storage state file for sessions that create their own context (--isolated, remote endpoint, CDP + --isolated) |
--executable-path <path> |
Custom browser executable |
--cdp-endpoint <endpoint> |
Connect to existing CDP endpoint |
--cdp-header <header> |
CDP connect header, e.g. "Authorization: Bearer <token>". Repeat the flag for multiple |
--cdp-timeout <ms> |
Timeout for connecting to the CDP endpoint (default 30000) |
--cdp-launch-command <command> |
Launch a Chromium-family desktop app with CDP enabled |
--cdp-launch-args <args> |
Comma-separated launch arguments. Use {port} placeholder for the debug port |
--cdp-launch-cwd <path> |
Working directory for the launched app |
--cdp-launch-port <port> |
Fixed CDP port for the launched app |
--cdp-launch-startup-timeout <ms> |
How long to wait for the launched app CDP endpoint |
--proxy-server <proxy> |
Proxy server, e.g. "http://myproxy:3128" |
--proxy-bypass <bypass> |
Comma-separated domains to bypass proxy |
--allowed-origins <origins> |
Semicolon-separated allowed origins |
--blocked-origins <origins> |
Semicolon-separated blocked origins |
--block-service-workers |
Block service workers |
--ignore-https-errors |
Ignore HTTPS certificate errors |
--user-agent <ua> |
Custom user agent string |
--host <host> |
Server bind host (default: localhost) |
--port <port> |
Port for MCP Streamable HTTP transport |
--navigation-timeout <ms> |
Page navigation timeout (default: 60000) |
--default-timeout <ms> |
Default Playwright operation timeout (default: 5000) |
--save-session |
Save session to output directory |
--save-trace |
Save Playwright trace to output directory |
--no-sandbox |
Disable browser sandboxing |
--image-responses <mode> |
"allow" or "omit" image responses (default: allow) |
Accessibility Scanning Tools
scan_page
Scan the current page for accessibility violations using Axe.
{"violationsTag": ["wcag2aa", "wcag21aa", "wcag22aa"]}
For Electron CDP targets, scan_page may currently fail with Target.createTarget: Not supported. If that happens, keep using the CLI session, select the live app tab with browser_tabs, and run Axe through browser_evaluate by injecting the local node_modules/axe-core/axe.min.js bundle.
audit_site
Crawl and aggregate accessibility violations across multiple pages. Writes a JSON report.
{
"startUrl": "https://example.com",
"strategy": "links",
"maxPages": 25,
"maxDepth": 2,
"sameOriginOnly": true,
"violationsTag": ["wcag2aa"]
}
Crawl strategies:
links(default) - Follow all<a>links up tomaxDepthnav- Scan the start page, then follow only navigation links found on that page inside<nav>,<header>, or[role="navigation"](single-hop)sitemap- Fetch URLs from sitemap XML (usesitemapUrlto override default/sitemap.xml)provided- Scan an expliciturlsarray
Key options:
maxPages(1-200, default 25)maxDepth(0-5, default 2, links strategy only)includeSubdomains- Allow subdomains whensameOriginOnly=trueexcludePathPatterns- Regex patterns to skip (default:logout|signout)reportFile- Custom output filename
Behind a login: the crawl shares the browser context, so signing in with browser_navigate / browser_fill_form first is enough. Alternatively record a session with npx playwright codegen --save-storage=auth.json <login-url> and start the server with --isolated --storage-state ./auth.json (storage state needs a mode that creates its own context — --isolated, a remote endpoint, or CDP with --isolated; the persistent profile, plain CDP attach and --extension error out rather than auditing anonymously). Extend excludePathPatterns with anything else that ends the session (account deletion, session revocation, account/locale switchers) — it replaces the default, so keep logout|signout in the list. If the crawl loses the cookies it started with, the result opens with a WARNING: session cookie(s) … line and the report carries a sessionLoss object naming the page reached after any redirect, even when that page failed to load; everything scanned after it was audited signed-out. Cookie values are not compared and a cookie the browser dropped at its own expiry is ignored, but any other cookie the crawl started with and lost is reported — nothing marks a cookie as an authentication one.
scan_page_matrix
Run accessibility scans across viewport, media, and zoom variants. Compares each variant against a baseline.
{
"violationsTag": ["wcag2aa"],
"reloadBetweenVariants": false
}
Default variants: baseline, mobile (375x812), desktop (1280x720), forced-colors, reduced-motion, zoom-200
Custom variants:
{
"variants": [
{"name": "baseline"},
{"name": "tablet", "viewport": {"width": 768, "height": 1024}},
{"name": "dark-mode", "media": {"colorScheme": "dark"}},
{"name": "zoom-150", "zoomPercent": 150}
]
}
Media options: colorScheme (light/dark), forcedColors (active/none), contrast (more/no-preference), reducedMotion (reduce/no-preference)
audit_keyboard
Audit keyboard tab order, focus visibility, skip links, and focus traps. Writes a JSON report.
{
"maxTabs": 50,
"checkSkipLink": true,
"checkFocusVisibility": true,
"checkFocusTrap": true,
"screenshotOnIssue": true,
"maxIssueScreenshots": 3
}
Key options:
includeShiftTab- Alternate Tab/Shift+TabactivateSkipLink- Press Enter when skip link foundstopOnCycle(default true) - Stop on focus trap detectionjumpScrollThresholdPx(default 800) - Scroll delta for jump detection
Violation Tag Reference
WCAG standards:
wcag2a, wcag2aa, wcag2aaa, wcag21a, wcag21aa, wcag21aaa, wcag22a, wcag22aa, wcag22aaa, section508
Categories:
cat.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
Browser Automation Tools
These tools are always available and work in the interactive REPL.
Navigation & Page
| Tool | Description |
|---|---|
browser_navigate |
Navigate to URL: {"url": "https://..."} |
browser_navigate_back |
Go back to previous page |
browser_close |
Close the page |
browser_resize |
Resize window: {"width": 1280, "height": 720} |
browser_snapshot |
Capture accessibility snapshot |
browser_take_screenshot |
Take screenshot (png/jpeg, fullPage option) |
browser_wait_for |
Wait for text/time: {"text": "loaded"} or {"time": 5} |
Interaction
| Tool | Description |
|---|---|
browser_click |
Click element by ref: {"element": "Submit", "ref": "s1e5"} |
browser_type |
Type text: {"element": "Search", "ref": "s1e3", "text": "query", "submit": true} |
browser_press_key |
Press key: {"key": "Enter"} |
browser_hover |
Hover over element |
browser_drag |
Drag between elements |
browser_select_option |
Select dropdown option |
browser_fill_form |
Fill multiple form fields at once |
browser_file_upload |
Upload files: {"paths": ["/path/to/file"]} |
browser_handle_dialog |
Handle browser dialog: {"accept": true} |
browser_evaluate |
Run JavaScript on page |
Tabs & Config
| Tool | Description |
|---|---|
browser_tabs |
Manage tabs: {"action": "list"}, {"action": "new"}, {"action": "close"}, {"action": "select", "index": 1} |
browser_navigation_timeout |
Set navigation timeout (30s-20min) |
browser_default_timeout |
Set default operation timeout (30s-20min) |
Diagnostics
| Tool | Description |
|---|---|
browser_console_messages |
Get all console messages |
browser_network_requests |
Get all network requests |
Optional Tools (require --caps)
--caps pdf: browser_pdf_save - Save page as PDF
--caps verify: browser_verify_element_visible, browser_verify_text_visible, browser_verify_list_visible, browser_verify_value
--caps vision: browser_mouse_move_xy, browser_mouse_click_xy, browser_mouse_drag_xy
Common Recipes
Full WCAG 2.2 AA audit of a site
npx mcp-accessibility-scanner --headless interactive
> browser_navigate {"url":"https://example.com"}
> audit_site {"strategy":"links","maxPages":50,"maxDepth":3,"violationsTag":["wcag2aa","wcag21aa","wcag22aa"]}
Quick single-page scan
npx mcp-accessibility-scanner --headless interactive
> browser_navigate {"url":"https://example.com/page"}
> scan_page {"violationsTag":["wcag2aa"]}
Responsive + media variant scan
npx mcp-accessibility-scanner --headless interactive
> browser_navigate {"url":"https://example.com"}
> scan_page_matrix {"violationsTag":["wcag2aa","wcag21aa"]}
Keyboard accessibility audit with screenshots
npx mcp-accessibility-scanner --headless interactive
> browser_navigate {"url":"https://example.com"}
> audit_keyboard {"screenshotOnIssue":true,"maxIssueScreenshots":5,"activateSkipLink":true}
Scan specific pages from a list
npx mcp-accessibility-scanner --headless interactive
> audit_site {"strategy":"provided","urls":["https://example.com/","https://example.com/about","https://example.com/contact"],"violationsTag":["wcag2aa"]}
Electron app flow
Launch the app binary directly if open -a does not expose the CDP port. If the app is already running, quit it first so the debug flag is applied on a clean start.
npx mcp-accessibility-scanner interactive --cdp-launch-command /Applications/YourApp.app/Contents/MacOS/YourApp --cdp-launch-args=--remote-debugging-port={port} --cdp-launch-port 9222 --cdp-launch-startup-timeout 20000
Typical REPL flow:
> browser_tabs {"action":"list"}
> browser_tabs {"action":"select","index":1}
> browser_evaluate {"function":"() => ({ url: location.href, text: document.body.innerText, links: Array.from(document.querySelectorAll('a,button,[role=button]')).map((el, i) => ({ i, text: (el.textContent || '').trim(), tag: el.tagName, href: el.getAttribute('href') })) })"}
> browser_evaluate {"function":"() => document.querySelector('SELECTOR_FOR_NEXT_STEP')?.click()"}
If scan_page {} fails on the Electron target, use this Axe fallback from the same REPL session:
{
"function": "async () => { if (!window.axe) { await new Promise((resolve, reject) => { const script = document.createElement('script'); script.src = 'file:///ABSOLUTE/PATH/TO/node_modules/axe-core/axe.min.js'; script.onload = resolve; script.onerror = () => reject(new Error('Failed to load axe')); document.head.appendChild(script); }); } const results = await window.axe.run(document); return { url: location.href, violations: results.violations.length, incomplete: results.incomplete.length, passes: results.passes.length, inapplicable: results.inapplicable.length, rules: results.violations.map(v => ({ id: v.id, impact: v.impact, help: v.help, nodes: v.nodes.length })) }; }"
}