Skip to main content
Glama
allchemylabs

@allchemylabs/aether-wcag-scanner

Official
by allchemylabs

Aether WCAG Scanner

A Claude Code plugin that finds WCAG 2.1 AA accessibility violations and returns ready-to-apply fixes — not just a list of problems.

It drives a real browser (Playwright + axe-core) across desktop, tablet, and mobile viewports, then pairs each violation with a concrete fix: corrected HTML, the relevant WCAG success criteria, and technique code examples.


Why it's different

Plain Claude Code can guess at accessibility issues by reading your markup. This plugin actually runs your page and grounds every fix in the WCAG spec.

Plain Claude Code

Aether (offline)

Aether (with API key)

Detection

Eyeballs the HTML it can see

Real browser + axe-core, all viewports

Real browser + axe-core, all viewports

Coverage

Misses computed/runtime issues

Catches contrast, ARIA, focus, names

Same

Fixes

Generic suggestions

Built-in fix templates

RAG-backed fixes + WCAG technique code

Grounding

None

Rule IDs + severity

Cited success criteria + techniques

Works offline

n/a

Yes

Falls back to offline automatically

The scanner degrades gracefully: with no API key (or when offline or rate-limited) it still returns template-based fixes for every violation. Add an API key and the same violations come back with corpus-grounded fixes and WCAG technique snippets.


Related MCP server: Accessibility MCP Server

Install

/plugin marketplace add https://github.com/allchemylabs/claude-plugins.git
/plugin install aether-wcag-scanner@allchemylabs

Once the official Claude Code marketplace listing is live, you can also install it directly from there.

The install prompts for your Allchemy Labs API key; paste the key you got from beta.allchemylabs.ai. To set or change it later:

/plugin configure aether-wcag-scanner@allchemylabs

The first start installs the plugin's dependencies (about a minute) and the first scan downloads Chromium for Playwright. If /mcp shows the server as not connected right after install, wait a moment and run /reload-plugins.

Running without a key

The scanner itself runs locally and works without a key: you get template fixes for every violation. The key adds corpus-grounded fixes from the hosted insights engine. Set it via the prompt above, or put ALLCHEMY_API_KEY=<key> in the .env of the project you are scanning.


Use it outside Claude Code (any MCP client)

The same server is published to npm and the MCP Registry as @allchemylabs/aether-wcag-scanner. Any MCP client that speaks stdio can run it:

{
  "mcpServers": {
    "aether-wcag-scanner": {
      "command": "npx",
      "args": ["-y", "@allchemylabs/aether-wcag-scanner"],
      "env": { "ALLCHEMY_API_KEY": "<your beta key>" }
    }
  }
}

The first scan downloads Chromium once (about 150 MB). Without ALLCHEMY_API_KEY the scanner still runs fully offline and returns template fixes.

The 5 tools

Tool

What it does

aether_scan_and_fix

Recommended. Scan a URL — or a single-page app across routes via the spa block — and return violations with fixes, each verified on the real browser, in one call. Set maxFixes: 0 for a fast scan-only pass.

aether_get_fix

Get a fix for one specific violation (verified on the real browser). Omit html to instead get a rule-level explanation — WCAG success criteria and technique examples.

aether_verify_fix

Deterministically verify a fix with real Playwright + axe — re-scan a URL or diff original vs fixed HTML. Reports whether the target cleared, any new regressions, and the net compliance delta.

aether_check_html

Analyze an HTML snippet for issues — no live URL or browser needed.

aether_submit_feedback

Rate a fix (useful / not useful) so the guidance engine keeps improving; your correction helps seed better fixes.

Just ask Claude naturally, e.g. "check localhost:3000 for accessibility issues and fix them" — it will pick the right tool.

The /wcag-scan skill

Run /wcag-scan <url> for a guided workflow: scan → review violations → apply fixes → re-scan to verify → summarize. The skill orchestrates the tools above and edits your files in place.


Scanning single-page apps

Pass a spa block to aether_scan_and_fix instead of url:

{ "spa": { "entryUrl": "http://localhost:4200", "framework": "angular", "maxRoutes": 10 } }
  • entryUrl — where the app boots. Routes are discovered by crawling client-side links unless you list them in routes: [{ "path": "/settings", "name": "Settings" }].

  • frameworkangular, react, vue, or omit to auto-detect.

  • maxRoutes — cap on discovered routes.

