Skip to main content
Glama

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

TableJSON Schema
NameRequiredDescriptionDefault
relativePathNoRelative path appended to http://localhost:5000
urlNoFull URL to test

Implementation Reference

  • 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
            ),
          },
        ],
      };
    }
  • 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);
    }
  • 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).';
Behavior2/5

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

No annotations are provided, so the description carries full burden. It mentions the local path behavior (appended to localhost:5000), which is useful, but doesn't disclose critical behavioral traits like what the tests actually do, whether they're destructive, what permissions are needed, rate limits, or output format. This leaves significant gaps for an agent.

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 a single, efficient sentence that front-loads the core purpose and includes essential details without any wasted words. Every element serves a clear purpose in conveying the tool's functionality.

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

Completeness2/5

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

Given no annotations and no output schema, the description is incomplete for a testing tool. It doesn't explain what accessibility tests are run, what the results look like, error conditions, or behavioral constraints. This leaves the agent with insufficient context to use the tool effectively.

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 parameters fully. The description adds marginal value by clarifying the local path behavior (appended to localhost:5000), but doesn't provide additional syntax, format details, or usage examples beyond what the schema states.

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 clearly states the specific action ('Run accessibility tests') and the target resources ('on a URL or a local path'), with no siblings to distinguish from. It uses precise verbs and identifies the exact scope of operation.

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 usage context by specifying the two input types (URL or local path), but doesn't provide explicit guidance on when to choose one over the other or mention any prerequisites. With no sibling tools, this is adequate but lacks detailed decision criteria.

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

Install Server

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/westsideori/cursor-a11y-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server