Back to skills
SkillHub ClubShip Full StackFull StackFrontendBackend

axe-accessibility

Accessibility testing and remediation using the axe MCP Server. Use when creating or modifying UI code (HTML, JSX, TSX, Vue, Svelte, CSS) to ensure accessibility compliance. Triggers on tasks involving web pages, components, forms, navigation, modals, tables, images, or any user-facing markup. Also use when explicitly asked to check accessibility or run an axe scan.

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,084
Hot score
99
Updated
March 20, 2026
Overall rating
C4.6
Composite score
4.6
Best-practice grade
A88.4

Install command

npx @skill-hub/cli install openclaw-skills-axe-devtools

Repository

openclaw/skills

Skill path: skills/dylanb/axe-devtools

Accessibility testing and remediation using the axe MCP Server. Use when creating or modifying UI code (HTML, JSX, TSX, Vue, Svelte, CSS) to ensure accessibility compliance. Triggers on tasks involving web pages, components, forms, navigation, modals, tables, images, or any user-facing markup. Also use when explicitly asked to check accessibility or run an axe scan.

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack, Frontend, Backend, Testing, Integration.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install axe-accessibility into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding axe-accessibility to shared team environments
  • Use axe-accessibility for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: axe-accessibility
description: Accessibility testing and remediation using the axe MCP Server. Use when creating or modifying UI code (HTML, JSX, TSX, Vue, Svelte, CSS) to ensure accessibility compliance. Triggers on tasks involving web pages, components, forms, navigation, modals, tables, images, or any user-facing markup. Also use when explicitly asked to check accessibility or run an axe scan.
---

# axe Accessibility Skill

Test web pages for accessibility violations and get AI-powered remediation guidance using the axe DevTools MCP Server.

## Prerequisites

- Docker running locally
- `AXE_API_KEY` environment variable set
- Docker image pulled: `dequesystems/axe-mcp-server:latest`

## Tools

The wrapper script at `scripts/axe-mcp.js` (Node.js — no extra dependencies) provides two tools:

### analyze

Scan a live web page for accessibility violations. Requires a URL (works with localhost).

```bash
node scripts/axe-mcp.js analyze <url>
```

Returns JSON-RPC response. The violations are in `result.content[0].text` (JSON string) under the `data` array. Each violation has: `rule`, `impact`, `description`, `selector`, `source`, `helpUrl`.

### remediate

Get AI-powered fix guidance for a specific violation. Handles HTML with quotes/brackets safely.

```bash
node scripts/axe-mcp.js remediate <ruleId> <elementHtml> <issueRemediation> [pageUrl]
```

Returns `general_description`, `remediation`, and `code_fix` in `result.content[0].text`.

### tools-list

List available MCP tools.

```bash
node scripts/axe-mcp.js tools-list
```

## Workflow

When modifying UI code and a live page is available:

1. **Analyze** — `node scripts/axe-mcp.js analyze <url>`
2. **Parse** — extract violations from the JSON response
3. **Remediate** — for each unique rule violation, call remediate with ruleId, element HTML, and issue description
4. **Apply** — implement the recommended code fixes in source
5. **Verify** — re-run analyze to confirm zero violations

When no live page is available (static code review), apply accessibility best practices directly:
- Images: `alt` text (or `alt=""` for decorative)
- Forms: inputs need associated `<label>` elements
- Interactive elements: keyboard accessible, visible focus
- Color contrast: WCAG AA (4.5:1 normal text, 3:1 large text)
- ARIA: valid, complete, not redundant with native semantics
- Headings: proper hierarchy (h1 → h2 → h3)
- Dynamic content: focus management for modals, SPAs, live regions

## Notes

- Each `remediate` call uses AI credits from your organization's allocation
- The analyze tool spins up a real browser in Docker — allow ~30s for results
- Works with localhost URLs for local development testing
> **Note**: Requires a paid Axe DevTools for Web subscription.

## Support

For technical support, bug reports, and feature requests:

