MCP Server
The AudioEye MCP server (@audioeye/testing-sdk-mcp) is a Model Context Protocol
server that lets an AI coding agent run an accessibility scan against a live page and propose source-level fixes. It
drives a real browser, scans the page with the AudioEye Testing SDK, attaches the JSX source location to each issue
where it can, and exposes the results to your agent as MCP tools.
Use it with MCP-capable coding agents such as Claude Code, Cursor, VS Code, and other hosts that support the Model Context Protocol.
Before you install
Complete the client-credential and package-manager setup in getting started before installing the MCP server. The server is distributed through AudioEye's private registry and is licensed at run time, so you need both your Client ID and Client Token before it will work.
Prerequisites
You will need:
- Node.js
22or24 - an AudioEye Client ID and Client Token (see getting started)
- an MCP-capable host (for example, Claude Code)
- macOS or Linux for full file-write containment (the server also runs on Windows with best-effort containment)
Step 1: Install the server
The MCP server is installed globally rather than as a project dependency. Make sure your package manager is configured
for the @audioeye registry first (see
Step 2 of getting started).
- npm
- yarn
- pnpm
npm install -g @audioeye/testing-sdk-mcp
yarn global add @audioeye/testing-sdk-mcp
pnpm add -g @audioeye/testing-sdk-mcp
This installs the audioeye-mcp command, which your MCP host runs as the server.
Step 2: Register the server with your agent
Register audioeye-mcp with your MCP host and pass your client credentials through the server's env block. This is
the standard way MCP hosts hand secrets to a server, and it keeps the credentials out of command-line arguments (which
can be visible to other processes and leak into shell history).
- Claude Code
- Cursor / VS Code / other hosts
Register the server with the claude mcp add command — no manual JSON editing required. --scope user registers it
once for every project on your machine (stored in ~/.claude.json), which is what you usually want for a globally
installed server:
claude mcp add --transport stdio \
--env AUDIOEYE_TESTING_SDK_CLIENT_ID='${AUDIOEYE_TESTING_SDK_CLIENT_ID}' \
--env AUDIOEYE_TESTING_SDK_CLIENT_TOKEN='${AUDIOEYE_TESTING_SDK_CLIENT_TOKEN}' \
--scope user audioeye -- npx -y @audioeye/testing-sdk-mcp
Keep the server name audioeye — it prefixes the tool and prompt names Claude Code displays (/mcp__audioeye__scan,
and so on).
Note the single quotes around the ${...} values: they keep your shell from expanding them, so the literal
references — not your secrets — are stored in the configuration. At launch, Claude Code's
environment-variable expansion
resolves the references from your shell environment; it works in user-scope ~/.claude.json entries the same as in a
project .mcp.json. Export the values once (see
getting started):
export AUDIOEYE_TESTING_SDK_CLIENT_ID=your-client-id-here
export AUDIOEYE_TESTING_SDK_CLIENT_TOKEN=your-client-token-here
To register for a single project instead — for example, to share the configuration with your team through a committed
.mcp.json — use --scope project in place of --scope user.
Most MCP hosts use the same shape — a server entry with a command and an env map. Add the server under the key
audioeye (keep that key — it prefixes the tool and prompt names your host displays) with your two credentials in the
env block:
{
"mcpServers": {
"audioeye": {
"command": "audioeye-mcp",
"env": {
"AUDIOEYE_TESTING_SDK_CLIENT_ID": "your-client-id-here",
"AUDIOEYE_TESTING_SDK_CLIENT_TOKEN": "your-client-token-here"
}
}
}
}
You don't have to hardcode the credentials in the env block. If AUDIOEYE_TESTING_SDK_CLIENT_ID and
AUDIOEYE_TESTING_SDK_CLIENT_TOKEN are already exported in your shell profile (~/.zshrc, ~/.bashrc, etc.) or your
CI environment, reference them with ${...} expansion instead — for example "${AUDIOEYE_TESTING_SDK_CLIENT_TOKEN}" —
which keeps the token out of committed files.
If your host does not support environment-variable expansion and you must use literal values, put the configuration in your user-level MCP settings rather than a committed project file, so the token never lands in version control.
After registering the server (or editing the configuration), reload your MCP client so it picks up the new server.
Step 3: Run the setup command (Claude Code, optional)
If your MCP host is Claude Code, run the bundled setup command from your project root. Setup takes a flag per MCP host
and only configures the hosts you name — --claude is the one supported today:
audioeye-mcp setup --claude # writes to ./.claude/ in the current project
audioeye-mcp setup --claude --global # or to ~/.claude/ for every project
For Claude Code it does one thing: allowlists AudioEye's tools by adding mcp__audioeye__* to permissions.allow
in settings.json, so the agent stops prompting for permission on every tool call. If you registered the server with
--scope user in Step 2, use the --global form so the allowlist
follows the server into every project.
The command is idempotent — re-running it is a no-op once everything is current. Reload your MCP client afterward.
Skipping this step is safe: you can always approve the tools interactively, and AudioEye's read-only tools
(audioeye_scan, audioeye_get_a11y_facts, audioeye_get_rule_metadata, audioeye_get_source_context) carry
readOnlyHint annotations per the MCP spec, so hosts that auto-approve read-only tools skip the prompt without the
allowlist.
Other hosts (Cursor, VS Code, …) don't have a setup flag yet; they need no configuration beyond registering the server.
Step 4: Verify it works
Ask your agent to scan a page. In Claude Code you can use the bundled prompt:
/mcp__audioeye__scan https://www.audioeye.com
…or prompt the agent directly: "Use the audioeye_scan tool to scan https://www.audioeye.com and summarize the failures."
A browser window opens, the scan runs, and the agent returns grouped accessibility results. If instead the tool fails
with a license message — for example
Set AUDIOEYE_TESTING_SDK_CLIENT_ID and AUDIOEYE_TESTING_SDK_CLIENT_TOKEN to run the AudioEye testing SDK. or
The AudioEye testing SDK token is invalid or inactive. — your Client ID or Client Token did not reach the server.
Re-check the env block and that the variables are exported in the environment that launched your MCP host. See
How licensing works.
Available tools
The server exposes these tools to your agent:
audioeye_open_browser— launch (or focus) a browser window with a persistent profile, so login state survives between scans.audioeye_scan— run the accessibility scan on the current page, attach a JSX source location to each failing element where possible, and return grouped results with rule metadata plus a server-renderedsummaryMarkdownreport that the agent presents verbatim — so the same scan produces the same summary on every host and every run.audioeye_get_rule_metadata— look up metadata for rule codes from an earlier scan.audioeye_get_source_context— read the lines around a source location from a previous scan.audioeye_get_a11y_facts— compute assistive-technology facts (accessible name, role, resolved ARIA attributes, nearest landmark) for an element on the current page.audioeye_verify_fix— re-scan after a fix and report whether the targeted failure is resolved.audioeye_close_browser— shut the browser down while preserving the profile.
Bundled prompts
Three prompts ship with the server, registered through the standard MCP prompts API — every host that surfaces MCP prompts exposes them automatically, with no setup step, under its own naming. In Claude Code they appear as:
/mcp__audioeye__scan(optionalurlargument) — scan a live URL and summarize the failures. No code edits./mcp__audioeye__fix— propose source-level fixes against an existing scan result. Does not run a scan./mcp__audioeye__scan-and-fix(optionalurlargument) — the full flow: scan, summarize, propose fixes (only with your approval), and verify.
Prompt updates arrive with the package (npm update) — there are no per-repo command files to maintain.
When source-level fixes are limited
The MCP server resolves a source location for failing elements in React projects running a development build. In some situations it can report a failure but cannot point to the exact line that authored it:
- Non-React projects (Vue, Svelte, Angular, plain HTML) — failures are reported without a source location.
- Production / minified builds — source mapping is limited unless your build ships source maps.
- CMS-rendered content — alt text, headings, and link names authored in a CMS live in the CMS, not your source, so the fix is a content change.
- React Server Components without
'use client'— server-rendered markup is opaque to the in-browser scan.
In these cases the scan still surfaces the issue; it just cannot always propose a code diff.
Ignoring specific issues
Real pages carry noise you can't fix at source — third-party widgets (Chargebee, Stripe, Intercom), dev-only tooling
(TanStack Router Devtools, React Query Devtools), and runtime-injected vendor iframes. You can suppress these with a
checked-in .audioeye-mcp.json at your repository root. The agent reads it on every scan and filters matching
failures out of the results before it summarizes or proposes fixes.
{
"ignore": [
{
"cssSelectorContains": "footer.TanStackRouterDevtools",
"comment": "Dev-only widget; not shipped to prod."
},
{
"ruleCode": "Iframe_Name_Missing",
"cssSelectorContains": "iframe#cb-master-frame",
"comment": "Vendor SDK iframe — vendor-owned."
},
{
"fileNameContains": "node_modules/",
"comment": "Don't try to patch dependencies."
}
]
}
Each entry under ignore is a matcher with one or more of these optional fields:
| Field | Matches when… |
|---|---|
ruleCode | the failing rule code equals this value exactly |
cssSelectorPrefix | the element's CSS selector starts with this string |
cssSelectorContains | the element's CSS selector contains this string |
fileNamePrefix | the resolved source file path starts with this string |
fileNameContains | the resolved source file path contains this string |
comment | (not a matcher) free-text note explaining why the entry exists |
An entry must specify at least one matcher field. Fields within an entry are AND'd (all must match); separate
entries are OR'd (an issue matching any entry is suppressed). Every scan response reports configPath, totalIgnored,
and per-rule hit counts, so reviewers can audit exactly what was filtered.
The agent manages this file for you: when it notices noise you repeatedly dismiss, it suggests an ignore entry — but
it treats .audioeye-mcp.json like source code and won't write to it without your approval. Because the file is checked
in, the same suppressions apply for every developer and in CI.
By default the server looks for .audioeye-mcp.json (or audioeye-mcp.config.json) by walking up from the workspace
root. Set AUDIOEYE_MCP_CONFIG_PATH to point at a config file in a non-standard location.
Troubleshooting
Scans fail with a license message
If the tool fails with
Set AUDIOEYE_TESTING_SDK_CLIENT_ID and AUDIOEYE_TESTING_SDK_CLIENT_TOKEN to run the AudioEye testing SDK. or
The AudioEye testing SDK token is invalid or inactive., the server could not verify your license. Confirm that:
- the
envblock in your MCP configuration containsAUDIOEYE_TESTING_SDK_CLIENT_IDandAUDIOEYE_TESTING_SDK_CLIENT_TOKEN - if you use
${...}expansion, those variables are exported in the environment that launched your MCP host - your Client Token has not been revoked by a refresh in the portal
See How licensing works for details on the license check and the 24-hour offline window.
The server is not listed in my agent
Reload your MCP client after editing the configuration, and confirm the audioeye-mcp command is on your PATH
(which audioeye-mcp). If the global install did not add it to your PATH, reinstall with your package manager's
global flag and reopen your terminal.
Other issues
For registry, credential, and browser-runtime problems shared with the rest of the SDK, see the main Troubleshooting guide.