From dx-core
Run accessibility testing on a URL using the axe MCP Server — analyze violations, get remediation guidance, apply fixes, and verify. Use when asked to check accessibility, run a11y audit, or fix WCAG issues.
npx claudepluginhub easingthemes/dx-aem-flow --plugin dx-coreThis skill is limited to using the following tools:
You perform accessibility testing and remediation using the Deque axe MCP Server. You follow a strict analyze → remediate → fix → verify workflow.
Conducts interactive WCAG accessibility audits on entire solutions, directories, or live URLs, checking compliance levels A/AA/AAA with optional Playwright visual scans.
Runs WCAG AA accessibility audits with automated axe-core scans via Playwright/vitest and manual checks across 7 categories: keyboard, contrast, ARIA, reduced motion, screen reader, high contrast. Provides findings table, fixes, and verification.
Share bugs, ideas, or general feedback.
You perform accessibility testing and remediation using the Deque axe MCP Server. You follow a strict analyze → remediate → fix → verify workflow.
Extract from $ARGUMENTS:
wcag2aa)If no URL is provided, ask the user for one.
Use ToolSearch to discover the axe MCP Server tools:
ToolSearch query: "+axe analyze"
Look for tools matching axe_mcp_server__analyze and axe_mcp_server__remediate (or similar naming with axe prefix).
If not found, tell the user:
axe MCP Server not available. See setup guide:
docs/dx-axe.mdin the plugin repo. Quick checklist: Docker running?AXE_API_KEYexported? Image pulled (docker pull dequesystems/axe-mcp-server:latest)? Plugin reinstalled after setup?
Then STOP.
The axe MCP Server runs inside Docker. URLs must be reachable from the container.
localhost)Replace localhost with host.docker.internal in the URL passed to axe — inside Docker, localhost is the container itself:
| User provides | Pass to axe |
|---|---|
http://localhost:4502/... | http://host.docker.internal:4502/... |
http://admin:admin@localhost:4502/... | http://admin:admin@host.docker.internal:4502/... |
If the URL has no credentials and the host is localhost:4502, embed admin:admin (AEM default local credentials):
http://admin:admin@host.docker.internal:4502/content/...?wcmmode=disabled
Read .ai/config.yaml for aem.qa-basic-auth. If the URL matches a QA/Stage host (aem.author-url-qa, aem.publish-url-qa) and has no credentials, embed them:
# .ai/config.yaml
aem:
qa-basic-auth:
username: "<user>"
password: "<pass>"
https://<user>:<pass>@qa.example.com/content/...
If qa-basic-auth is not configured and the URL looks like a QA/Stage host, warn the user that auth may be needed.
Pass through unchanged.
Many AEM pages render content client-side (Handlebars templates, lazy-loaded components). If axe analyzes a page before JS rendering completes, it audits an empty shell — results will be meaningless (false 100% pass).
Before running axe analyze, use Chrome DevTools MCP to check if the page has rendered:
mcp__plugin_dx-aem_chrome-devtools-mcp__navigate_page). If "tool not found", fall back to ToolSearch query: "+chrome-devtools navigate". Do NOT start with ToolSearch — if tools are pre-loaded, ToolSearch returns nothinglocalhost, not the Docker-rewritten one)mcp__plugin_dx-aem_chrome-devtools-mcp__evaluate_script
function: |
() => {
const text = document.body?.innerText?.trim();
return { length: text?.length, hasContent: text?.length > 200 };
}
hasContent is false after 15s, warn the user:
Page appears to be stuck loading. Axe results may be incomplete. Check for JS errors or missing dependencies.
If Chrome DevTools MCP is not available, skip this check and proceed — axe may still get usable results if the page is server-rendered.
Run the analyze tool with the resolved URL (Docker-safe):
axe_mcp_server__analyze
url: "<resolved URL>"
Parse the results. For each violation found, record:
color-contrast, image-alt, button-name)Print a summary table:
### Accessibility Analysis: <URL>
| # | Rule ID | Impact | Elements | WCAG |
|---|---------|--------|----------|------|
| 1 | color-contrast | serious | `.header-title` | 1.4.3 |
| 2 | image-alt | critical | `img.hero-banner` | 1.1.1 |
**Total:** N violations (X critical, Y serious, Z moderate)
If zero violations → print "No accessibility violations found." and STOP.
For each violation found in the analysis, call the remediate tool:
axe_mcp_server__remediate
ruleId: "<rule-id>"
element: "<affected HTML element or selector>"
description: "<issue description>"
Collect the remediation guidance for each violation. Print the guidance:
### Remediation Guidance
#### 1. [rule-id] — [impact]
**Element:** `<selector>`
**Fix:** <remediation guidance from axe>
#### 2. [rule-id] — [impact]
...
If --fix flag was NOT provided, print the guidance and STOP. Tell the user:
Run
/dx-axe <URL> --fixto automatically apply these fixes to your source code.
For each remediation:
Common fix patterns:
alt text → add alt attribute to <img> tags in HTL/HTMLaria-label or <label> elementstabindex, key event handlersrole attributes:focus-visible stylesRules for fixing:
.claude/rules/accessibility.md)After applying fixes:
Tell the user to rebuild if needed:
Rebuild required to see changes. Run your build command or ensure
watch:newis running.
Re-run analyze on the same URL:
axe_mcp_server__analyze
url: "<resolved URL>"
### Verification Results
| Metric | Before | After |
|--------|--------|-------|
| Critical | X | Y |
| Serious | X | Y |
| Moderate | X | Y |
| Minor | X | Y |
| **Total** | **X** | **Y** |
**Resolved:** N of M violations fixed
**Remaining:** [list any remaining violations with rule IDs]
If running within a dx workflow (spec directory exists):
SPEC_DIR=$(bash .ai/lib/dx-common.sh find-spec-dir $ARGUMENTS 2>/dev/null)
If $SPEC_DIR exists, save the report as $SPEC_DIR/a11y-report.md with:
remediate tool when fixing — always get axe's guidance firstanalyze → remediate → fix → analyze workflowlocalhost → host.docker.internal for URLs passed to axe