Skip to main content
Glama
Duds

Accessibility MCP Server

by Duds
README.md
# Accessibility MCP Server

An MCP (Model Context Protocol) server that provides accessibility auditing tools for LLMs through Cursor. Integrates axe-core (via Playwright), Lighthouse CLI, and optional WAVE API to deliver deterministic, machine-actionable accessibility audit results.

## Features

- **axe-core Integration**: Automated accessibility testing via Playwright with full WCAG 2.1/2.2 coverage
- **Lighthouse CLI**: Comprehensive accessibility audits with performance insights
- **WAVE API**: Optional integration for additional accessibility validation
- **Deterministic Output**: All results normalised to explicit pass/fail/unknown outcomes
- **WCAG Compliance**: Every finding mapped to WCAG 2.1/2.2 criteria with severity classification
- **Machine-Actionable**: Results include selectors and DOM context for remediation
- **Type-Safe**: Full TypeScript implementation with strict type checking

## Installation

```bash
# Clone the repository
git clone <repository-url>
cd accessibility-mcp

# Install dependencies
npm install

# Build the project
npm run build

# Install Playwright browsers (required for axe-core)
npx playwright install chromium
```

## Configuration

Create a `.env` file in the project root (see `.env.example` for template):

```env
# WAVE API Configuration (optional)
WAVE_API_KEY=your_wave_api_key_here
WAVE_API_URL=https://wave.webaim.org/api/request

# Lighthouse Configuration (optional)
LIGHTHOUSE_TIMEOUT=60000
LIGHTHOUSE_CHROME_FLAGS=--headless --no-sandbox

# Playwright Configuration (optional)
PLAYWRIGHT_BROWSER=chromium
PLAYWRIGHT_TIMEOUT=30000
```

## Usage

### As MCP Server in Cursor

1. Build the project: `npm run build`
2. Configure in Cursor's MCP settings (`~/.cursor/mcp.json` or Cursor settings):

```json
{
  "mcpServers": {
    "accessibility": {
      "command": "node",
      "args": ["/absolute/path/to/accessibility-mcp/dist/index.js"]
    }
  }
}
```

3. Restart Cursor to load the MCP server

### Available MCP Tools

#### `axe_audit`

Run an accessibility audit using axe-core via Playwright. Supports URLs, local file paths, and localhost URLs.

**Parameters:**
- `url` (required): The URL to audit. Can be:
  - HTTP/HTTPS URL: `"https://example.com"` or `"http://localhost:3000"`
  - Local file path: `"./index.html"` or `"/path/to/file.html"`
  - File protocol URL: `"file:///path/to/file.html"`
- `options` (optional): Configuration object
  - `tags`: Array of WCAG tags (e.g., `["wcag2a", "wcag2aa"]`)
  - `rules`: Object with rule-specific configuration
  - `timeout`: Timeout in milliseconds (default: 30000)
  - `browser`: Browser to use - `"chromium"`, `"firefox"`, or `"webkit"` (default: `"chromium"`)

**Examples:**
```json
{
  "name": "axe_audit",
  "arguments": {
    "url": "https://example.com",
    "options": {
      "tags": ["wcag2a", "wcag2aa"],
      "browser": "chromium"
    }
  }
}
```

```json
{
  "name": "axe_audit",
  "arguments": {
    "url": "./src/index.html"
  }
}
```

```json
{
  "name": "axe_audit",
  "arguments": {
    "url": "http://localhost:3000"
  }
}
```

#### `lighthouse_audit`

Run an accessibility audit using Lighthouse CLI. Supports URLs, local file paths, and localhost URLs.

**Parameters:**
- `url` (required): The URL to audit. Can be:
  - HTTP/HTTPS URL: `"https://example.com"` or `"http://localhost:3000"`
  - Local file path: `"./index.html"` or `"/path/to/file.html"`
  - File protocol URL: `"file:///path/to/file.html"`
- `categories` (optional): Array of Lighthouse categories to include
- `options` (optional): Configuration object
  - `onlyCategories`: Array of categories to include
  - `skipAudits`: Array of audit IDs to skip
  - `timeout`: Timeout in milliseconds (default: 60000)

**Examples:**
```json
{
  "name": "lighthouse_audit",
  "arguments": {
    "url": "https://example.com",
    "categories": ["accessibility"]
  }
}
```

```json
{
  "name": "lighthouse_audit",
  "arguments": {
    "url": "./dist/index.html"
  }
}
```

#### `wave_audit`

Run an accessibility audit using WAVE API (requires API key). Supports URLs and localhost URLs. Local files are automatically served via a temporary local server.

**Parameters:**
- `url` (required): The URL to audit. Can be:
  - HTTP/HTTPS URL: `"https://example.com"` or `"http://localhost:3000"`
  - Local file path: `"./index.html"` (will be served via temporary server)
- `apiKey` (optional): WAVE API key (uses `WAVE_API_KEY` env var if not provided)

**Examples:**
```json
{
  "name": "wave_audit",
  "arguments": {
    "url": "https://example.com",
    "apiKey": "your_api_key"
  }
}
```

```json
{
  "name": "wave_audit",
  "arguments": {
    "url": "./src/index.html"
  }
}
```