- **Email**: [[email protected]](mailto:[email protected])
- **Support Portal**: [support.deque.com](https://support.deque.com)
- **[Support Guide](.github/SUPPORT.md)**

## Pricing & Sales

- **Product Page**: [deque.com/axe/mcp-server](https://www.deque.com/axe/mcp-server/)
- **Contact Sales**: [deque.com/contact](https://www.deque.com/contact)

## About Deque

[Deque Systems](https://www.deque.com) is the trusted leader in digital accessibility.

- **LinkedIn**: [Deque Systems](https://www.linkedin.com/company/deque-systems/)


---

## Referenced Files

> The following files are referenced in this skill and included for context.

### scripts/axe-mcp.js

```javascript
#!/usr/bin/env node
// axe MCP Server wrapper — sends JSON-RPC requests over Docker stdio
// Usage: node axe-mcp.js analyze <url>
//        node axe-mcp.js remediate <ruleId> <elementHtml> <issueRemediation> [pageUrl]
//        node axe-mcp.js tools-list

const { spawn } = require("child_process");

const AXE_API_KEY = process.env.AXE_API_KEY;
if (!AXE_API_KEY) {
  console.error("Error: Set AXE_API_KEY environment variable");
  process.exit(1);
}

const DOCKER_IMAGE = "dequesystems/axe-mcp-server:latest";

const INIT = JSON.stringify({
  jsonrpc: "2.0",
  id: 1,
  method: "initialize",
  params: {
    protocolVersion: "2024-11-05",
    capabilities: {},
    clientInfo: { name: "openclaw", version: "1.0" },
  },
});

const INITIALIZED = JSON.stringify({
  jsonrpc: "2.0",
  method: "notifications/initialized",
});

function sendMcp(call) {
  return new Promise((resolve, reject) => {
    const dockerArgs = [
      "run", "-i", "--rm",
      "-e", `AXE_API_KEY=${AXE_API_KEY}`,
    ];
    if (process.env.AXE_SERVER_URL) {
      dockerArgs.push("-e", `AXE_SERVER_URL=${process.env.AXE_SERVER_URL}`);
    }
    dockerArgs.push(DOCKER_IMAGE);

    const proc = spawn("docker", dockerArgs, { stdio: ["pipe", "pipe", "pipe"] });

    let stdout = "";
    let stderr = "";

    proc.stdout.on("data", (d) => (stdout += d.toString()));
    proc.stderr.on("data", (d) => (stderr += d.toString()));

    proc.on("close", (code) => {
      if (code !== 0) {
        return reject(new Error(`Docker exited with code ${code}: ${stderr}`));
      }
      // Find the response line with id:2
      const lines = stdout.trim().split("\n");
      for (const line of lines) {
        try {
          const parsed = JSON.parse(line);
          if (parsed.id === 2) return resolve(parsed);
        } catch {}
      }
      reject(new Error(`No response found. stdout: ${stdout}`));
    });

    proc.on("error", reject);

    const messages = `${INIT}\n${INITIALIZED}\n${JSON.stringify(call)}\n`;
    proc.stdin.write(messages);
    proc.stdin.end();
  });
}

async function main() {
  const [, , command, ...args] = process.argv;

  let call;

  switch (command) {
    case "analyze": {
      const url = args[0];
      if (!url) {
        console.error("Usage: axe-mcp.js analyze <url>");
        process.exit(1);
      }
      call = {
        jsonrpc: "2.0",
        id: 2,
        method: "tools/call",
        params: { name: "analyze", arguments: { url } },
      };
      break;
    }

    case "remediate": {
      const [ruleId, elementHtml, issueRemediation, pageUrl] = args;
      if (!ruleId || !elementHtml || !issueRemediation) {
        console.error(
          "Usage: axe-mcp.js remediate <ruleId> <elementHtml> <issueRemediation> [pageUrl]"
        );
        process.exit(1);
      }
      const remArgs = { ruleId, elementHtml, issueRemediation };
      if (pageUrl) remArgs.pageUrl = pageUrl;
      call = {
        jsonrpc: "2.0",
        id: 2,
        method: "tools/call",
        params: { name: "remediate", arguments: remArgs },
      };
      break;
    }

    case "tools-list": {
      call = {
        jsonrpc: "2.0",
        id: 2,
        method: "tools/list",
        params: {},
      };
      break;
    }

    default:
      console.error("Usage: axe-mcp.js {analyze|remediate|tools-list} [args...]");
      process.exit(1);
  }

  try {
    const response = await sendMcp(call);
    console.log(JSON.stringify(response, null, 2));
  } catch (err) {
    console.error(`Error: ${err.message}`);
    process.exit(1);
  }
}

main();

```



---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### _meta.json

```json
{
  "owner": "dylanb",
  "slug": "axe-devtools",
  "displayName": "Axe DevTools",
  "latest": {
    "version": "4.0.0",
    "publishedAt": 1770908892162,
    "commit": "https://github.com/openclaw/skills/commit/c84a88c8a7b57ad991780fbc7093c19069d1424a"
  },
  "history": []
}

```

axe-accessibility | SkillHub