navable MCP v0.2: Dual-Engine Scanning with Pa11y and HTMLCS
One scan engine is good. Two engines confirming the same issue? That's confidence you can put in a compliance report.
What's New in v0.2
Version 0.2 of @navable/mcp introduces Pa11y/HTMLCS as an optional second accessibility scan engine alongside axe-core. When enabled, both engines run in parallel against the same page, and their findings are deduplicated server-side before reaching your AI agent.
The result: higher-confidence audits, cross-confirmed findings, and broader WCAG coverage — without doubling token cost or scan time.
Why Two Engines?
No single accessibility testing engine catches everything. axe-core and HTMLCS (the engine behind Pa11y) have different rule sets, different detection strategies, and different blind spots. When both engines flag the same element for the same WCAG success criterion, that's a cross-confirmed finding — high confidence that it's a real barrier, not a false positive. This matters for compliance sign-off where auditors expect evidence.
How It Works
Enable Pa11y
Per scan — pass engines to the tool call:
run_accessibility_scan({ url: "http://localhost:3000", engines: ["axe", "htmlcs"] })
Always on — add to .navable.json in your project root:
{
"engines": ["axe", "htmlcs"]
}
By default, only axe-core runs. Pa11y is opt-in — you choose when to use it.
No Extra Downloads
Pa11y shares the same Chromium binary that Playwright already installed for axe-core scanning. There's no second browser download. The pa11y and puppeteer-core packages are bundled with @navable/mcp — just update to v0.2 and you're ready.
Server-Side Deduplication
When both engines run, the MCP server uses a conservative dedup strategy:
- Same WCAG success criterion + identical normalized CSS selector + matching HTML snippet → merged into one entry (axe version kept, tagged
alsoFlaggedBy: ["htmlcs"]) - Ambiguous overlap → both entries kept as separate findings
This means you never lose a legitimate finding due to aggressive merging. The safety bias is: wrong merges are far worse than missed merges.
What Results Look Like
{
"ruleId": "image-alt",
"impact": "critical",
"source": "axe",
"alsoFlaggedBy": ["htmlcs"],
"wcagCriteria": [{ "sc": "1.1.1", "en301549": "9.1.1.1" }],
"selector": "img.hero-banner",
"html": "<img class=\"hero-banner\" src=\"/hero.jpg\">"
}
Findings unique to HTMLCS include a helpUrl (link to the WCAG Understanding document) and a developerNote (one-sentence guidance for your agent):
{
"ruleId": "WCAG2AA.Principle1.Guideline1_3.1_3_1.H49.AlignAttr",
"impact": "moderate",
"source": "htmlcs",
"helpUrl": "https://www.w3.org/WAI/WCAG22/Understanding/info-and-relationships.html",
"developerNote": "Use semantic HTML to convey structure: headings for sections, <table> with <th> for data...",
"wcagCriteria": [{ "sc": "1.3.1", "en301549": "9.1.3.1" }]
}
When to Use Each Mode
| Scenario | Recommended engines | Why |
|---|---|---|
| Iterative fix loops (scan → fix → re-scan) | ["axe"] (default) | Fast (~3 s), low token cost, tight feedback loop |
| Compliance audit / BFSG sign-off | ["axe", "htmlcs"] | Cross-confirms findings, broader coverage, audit-grade confidence |
| User asks for "thorough" or "full" scan | ["axe", "htmlcs"] | Maximum detection coverage |
| CI pipeline quick-check | ["axe"] | Speed matters, minimal output |
The audit-page-structure agent skill enables dual-engine automatically. The scan-accessibility skill (used for fix workflows) keeps the axe-only default for faster iteration.
Controlling Token Cost with htmlcsIgnore
HTMLCS emits advisory "Check that…" warnings meant for human auditors. These inflate token cost without giving your agent actionable work. Suppress them in .navable.json:
{
"engines": ["axe", "htmlcs"],
"htmlcsIgnore": [
"WCAG2AA.Principle1.Guideline1_3.1_3_1.H49.AlignAttr",
"WCAG2AA.Principle2.Guideline2_4.2_4_1.H64.1",
"WCAG2AA.Principle1.Guideline1_3.1_3_1.H42.2"
]
}
Look for HTMLCS entries whose help text starts with "Check that…" in your scan output — those are candidates for suppression.
Upgrade
npm install @navable/mcp@latest
Or if you're using npx:
{
"mcpServers": {
"navable": {
"command": "npx",
"args": ["-y", "@navable/mcp@latest"]
}
}
}
No breaking changes. Existing workflows that don't pass engines continue to run axe-only — same behavior as before.
Updated Agent Skills
The navable agent skills are updated for v0.2:
scan-accessibility— now documents theenginesparameter with guidance on when to use axe-only vs dual-engine. Remains axe-only by default for fast fix loops.audit-page-structure— automatically enables["axe", "htmlcs"]for structural audits where cross-confirmation adds value.- Both skills handle the new result fields (
source,alsoFlaggedBy,helpUrl,developerNote) so your agent knows how to act on HTMLCS-only findings.
If you've already copied the skills into your project, pull the latest versions from the repository to get the updated descriptions and dual-engine handling.
What's Next
- HTMLCS advisory filter presets — community-curated
htmlcsIgnorelists for common frameworks - Per-engine timing in metadata — see exactly how long each engine took
- Configurable dedup strictness — loosen or tighten the merge strategy for your use case
Links
- npm: @navable/mcp
- GitHub (MCP): web-DnA/navable-web-accessibility-mcp
- GitHub (Skills): web-DnA/navable-web-accessibility-skills
