a11y
Identify and test accessibility issues on websites or local development paths using axe-core and Puppeteer, ensuring web applications meet accessibility standards.
Instructions
Run accessibility tests on a URL or a local path (relative URL appended to http://localhost:5000).
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| relativePath | No | Relative path appended to http://localhost:5000 | |
| url | No | Full URL to test |
Input Schema (JSON Schema)
{
"properties": {
"relativePath": {
"description": "Relative path appended to http://localhost:5000",
"type": "string"
},
"url": {
"description": "Full URL to test",
"type": "string"
}
},
"required": [],
"type": "object"
}
Implementation Reference
- src/tools/a11y.js:18-82 (handler)The core handler function that executes the a11y tool: launches a headless browser with Puppeteer, navigates to the provided URL or localhost path, injects axe-core, runs accessibility tests, formats violations, and returns them as JSON.export async function runA11yTool(args) { // Determine final URL let finalUrl = args.url; if (!finalUrl) { if (!args.relativePath) { throw new Error("Must provide either 'url' or 'relativePath'"); } finalUrl = `http://localhost:5000/${args.relativePath.replace(/^\//, '')}`; } // Launch Puppeteer const browser = await puppeteer.launch({ headless: 'new', }); const page = await browser.newPage(); // Navigate to URL await page.goto(finalUrl); // Inject and run axe-core await page.addScriptTag({ url: 'https://cdnjs.cloudflare.com/ajax/libs/axe-core/4.7.0/axe.min.js', }); // Run axe const results = await page.evaluate(() => { return new Promise((resolve) => { axe.run((err, results) => { if (err) throw err; resolve(results); }); }); }); await browser.close(); // Format results for output const violations = results.violations.map((violation) => ({ impact: violation.impact, description: violation.description, help: violation.help, helpUrl: violation.helpUrl, nodes: violation.nodes.map((node) => ({ html: node.html, failureSummary: node.failureSummary, target: node.target, })), })); return { content: [ { type: 'text', text: JSON.stringify( { violationCount: violations.length, violations: violations, }, null, 2 ), }, ], }; }
- src/tools/a11y.js:13-16 (schema)Zod schema for validating the input arguments to the a11y tool: optional url or relativePath.export const A11yToolSchema = z.object({ url: z.string().optional(), relativePath: z.string().optional(), });
- src/index.js:31-54 (registration)Registers the a11y tool in the MCP listTools handler, providing its name, description, and input schema.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ { name: a11yToolName, description: a11yToolDescription, inputSchema: { type: 'object', properties: { url: { type: 'string', description: 'Full URL to test', }, relativePath: { type: 'string', description: 'Relative path appended to http://localhost:5000', }, }, required: [], }, }, ], }; });
- src/index.js:60-63 (registration)In the MCP callTool handler, matches on a11y tool name, validates arguments using the schema, and invokes the runA11yTool handler.case a11yToolName: { const validated = A11yToolSchema.parse(args); return await runA11yTool(validated); }
- src/tools/a11y.js:9-11 (helper)Constants for the tool name and description used in registration and handling.export const a11yToolName = 'a11y'; export const a11yToolDescription = 'Run accessibility tests on a URL or a local path (relative URL appended to http://localhost:5000).';