Navigation is client-side (the browser context and app state are kept between routes), and readiness is decided by a layered stability cascade — DOM quiet, framework hooks such as Angular testability, pending-request drain — never by Playwright's networkidle, which deadlocks on apps with long-polling or websockets. A config that sets networkIdle is rejected for that reason.

Requirements

  • Node.js >= 20

  • Chromium (installed automatically on first run)

Disclaimer

Aether is an accessibility analysis and guidance tool. Using the platform does not, by itself, make your website, application, or digital service conformant with WCAG, the ADA (including Title II), the European Accessibility Act, Section 508, EN 301 549, or any other accessibility law or standard.

Automated scans detect only a subset of accessibility barriers. A "zero issues" result means the scanner did not flag anything in its detection range — not that the property is legally compliant.

You remain responsible for:

  • reviewing findings with qualified people

  • fixing issues in the underlying code and content

  • conducting or commissioning manual testing and audits as needed

  • maintaining accessibility as the product changes

  • obtaining legal advice for your specific obligations

Aether does not provide legal advice and does not replace an accessibility audit or a VPAT/ACR prepared by a qualified auditor.

License

MIT for the client (this plugin). The hosted insights engine and related Allchemy Labs services are proprietary — see LICENSE and NOTICE.

Available Tools

5 tools
aether_check_htmlA

Analyze an HTML snippet for WCAG accessibility issues without needing a live URL or browser. Uses static heuristic checks and optionally enriches results with RAG-powered fixes. Use this when a developer pastes HTML or asks about a component's accessibility.

ParametersJSON Schema
NameRequiredDescriptionDefault
htmlYesThe HTML to check for accessibility issues
contextNoAdditional context about where this HTML lives (e.g. "navigation bar", "login form")

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

There are no annotations, so the description must carry the behavioral burden. It usefully discloses static heuristic checks, no live URL/browser requirement, and optional RAG-powered fixes, but it does not clarify whether RAG enrichment triggers external calls, how 'optional' is controlled, or what the output shape is. That leaves a noticeable gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each with a distinct job: definition, method, and usage. It is front-loaded with the core purpose and contains no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 2-parameter read-only check with a fully documented schema, the description covers what the tool does, how (static heuristics, optional RAG), and when to use it. It slightly falters by not describing the return shape or the precise trigger for RAG enrichment, but nothing needed to invoke it successfully is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both html and context. The free-text description does not add detail about parameter format or edge cases, giving the baseline score of 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence names a specific verb ('Analyze'), a concrete resource ('an HTML snippet'), and an explicit goal ('WCAG accessibility issues'). It also distinguishes itself from live-scanning siblings by stating it works without a live URL or browser.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The last sentence gives direct usage guidance: use it when a developer pastes HTML or asks about a component's accessibility. It does not explicitly name sibling tools or say when not to use them, so it misses the top tier.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aether_get_fixA

Get a RAG-powered fix OR explanation for a WCAG violation. Pass html (the failing element) to get a concrete fixHtml plus a measured verification. Omit html to get a rule-level explanation (WCAG success criteria, technique code examples, failure patterns, and fix guidance). Requires ALLCHEMY_API_KEY for RAG output; falls back to templates without it.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoURL where the violation was found (context only; not navigated to)
htmlNoThe failing HTML element's outerHTML. Omit to get a rule-level explanation instead of an element-specific fix.
ruleIdYesAxe-core rule ID (e.g. "button-name", "image-alt", "color-contrast")
verifyNoRe-run real axe on original vs fixed HTML to measure whether the fix works (default true). Ignored in explanation mode.
parentHtmlNoParent element's outerHTML for context
siblingHtmlNoSibling elements' opening tags (tight lockups) — lets contrast flag logo-adjacent text
childrenHtmlNoChildren innerHTML for context
failureSummaryNoAxe's failureSummary string

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the burden of behavioral disclosure. It reveals RAG dependence, API key requirements, template fallback, and the verify-only-in-fix-mode behavior. This is substantial, though it does not disclose response shape details or potential error/rate-limit behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly written sentences front-load the purpose, then explain the mode switch, then disclose the credential dependency. There is no filler, and each sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the eight-parameter schema, high schema coverage, and absence of an output schema, the description covers the key behavioral branches and dependencies. It could be slightly more specific about the exact response shape, but it explains both modes and the key constraint, making it sufficient for an agent to select and call the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds meaningful parameter-interaction semantics: html omission switches modes institution, and verify is 'Ignored in explanation mode.' This goes beyond a simple restatement of schema fields.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Get a RAG-powered fix OR explanation for a WCAG violation.' It clearly distinguishes the two operating modes (fix with html, explanation without) and is semantically distinct from siblings like aether_check_html and aether_verify_fix.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit conditional guidance: 'Pass html ... to get a concrete fixHtml' versus 'Omit html to get a rule-level explanation.' It also notes the ALLCHEMY_API_KEY requirement and fallback behavior. No explicit comparison with sibling tools is provided, but the mode-based guidance is clear enough for correct invocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aether_scan_and_fixA

