Skip to main content
Glama
sitelint
by sitelint
README.md
# SiteLint Auditor MCP Server

MCP server that runs [SiteLint Auditor](https://www.sitelint.com) - WCAG and SiteLint Best Practices for accessibility, SEO, performance, and security audits via LLM agents.

The auditor bundle additionally supports [WebMCP](https://developer.chrome.com/docs/ai/webmcp): when enabled it registers in-page tools on `document.modelContext`, so browser agents can run and inspect audits directly on a live site without this server. See [WebMCP (in-page tools)](#webmcp-in-page-tools).

## Quick start

```bash
npx @sitelint/auditor-mcp
```

Requires Chromium or Chrome. The MCP server automatically detects an installed system
browser. If none is available, Puppeteer normally downloads Chrome during package
installation; if that download was skipped, it downloads Chrome for Testing on the first
audit. No browser path configuration is required.

## Tools

### `audit_url`

Audit a live URL.

```json
{
  "url": "https://example.com",
  "standards": ["wcag"],
  "auditTypes": ["accessibility"],
  "wcagLevels": ["A", "AA"],
  "wcagVersions": ["2.2"],
  "wcagCriteria": []
}
```

### `audit_html`

Audit raw HTML without fetching a URL. Defaults to `waitUntil: "load"` so image-based rules (e.g. oversized images, size calculations) see fully loaded assets. A `timeout` guards against hanging external resources — if the `load` event never fires, the audit aborts with a clear error instead of hanging. Pass `waitUntil: "domcontentloaded"` to skip slow assets entirely.

All filter parameters are **required** — pass empty arrays to skip a filter.

WCAG audit:

```json
{
  "html": "<!DOCTYPE html><html>...</html>",
  "standards": ["wcag"],
  "auditTypes": ["accessibility"],
  "wcagLevels": ["A", "AA"],
  "wcagVersions": ["2.2"],
  "wcagCriteria": ["1.1.1", "1.4.3"]
}
```

SiteLint best practices (proprietary SEO, performance, security):

```json
{
  "html": "<!DOCTYPE html><html lang=\"en\"><head><title>Test</title></head><body></body></html>",
  "standards": ["sitelint"],
  "auditTypes": ["seo", "performance", "security"],
  "wcagLevels": [],
  "wcagVersions": [],
  "wcagCriteria": []
}
```

Full audit (everything):

```json
{
  "html": "<!DOCTYPE html><html>...</html>",
  "standards": ["wcag", "sitelint"],
  "auditTypes": ["accessibility", "performance", "security", "seo"],
  "wcagLevels": ["A", "AA", "AAA"],
  "wcagVersions": ["2.0", "2.1", "2.2"],
  "wcagCriteria": []
}
```

### `check_wcag_criterion`

Check a single WCAG criterion against a URL.

```json
{
  "url": "https://example.com",
  "criterion": "1.1.1"
}
```

Returns `pass`/`fail` with violation count.

## Filter parameters

Filters are ANDed — a rule must match every provided filter to run. On `audit_url` filters are optional (omit or pass empty arrays to skip). On `audit_html` all filter parameters are **required** — pass empty arrays to skip.

| Parameter | Values | Example |
| --- | --- | --- |
| `standards` | `wcag`, `sitelint` | `["wcag"]` |
| `auditTypes` | `accessibility`, `performance`, `security`, `seo` | `["accessibility", "seo"]` |
| `wcagLevels` | `A`, `AA`, `AAA`, `best_practices` | `["A", "AA"]` |
| `wcagVersions` | `2.0`, `2.1`, `2.2` | `["2.2"]` |
| `wcagCriteria` | WCAG criterion numbers | `["1.1.1", "1.4.3"]` |

Omit a parameter (or pass empty array) to skip that filter.

## Resources

| URI | Description |
| --- | --- |
| `auditor://standards` | Supported WCAG criteria with levels |
| `auditor://report/{id}` | Full JSON report from a previous audit |

## Configuration

### Environment variables

| Variable | Default | Description |
| --- | --- | --- |
| `AUDITOR_BROWSER_PATH` | Automatic detection | Optional custom Chromium/Chrome executable path |
| `AUDITOR_CONCURRENCY` | `3` | Max concurrent audit pages (hard cap) |
| `AUDITOR_TIMEOUT` | `30000` | Navigation/render timeout (ms) |
| `AUDITOR_HEADLESS` | `true` | Set `false` to see browser |
| `AUDITOR_TRANSPORT` | `stdio` | `stdio` or `sse` |
| `AUDITOR_PORT` | `3100` | Port for SSE transport |

### SSE / HTTP transport

Run the server over Streamable HTTP instead of stdio:

```bash
AUDITOR_TRANSPORT=sse AUDITOR_PORT=3100 npm start
```

The server listens on `127.0.0.1:3100` and accepts MCP requests via `POST /`. Host and Origin headers are validated (localhost only). Graceful shutdown on SIGINT/SIGTERM closes the browser and the HTTP server.

Client config:

```json
{
  "mcpServers": {
    "sitelint-auditor": {
      "url": "http://127.0.0.1:3100"
    }
  }
}
```

### CLI flags

```cli
auditor-mcp --bundle ./custom-bundle.js --timeout 60000 --headless false
```

| Flag | Env equivalent |
| --- | --- |
| `--browser <path>` | `AUDITOR_BROWSER_PATH` |
| `--concurrency <n>` | `AUDITOR_CONCURRENCY` |
| `--timeout <ms>` | `AUDITOR_TIMEOUT` |
| `--headless <bool>` | `AUDITOR_HEADLESS` |
| `--bundle <path>` | — |
| `--transport <stdio \| sse>` | `AUDITOR_TRANSPORT` |
| `--port <n>` | `AUDITOR_PORT` |

## Integration guides

### opencode

Add to `~/.config/opencode/opencode.json`:

```json
{
  "mcp": {
    "sitelint-auditor": {
      "type": "local",
      "command": ["npx", "-y", "@sitelint/auditor-mcp"]
    }
  }
}
```

For a local build:

```json
{
  "mcp": {
    "sitelint-auditor": {
      "type": "local",
      "command": ["node", "/path/to/auditor-mcp/dist/cli.js"]
    }
  }
}
```

With custom Chromium:

```json
{
  "mcp": {
    "sitelint-auditor": {
      "type": "local",
      "command": ["npx", "-y", "@sitelint/auditor-mcp"],
      "environment": {
        "AUDITOR_BROWSER_PATH": "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
        "AUDITOR_TIMEOUT": "60000"
      }
    }
  }
}
```

### Claude Desktop

Edit `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "sitelint-auditor": {
      "command": "npx",
      "args": ["-y", "@sitelint/auditor-mcp"]
    }
  }
}
```

### Claude Code

#### Plugin (recommended)

```shell
/plugin marketplace add sitelint/auditor-mcp
/plugin install auditor-mcp@sitelint
```

#### Manual

```shell
claude mcp add sitelint-auditor -- npx -y @sitelint/auditor-mcp
```

### Codex

#### Plugin (recommended)

```shell
codex plugin marketplace add sitelint/auditor-mcp
codex plugin add auditor-mcp@sitelint
```

#### Manual

```shell
codex mcp add sitelint-auditor -- npx -y @sitelint/auditor-mcp
```

### ZCode

```json
{
  "sitelint-auditor": {
    "type": "stdio",
    "command": "npx",
    "args": [
      "-y",
      "@sitelint/auditor-mcp@latest"
    ]
  }
}
```

### VS Code (Cline)

In Cline extension settings → MCP Servers:

```json
{
  "sitelint-auditor": {
    "command": "npx",
    "args": ["-y", "@sitelint/auditor-mcp"]
  }
}
```

### VS Code (Continue)

In `~/.continue/config.json`:

```json
{
  "experimental": {
    "mcpServers": {
      "sitelint-auditor": {
        "command": "npx",
        "args": ["-y", "@sitelint/auditor-mcp"]
      }
    }
  }
}
```

### AnythingLLM

```json
{
  "mcpServers": {
    "sitelint-auditor": {
      "command": "npx",
      "args": ["-y", "@sitelint/auditor-mcp"]
    }
  }
}
```

### Other MCP clients

Any MCP client can connect. Use `stdio` transport (default) for local tools, or `AUDITOR_TRANSPORT=sse` with `AUDITOR_PORT=3100` for remote.

## Build from source

```bash
git clone <repo>
cd auditor-mcp
npm install
npm run build

# Bundle the auditor engine
cp /path/to/auditor/dist/auditor.bundle.js vendor/
cp /path/to/auditor/app/translations/en-us.json vendor/translations/
```

## Requirements

- Node.js 20+
- Chromium or Chrome (detected automatically, or downloaded by Puppeteer during
  installation/on the first audit if needed)
- SiteLint Auditor bundle (vendored as `vendor/auditor.bundle.js`)

## How it works

1. Launches headless Chromium via Puppeteer (single browser, pages capped by `AUDITOR_CONCURRENCY`)
2. Loads the target page and waits for it to settle (bounded by `AUDITOR_TIMEOUT`)
3. Injects the SiteLint Auditor JS bundle into the page
4. Runs a **single-shot audit** against the current DOM state
5. Formats results into a concise text report with grouping and truncation for long outputs
6. Stores full JSON as a resource accessible via `auditor://report/{id}`

Navigation failures, timeouts, and browser-launch errors are returned as readable messages rather than raw exceptions.

### Limitations vs. embedded auditor

When SiteLint Auditor is embedded directly into a website via `<script>`, it watches for DOM mutations, re-tests dynamically loaded content, and provides an interactive sidebar UI. The MCP server does **not** do any of that — it takes a one-time snapshot of the page at the moment of injection. Content loaded after the audit starts (lazy images, infinite scroll, SPA route transitions) is not evaluated. For SPAs or pages with heavy dynamic content, consider waiting for full render before calling the tool.

## WebMCP (in-page tools)

WebMCP turns the page itself into a tool server: the site exposes client-side functions with
JSON schemas, and a browser agent invokes them directly in the open tab. No stdio/SSE transport,
no headless browser, no server deployment.

When the auditor is embedded via `<script>` with the `webmcp` option enabled, it registers:

| Tool | Description |
| --- | --- |
| `sitelint_run_audit` | Runs a full audit of the live page; returns score and issue totals |
| `sitelint_get_reports` | Issues from the last audit with translated messages and element locators (`jsPath`, `cssSelector`, `xpath`); filters `ruleId`, `severity`, `standard`; paginated via `offset`/`limit` (default 25, max 100) |
| `sitelint_list_rules` | All registered rules with id, severity, standard and WCAG level |
| `sitelint_highlight_issue` | Scrolls to and visually highlights the element for an issue `jsPath` returned by `sitelint_get_reports` |

Enabling from page code:

```js
auditor.config({ webmcp: true });
auditor.run();
```

The flag is opt-in and defaults to `false`. Registration is feature-detected: browsers without
`document.modelContext` silently skip it and the auditor behaves exactly as before.

### When to use WebMCP instead of this server

- **Live page state** — audits SPAs, authenticated views, and content rendered after load; the
  server only snapshots the initial DOM (see *Limitations vs. embedded auditor* above).
- **Fix-and-verify loop** — the agent changes the page, re-runs `sitelint_run_audit`, and uses
  `sitelint_highlight_issue` to show the user what remains — all inside the user's tab.
- **Assistive and browser-agent workflows** — the agent and the user share one context.

### Requirements

- Chromium 146+ with WebMCP enabled (`chrome://flags/#enable-webmcp-testing` in preview builds;
  Chrome 150+ exposes the producer API on `document.modelContext`)
- Secure context (HTTPS)
- Tools are visible to same-origin consumers only; cross-origin exposure requires the `tools`
  permissions policy plus `exposedTo` at registration

WebMCP complements this server rather than replacing it: headless audits of arbitrary URLs (CI,
batch checks, sites that do not embed the auditor) stay on `@sitelint/auditor-mcp`; in-browser
agents driving a live site use the WebMCP tools.

TDQS

A3.9/5.0

Scored across 3 tools

Disambiguation4/5

audit_url and audit_html are clearly distinct by input type, but check_wcag_criterion overlaps with audit_url when filtering to a single criterion. The descriptions help differentiate them by emphasizing speed and a single-criterion focus, but minor ambiguity remains.

Naming Consistency4/5

Tool names follow a verb_noun pattern (audit_url, audit_html, check_wcag_criterion). The switch from 'audit' to 'check' is a slight inconsistency but still logical, as checking a single criterion differs from running a full audit.

Tool Count5/5

With only 3 tools, the set is tightly scoped for a specialized auditor server. Each tool serves a distinct, necessary function—URL auditing, HTML snippet auditing, and focused WCAG criterion checks—without unnecessary bloat.

Completeness4/5

The core auditing workflows are covered: auditing a live URL, auditing raw HTML, and checking a specific WCAG criterion. Minor gaps exist, such as no tool for retrieving historical audits or comparing results, but these do not block primary usage.

Maintenance

ActivityActive
ResponsivenessNo issues