**Note:** For local files, the MCP server automatically creates a temporary HTTP server to serve the file, as WAVE API requires HTTP/HTTPS URLs.

### Output Format

All tools return normalised results in the following format:

```typescript
{
  url: string;
  tool: 'axe' | 'lighthouse' | 'wave';
  timestamp: string;
  results: Array<{
    rule_id: string;
    wcag_ref: string[];
    severity: 'critical' | 'serious' | 'moderate' | 'minor';
    confidence: 'high' | 'medium' | 'low';
    outcome: 'pass' | 'fail' | 'unknown';
    selector: string;
    dom_context: string;
    message: string;
    reason_code?: string; // Required when outcome is 'unknown'
  }>;
  summary: {
    total: number;
    pass: number;
    fail: number;
    unknown: number;
    by_severity: {
      critical: number;
      serious: number;
      moderate: number;
      minor: number;
    };
  };
}
```

## Development

### Prerequisites

- Node.js 18.0.0 or higher
- npm or yarn

### Scripts

```bash
# Development mode (with hot reload)
npm run dev

# Build TypeScript to JavaScript
npm run build

# Run all tests
npm test

# Run unit tests only
npm run test:unit

# Run integration tests only
npm run test:integration

# Type check without building
npm run type-check

# Lint code
npm run lint
```

### Project Structure

```
accessibility-mcp/
├── .cursor/
│   ├── rules/          # Cursor behavioural constraints
│   └── commands/       # Cursor repeatable actions
├── src/
│   ├── adapters/       # External tool adapters (axe, Lighthouse, WAVE)
│   ├── services/       # Business logic (audits, normalisation)
│   ├── tools/          # MCP tool definitions
│   ├── types/          # TypeScript type definitions
│   ├── utils/          # Utility functions (WCAG mappings, selectors)
│   ├── index.ts        # Entry point
│   └── server.ts       # MCP server setup
├── tests/
│   ├── fixtures/       # Test data fixtures
│   ├── unit/           # Unit tests
│   └── integration/    # Integration tests
└── dist/               # Compiled JavaScript output
```

### Architecture

The server follows a clean architecture pattern:

1. **Tools Layer** (`src/tools/`): MCP tool definitions that expose audit capabilities
2. **Services Layer** (`src/services/`): Business logic for audit execution and result normalisation
3. **Adapters Layer** (`src/adapters/`): Interface layer for external tools (axe, Lighthouse, WAVE)
4. **Types Layer** (`src/types/`): Shared type definitions for audit results and normalised outputs

### Adding a New Audit Tool

See `.cursor/commands/add-new-audit-tool.md` for detailed instructions on adding a new accessibility audit tool.

### Testing

```bash
# Run all tests
npm test

# Run with coverage
npm test -- --coverage

# Run specific test file
npm test tests/unit/normaliser.test.ts
```

## CI/CD Integration

The project includes commands for CI/CD integration. See `.cursor/commands/ci-gate-accessibility.md` for details on setting up accessibility gates in your CI pipeline.

## Contributing

1. Follow the architectural constraints defined in `.cursor/rules/`
2. Ensure all code passes type checking: `npm run type-check`
3. Write tests for new features
4. Ensure deterministic outputs (see `.cursor/rules/determinism.md`)
5. Map all findings to WCAG criteria (see `.cursor/rules/accessibility.md`)

## License

MIT

## Acknowledgments

- [axe-core](https://github.com/dequelabs/axe-core) - Accessibility testing engine
- [Lighthouse](https://github.com/GoogleChrome/lighthouse) - Web performance and accessibility auditing
- [WAVE](https://wave.webaim.org/) - Web accessibility evaluation tool
- [Playwright](https://playwright.dev/) - Browser automation framework
- [Model Context Protocol](https://modelcontextprotocol.io/) - Protocol for LLM tool integration

TDQS

B3.2/5.0

Scored across 3 tools

Disambiguation2/5

All three tools perform accessibility audits with overlapping purposes, making them highly ambiguous. An agent would struggle to choose between axe_audit, lighthouse_audit, and wave_audit since they all audit accessibility, differ only in the underlying engine (axe-core, Lighthouse, WAVE), and have nearly identical input support (URLs, local files). This overlap creates significant confusion without clear guidance on when to use each.

Naming Consistency5/5

Tool names follow a perfectly consistent pattern: all use snake_case with the format 'engine_audit' (axe_audit, lighthouse_audit, wave_audit). This predictable naming makes it easy to understand each tool's purpose at a glance, with no deviations or mixed conventions.

Tool Count3/5

With only 3 tools, the count feels thin for an accessibility server, as it lacks broader functionality like reporting, remediation suggestions, or compliance checks. However, it's borderline reasonable for a focused audit toolset, though it could benefit from additional tools to enhance utility beyond just running audits.

Completeness2/5

The server is severely incomplete for accessibility testing, offering only audit execution without any tools for analysis, reporting, or follow-up actions. There are no tools to generate reports, track issues, suggest fixes, or validate compliance, leaving significant gaps that will hinder agents in performing comprehensive accessibility workflows.

Maintenance

ActivityInactive
ResponsivenessNo issues