Scan a URL (or a multi-route SPA via the spa block) for WCAG 2.1 AA accessibility violations AND generate RAG-powered fixes in one call. Returns violations paired with fixHtml, explanations, and WCAG technique references. Set maxFixes:0 for a fast scan-only pass. This is the recommended tool for accessibility auditing — use it when a developer asks to check or fix accessibility.

ParametersJSON Schema
NameRequiredDescriptionDefault
spaNoScan a Single-Page Application across multiple routes instead of a single URL. Presence of this block selects SPA mode. Mutually exclusive with `url`.
urlNoSingle-page target URL (e.g. http://localhost:3000). Provide this OR `spa`, not both.
maxFixesNoMaximum number of violations to generate fixes for (default 10). Set 0 for a scan-only pass (no RAG calls).
viewportNoSingle-page mode only: viewport(s) to report. "all" scans desktop, tablet, and mobile.all
minSeverityNoMinimum severity to include (default "moderate")moderate
verifyFixesNoRe-run real axe on each generated fix (original vs fixed HTML) to measure whether it works (default true)

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses the main behavior: scanning, RAG-powered fix generation, return data (violations paired with fixHtml, explanations, WCAG references), and the effect of maxFixes:0 and verifyFixes. It does not confirm whether the operation is read-only or requires special permissions, but for a scanner this is a strong disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each with a purpose: the first states the core action, the second names the return artifacts, the third gives a fast-path tip, and the fourth provides routing guidance. The most important information is front-loaded, and there is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the moderate complexity of 6 params and a nested spa object, the description covers the essential decision points: what it does, what it returns, the scan-only option, and when to choose it. No output schema exists, but the description lists the key fields returned, making it complete enough for an agent to call it correctly. It could mention that url and spa are mutually exclusive, but the schema already does.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds context about the 'one-call' combined mode and mentions maxFixes:0 for scan-only, but the schema already documents that. It doesn't materially expand on the url/spa interaction beyond what the schema descriptions state.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb-resource pair: scan a URL or SPA for WCAG 2.1 AA violations and generate RAG-powered fixes in one call. It also includes the output shape (violations with fixHtml, explanations, technique references), which clearly distinguishes it from siblings like aether_check_html or aether_get_fix.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly recommends this tool for accessibility auditing and tells the agent to use it when a developer asks to check or fix accessibility. It also provides a concrete alternative within the same tool (maxFixes:0 for scan-only). It doesn't explicitly name sibling tools or describe when NOT to use it, but the primary recommendation is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aether_submit_feedbackA

Submit developer feedback on a previously returned WCAG fix/artifact, keyed by its finding_id. Records a rating plus an optional reason_code and the code the developer actually shipped, so the fix pipeline can learn from misses. Requires ALLCHEMY_API_KEY.

ParametersJSON Schema
NameRequiredDescriptionDefault
ratingYesWhether the fix/guidance was useful
scanIdNoThe scan_id the finding belonged to
ratedByNoRole/persona (not PII)
freeTextNoOptional free-form note
versionsNoVersion stamps echoed from the artifact for attribution
findingIdYesThe finding_id of the artifact the rating targets (from a scan/fix result)
reasonCodeNoWhy the fix missed: wrong_fix | didnt_apply | broke_something | unclear | wrong_technique | other
developerCorrectionNoThe code the developer actually shipped (becomes raw material for a new template)

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral disclosure burden. It usefully reveals the write-like side effect (records rating, reason_code, shipped code, feeds learning pipeline) and mentions the required API key. It does not disclose whether feedback can overwrite prior feedback, idempotency behavior, or error/return behavior, so it is adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with no filler. The core action and key are front-loaded in the first sentence, the briefly important learning context and API key requirement follow in the second. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation-like tool with no output schema and no annotations, the description covers the essential operational context: what it does, what records, the required key, and the intent behind submission. It could additionally explain where finding_id comes from or how failures surface, but the schema already handles the parameter details and the core call scenario is clear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema fully documents all eight parameters. The description adds a small amount of connective context by calling out rating, reason_code, and developerCorrection as the key recorded fields, but it does not meaningfully supplement the existing per-parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb ('Submit') and resource ('developer feedback on a previously returned WCAG fix/artifact') and anchors it to a concrete key ('finding_id'). It clearly differentiates this from the sibling scan/fix/verify tools by focusing on post-fix feedback rather than performing scans or fixes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is used after a fix/artifact has been returned, and notes it is meant to help the pipeline learn from misses. However, it does not explicitly state when not to use it or name sibling alternatives as fallbacks, leaving the timing context inferable rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

aether_verify_fixA

Deterministically verify a WCAG fix with the real Playwright + axe-core engine. URL mode re-scans a live page; snippet mode diffs original vs fixed HTML before deploy. Returns MEASURED facts: targetCleared, newViolations (regressions), resolvedViolations, and complianceDelta. This is the authoritative "did the fix work?" signal.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoLive/deployed URL to re-scan (URL mode; preferred when a URL exists)
ruleIdYesAxe-core rule ID the fix was meant to resolve (e.g. "button-name")
baselineNoURL mode: pre-fix violation set for a full new/resolved delta (max 5000 entries)
fixedHtmlNoFixed HTML to verify (snippet mode; requires originalHtml)
originalHtmlNoOriginal failing HTML (snippet mode; requires fixedHtml)

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden. It discloses determinism, the engine used, and the specific returned metrics. It does not mention side effects (e.g., network requests, runtime, rate limits) or explicitly state it is read-only, which would be expected for a verification tool. The description is adequate but not comprehensive.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with zero fluff. It front-loads the purpose, then modes, then outputs. Every sentence contributes meaning, making it highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of 5 parameters and two modes, the description covers modes, required parameter relationships, and return fields. It leaves ambiguity about what happens if both url and fixedHtml are provided simultaneously, and whether baseline is mandatory for a delta in URL mode (schema marks it optional). These minor gaps prevent a perfect score.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds value by explaining the mode-dependent roles of parameters: url for URL mode, fixedHtml/originalHtml for snippet mode, and baseline for delta calculation. This clarifies relationships beyond the schema's individual descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('verify'), resource ('WCAG fix'), and engine ('Playwright + axe-core'). It clearly distinguishes itself from siblings by claiming to be the authoritative 'did the fix work?' signal, and outlines two distinct modes (URL and snippet) with measurable outputs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear guidance on when to use each mode (URL preferred when a URL exists; snippet for pre-deploy diffing) and explains the purpose of the tool as post-fix verification. However, it does not explicitly compare with sibling tools like aether_check_html or aether_scan_and_fix, leaving the selection among them to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv1.0.0
    • First observedaether_check_html
    • First observedaether_get_fix
    • First observedaether_scan_and_fix
    • First observedaether_submit_feedback
    • First observedaether_verify_fix

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool addresses a distinct phase of the accessibility workflow: analyzing static HTML, scanning/fixing a URL, retrieving fixes/explanations, verifying fixes, and submitting feedback. There is no overlap or ambiguity between their purposes.

Naming Consistency4/5

All tools share the 'aether_' prefix and mostly follow a verb_noun pattern (check_html, get_fix, verify_fix, submit_feedback). The exception is 'scan_and_fix', which uses a compound verb phrase, but this is still clear and consistent in style.

Tool Count5/5

With 5 tools, the server covers the full lifecycle of accessibility auditing and remediation without bloat. Each tool is necessary and earns its place, making the count well-scoped for the domain.

Completeness5/5

The tool surface covers analysis, scanning with optional fixes, retrieval of detailed fix guidance, verification of applied fixes, and feedback collection. There are no obvious missing operations for the intended workflow.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers