agentsclimarketplace

Scan accessibility

Skill web-DnA/navable-web-accessibility-skills/skills/scan-accessibility

Agent skills that teach AI coding agents to scan, fix, audit, and review WCAG 2.1 Level A + AA accessibility issues using the navable MCP server.

Install
npx -y skills add web-DnA/navable-web-accessibility-skills --skill scan-accessibility

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Scans a URL for WCAG 2.1 AA accessibility violations using Playwright and axe-core via the navable MCP server. Generates a prioritized fix plan with before/after code patterns and EN 301 549 mapping. Use this as the default skill for accessibility work: when the user asks to check, scan, or fix accessibility of a page or URL. (For structure-only audits, see audit-page-structure.)

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

16.2 KB, as published. Nobody here has run it

Accessibility Scan & Fix Workflow

Prerequisites

  • navable MCP server must be configured (see Step 0)
  • Playwright Chromium browser engine — installed automatically when @navable/mcp is installed. If the auto-download was skipped (restricted network or CI), run npx playwright install chromium manually. A missing browser will return a clear error with install instructions.
  • Target URL accessible on localhost (any port). External hosts require a .navable.json config with allowedHosts.

Workflow

Step 0: Ensure navable MCP Server is Configured

Check if the navable MCP server is already available by looking for an existing config:

  1. VS Code (Copilot) — check if .vscode/mcp.json exists and contains a "navable" entry
  2. Cursor — check if .cursor/mcp.json exists and contains a "navable" entry
  3. Claude Code — check if navable appears in the MCP server list

If the navable MCP server is not configured, create the config file:

For VS Code — create or update .vscode/mcp.json:

{
  "servers": {
    "navable": {
      "command": "npx",
      "args": ["-y", "@navable/mcp"]
    }
  }
}

For Cursor — create or update .cursor/mcp.json:

{
  "mcpServers": {
    "navable": {
      "command": "npx",
      "args": ["-y", "@navable/mcp"]
    }
  }
}

For Claude Code — run in terminal:

claude mcp add navable -- npx -y @navable/mcp

After creating the config, the IDE will auto-detect and start the MCP server. The @navable/mcp package is downloaded automatically via npx on first use — no separate install step needed.

If .navable-plan.json is written to the wrong directory, add the NAVABLE_PROJECT_ROOT env var to the config pointing to the project root.

Once the MCP server is available, proceed to Step 1.

Step 1: Check for Existing Plan (Resumability)

Check if .navable-plan.json exists in the project root.

  • If it exists with pending items → skip to Step 4 (resume fixing)
  • If it exists with all items done → ask user if they want to re-scan or verify
  • If it doesn't exist → proceed to Step 2

Step 2: Scan the URL

Call run_accessibility_scan with the user's URL:

run_accessibility_scan({ url: "<user-provided URL>" })

The URL can be any localhost address (e.g. http://localhost:3000, http://localhost:4200/checkout, http://127.0.0.1:8080).

Optional parameters:

  • tags — axe-core rule tags to run (default: wcag2a, wcag21a, wcag2aa, wcag21aa)
  • include — CSS selectors to scope the scan to specific regions
  • exclude — CSS selectors to skip (e.g. third-party widgets)
  • engines — Engines to run. Default: ["axe"]. Pass ["axe", "htmlcs"] for crossover validation (Pa11y/HTMLCS as a second engine). Adds ~2–4 s wall-clock per scan and grows result size by ~30–70%. Use only when the user explicitly asks for higher confidence, a compliance audit, or BFSG/EN 301 549 sign-off. For iterative fix loops, keep the default ["axe"].

The result includes a scanId field — save it for Step 3.

Note on large results: Scan output is typically 10-20 KB. Some agents write large tool results to temp files instead of displaying them inline. If the result is in a temp file, read it to extract the scanId value. You do not need to pass the full scan object to the next step.

Step 3: Generate Fix Plan

Use the scanId from Step 2 (preferred — avoids re-serializing large data):

generate_fix_plan({ scanId: "<scanId from step 2>" })

Fallback (only if the server was restarted and scanId is no longer available):

generate_fix_plan({ scan: <full_scan_output> })

This writes .navable-plan.json to the project root. The response includes planPath — the absolute path where the file was written.

If planPath points to the wrong location, set NAVABLE_PROJECT_ROOT in the MCP server config.

The plan is pre-sorted by priority:

  1. critical
  2. serious
  3. moderate
  4. minor

Do NOT reorder the plan. The server applies the correct priority sort.

Step 3b: Confirm with User Before Fixing

STOP. Do not proceed to Step 4 automatically.

Present the plan summary to the user and ask for explicit confirmation:

  • State clearly: "Scanned against WCAG 2.1 Level A + AA (50 criteria)."
  • Show the summary from the generate_fix_plan response (total items, critical/serious counts)
  • List the topItems so the user can see what will be changed
  • Ask: "Do you want me to apply these fixes now?"

Only proceed to Step 4 if the user confirms. If they decline or ask to review first, stop and wait.

This is a hard stop — never auto-apply fixes after generating the plan.

Step 4: Fix Items in Priority Order

Work through plan.items where status === "pending":

Group fixes by DOM element first

Multiple plan items often target the same element — either as separate axe nodes in a multi-node violation, or as cross-engine flags under different WCAG criteria. Editing the same element once for all its findings avoids regressions (a later fix undoing an earlier one) and cuts file reads/writes.

Two items belong in the same element bucket when both:

  1. Selectors match — identical, or one selector is a tail of the other (the longer one has > immediately before where the shorter one starts; the shorter side need not contain > itself, so img:nth-child(1) matches … > img:nth-child(1)), or they match after stripping [attribute] filters (e.g. button[type="button"] matches button). When you fall back to the attribute-stripped path, require exact HTML equality — distinct elements like input[type="checkbox"] and input[type="radio"] collapse to the same stripped selector, so any HTML divergence means they are different elements.
  2. affectedNodes[0].html snippets match — normalize whitespace (collapse runs of spaces, trim) and lowercase, then compare the first ~200 characters. The 200-char window is wide enough to catch divergence in child content (e.g. <option> text inside two different <select> elements that share their opening tag).

If selectors look similar but the HTML differs, treat them as different elements. Two <select> elements in two different forms can share the suffix form > div:nth-child(4) > select but are distinct — their <option> content disambiguates them, but only if you compare enough of the HTML.

:nth-child index drift. axe and HTMLCS occasionally disagree on :nth-child indices when there are sibling text nodes or comments. If two findings are clearly the same element but the indices differ by one, trust the HTML snippet over the selector and bucket them together.

Process per bucket:

  1. Read all fix items in the bucket and list every WCAG SC they cover.
  2. Design one minimal HTML edit that addresses every fix in the bucket.
  3. Apply the edit.
  4. Call update_fix_status with all resolved fix IDs in one call.

Example. A <select> flagged by 5 fixes (SC 3.3.2 missing label, SC 4.1.2 no name, SC 1.3.1 no programmatic label, SC 4.1.2 no value, SC 1.3.1 no <optgroup>) is one edit:

- <select>
-   <option>Choose your team size</option>
-   <option>1-10</option>
-   <option>11-50</option>
- </select>
+ <label for="team-size">Team size</label>
+ <select id="team-size" name="teamSize">
+   <option value="" disabled selected>Choose your team size</option>
+   <optgroup label="Sizes">
+     <option value="1-10">1–10</option>
+     <option value="11-50">11–50</option>
+   </optgroup>
+ </select>

Then: update_fix_status({ fixIds: ["fix-5", "fix-16", "fix-17", "fix-31", "fix-32"], status: "done" }).

For each bucket (or single-item bucket)

  1. Identify the violation category from the ruleId and load the relevant fix guide
  2. Locate the source file — use item.affectedNodes[].selector and item.affectedNodes[].html to find the component
  3. Apply the fix following the before/after pattern from the fix guide
  4. Mark it done — call update_fix_status({ fixId: "fix-1", status: "done" }) to update the plan file. This is faster and safer than editing .navable-plan.json manually.
  5. Move to the next pending item

Progress checklist (update as you go):

  • Fix critical items
  • Fix serious items
  • Fix moderate items
  • Fix minor items

Step 5: Verify Fixes

Re-scan the URL with run_accessibility_scan using the same parameters as Step 2.

  • If violations remain → report them and offer to continue fixing
  • If clean → confirm all issues resolved
  • Update plan.verification in .navable-plan.json:
    { "completedAt": "<ISO 8601>", "remainingViolations": 0, "passed": true }
    

Always add this note:

Automated scanning cannot detect every accessibility issue. Manual testing is still required for keyboard navigation flows, screen reader behavior, and cognitive load assessment.

Fix Guides by Category

Load the relevant guide when fixing a specific violation type:

CategoryGuideRules
Images & mediareferences/fix-guide-images.mdimage-alt, svg-img-alt, object-alt, input-image-alt, role-img-alt, area-alt, video-caption
Forms & labelsreferences/fix-guide-forms.mdlabel, select-name, autocomplete-valid, input-button-name
Color & contrastreferences/fix-guide-color.mdcolor-contrast, color-contrast-enhanced, link-in-text-block, css-orientation-lock
Navigation & linksreferences/fix-guide-navigation.mdlink-name, bypass, frame-title, button-name, label-content-name-mismatch, meta-viewport
Headings & structurereferences/fix-guide-headings.mdheading-order, page-has-heading-one, document-title, empty-heading, p-as-heading
Landmarks & regionsreferences/fix-guide-landmarks.mdregion, landmark-one-main
ARIA usagereferences/fix-guide-aria.mdaria-required-attr, aria-valid-attr-value, aria-allowed-attr, aria-hidden-focus, aria-allowed-role, aria-required-children, aria-required-parent, aria-roles, aria-valid-attr, duplicate-id, duplicate-id-aria
Keyboard & focusreferences/fix-guide-keyboard.mdtabindex, focus-order-semantics, keyboard, target-size, accesskeys, no-autoplay-audio, scrollable-region-focusable
Language attributesreferences/fix-guide-language.mdhtml-has-lang, html-lang-valid, valid-lang
Tables & listsreferences/fix-guide-tables.mdtd-has-header, th-has-data-cells, table-fake-caption, definition-list, dlitem, list, listitem

MCP Resources (load on demand)

  • navable://docs/fix-patterns/{ruleIds}preferred: before/after code for specific rules (e.g. navable://docs/fix-patterns/image-alt,label,color-contrast). Pass comma-separated rule IDs from the scan.
  • navable://docs/fix-patterns — all 55 rules (~49 KB). Only load if you need the full reference.
  • navable://docs/aria-patterns/{patternSlug} — single ARIA widget pattern detail
  • navable://docs/aria-patterns — index of 25 patterns (compact list)
  • navable://docs/semantic-html/{element} — single element detail
  • navable://docs/semantic-html — index of all elements (compact list)
  • navable://docs/wcag-mapping — WCAG 2.1 AA mapping table (compact)
  • navable://docs/bfsg-legal — BFSG legal context, glossary, enforcement (optional, for German compliance)

.navable-plan.json Format Reference

{
  "planId": "navable-plan-<timestamp>",
  "url": "http://localhost:3000/...",
  "items": [
    {
      "id": "fix-1",
      "ruleId": "image-alt",
      "impact": "critical",
      "priority": 1,
      "wcagSc": ["1.1.1"],
      "en301549": "9.1.1.1",
      "help": "Images must have alternate text",
      "affectedNodes": [
        { "selector": "img.hero", "html": "<img src=\"...\">", "failureSummary": "..." }
      ],
      "fixDescription": "...",
      "status": "pending",
      "appliedAt": null
    }
  ],
  "manualReview": [],
  "verification": null
}

Gotchas

  • Always use scanId for chaining. After run_accessibility_scan, pass scanId (not the full scan object) to generate_fix_plan. This avoids serialization issues with large payloads.
  • run_accessibility_scan requires a running server. The URL must be reachable. If it fails, ask the user to confirm their dev server is running.
  • CSS selectors may not map 1:1 to source files. Use html snippets from affectedNodes to locate components. Search for unique strings (class names, text content, attributes) in the codebase.
  • The plan is sorted server-side. Do not re-sort items by your own logic. Work through them in array order.
  • Use update_fix_status after each fix, not manual file edits. This ensures correct JSON formatting and enables resumability if the session is interrupted.
  • incomplete items in the scan are issues axe cannot determine automatically. They appear in plan.manualReview. Mention them to the user but do not auto-fix them.
  • Dual-engine results (when engines: ["axe", "htmlcs"]): violations include a source field ("axe" or "htmlcs"). An entry with alsoFlaggedBy: ["htmlcs"] is double-confirmed by both engines — treat as high confidence and prioritize. HTMLCS-only entries (source: "htmlcs") come with a helpUrl (WCAG Understanding doc) and developerNote (one-sentence guidance) to use in place of fix-pattern resources, since HTMLCS rule IDs don't match navable://docs/fix-patterns/*.
  • Framework detection: Check package.json for react, vue, svelte, angular to choose the right fix patterns from the guides.

Gives 0 of the 12 instructions most mcp tooling skills give

Counted across 638 of the 750 authors here whose files we hold, read 2026-08-06

  • create ten complex read-only evaluation questionsin 71 of 638, across 17 files
  • test servers using MCP Inspectorin 60 of 638, across 18 files
  • provide actionable error messagesin 56 of 638, across 14 files
  • prioritize comprehensive API coverage over specific workflowsin 54 of 638, across 12 files
  • use TypeScript and Streamable HTTP for remote serversin 53 of 638, across 7 files
  • define structured output schemas where possiblein 51 of 638, across 9 files
  • use Zod or Pydantic for input schemasin 48 of 638, across 6 files
  • fetch MCP specification pages with markdown suffixin 46 of 638, across 4 files
  • load framework documentation using WebFetchin 45 of 638, across 3 files
  • verify each evaluation answer independentlyin 45 of 638, across 3 files
  • implement API client with authentication and paginationin 45 of 638, across 3 files
  • Define input schemas with validationin 28 of 638, across 10 files

Said here and by no other author read

  • check if the navable server is configured
  • resume pending items if a plan file exists
  • run the accessibility scan
  • generate a fix plan from the scan
  • group violations by DOM element
  • fix items in priority order

Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.