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
# 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):
# 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
- Build the project:
npm run build - Configure in Cursor's MCP settings (
~/.cursor/mcp.jsonor Cursor settings):
{
"mcpServers": {
"accessibility": {
"command": "node",
"args": ["/absolute/path/to/accessibility-mcp/dist/index.js"]
}
}
}
- 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"
- HTTP/HTTPS URL:
options(optional): Configuration objecttags: Array of WCAG tags (e.g.,["wcag2a", "wcag2aa"])rules: Object with rule-specific configurationtimeout: Timeout in milliseconds (default: 30000)browser: Browser to use -"chromium","firefox", or"webkit"(default:"chromium")
Examples:
{
"name": "axe_audit",
"arguments": {
"url": "https://example.com",
"options": {
"tags": ["wcag2a", "wcag2aa"],
"browser": "chromium"
}
}
}
{
"name": "axe_audit",
"arguments": {
"url": "./src/index.html"
}
}
{
"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"
- HTTP/HTTPS URL:
categories(optional): Array of Lighthouse categories to includeoptions(optional): Configuration objectonlyCategories: Array of categories to includeskipAudits: Array of audit IDs to skiptimeout: Timeout in milliseconds (default: 60000)
Examples:
{
"name": "lighthouse_audit",
"arguments": {
"url": "https://example.com",
"categories": ["accessibility"]
}
}
{
"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)
- HTTP/HTTPS URL:
apiKey(optional): WAVE API key (usesWAVE_API_KEYenv var if not provided)
Examples:
{
"name": "wave_audit",
"arguments": {
"url": "https://example.com",
"apiKey": "your_api_key"
}
}
{
"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:
{
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
# 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:
- Tools Layer (
src/tools/): MCP tool definitions that expose audit capabilities - Services Layer (
src/services/): Business logic for audit execution and result normalisation - Adapters Layer (
src/adapters/): Interface layer for external tools (axe, Lighthouse, WAVE) - 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
# 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
- Follow the architectural constraints defined in
.cursor/rules/ - Ensure all code passes type checking:
npm run type-check - Write tests for new features
- Ensure deterministic outputs (see
.cursor/rules/determinism.md) - Map all findings to WCAG criteria (see
.cursor/rules/accessibility.md)
License
MIT
Acknowledgments
- axe-core - Accessibility testing engine
- Lighthouse - Web performance and accessibility auditing
- WAVE - Web accessibility evaluation tool
- Playwright - Browser automation framework
- Model Context Protocol - Protocol for LLM tool integration
