@dallask/a11y-mcp-srv 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/NOTICE +9 -0
- package/README.md +1311 -0
- package/bin/server.js +8 -0
- package/dist/core/accessibility-runner.d.ts +115 -0
- package/dist/core/accessibility-runner.d.ts.map +1 -0
- package/dist/core/accessibility-runner.js +419 -0
- package/dist/core/accessibility-runner.js.map +1 -0
- package/dist/core/config.d.ts +42 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +159 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/error-handler.d.ts +61 -0
- package/dist/core/error-handler.d.ts.map +1 -0
- package/dist/core/error-handler.js +264 -0
- package/dist/core/error-handler.js.map +1 -0
- package/dist/core/progress-streamer.d.ts +44 -0
- package/dist/core/progress-streamer.d.ts.map +1 -0
- package/dist/core/progress-streamer.js +160 -0
- package/dist/core/progress-streamer.js.map +1 -0
- package/dist/core/result-processor.d.ts +69 -0
- package/dist/core/result-processor.d.ts.map +1 -0
- package/dist/core/result-processor.js +461 -0
- package/dist/core/result-processor.js.map +1 -0
- package/dist/core/session-manager.d.ts +73 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +243 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +1298 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/aggregate.d.ts +26 -0
- package/dist/tools/aggregate.d.ts.map +1 -0
- package/dist/tools/aggregate.js +308 -0
- package/dist/tools/aggregate.js.map +1 -0
- package/dist/tools/analysis.d.ts +68 -0
- package/dist/tools/analysis.d.ts.map +1 -0
- package/dist/tools/analysis.js +1232 -0
- package/dist/tools/analysis.js.map +1 -0
- package/dist/tools/audit.d.ts +38 -0
- package/dist/tools/audit.d.ts.map +1 -0
- package/dist/tools/audit.js +422 -0
- package/dist/tools/audit.js.map +1 -0
- package/dist/tools/comparison.d.ts +27 -0
- package/dist/tools/comparison.d.ts.map +1 -0
- package/dist/tools/comparison.js +488 -0
- package/dist/tools/comparison.js.map +1 -0
- package/dist/tools/export.d.ts +43 -0
- package/dist/tools/export.d.ts.map +1 -0
- package/dist/tools/export.js +729 -0
- package/dist/tools/export.js.map +1 -0
- package/dist/tools/filter.d.ts +26 -0
- package/dist/tools/filter.d.ts.map +1 -0
- package/dist/tools/filter.js +227 -0
- package/dist/tools/filter.js.map +1 -0
- package/dist/tools/session.d.ts +26 -0
- package/dist/tools/session.d.ts.map +1 -0
- package/dist/tools/session.js +227 -0
- package/dist/tools/session.js.map +1 -0
- package/dist/tools/visualize.d.ts +26 -0
- package/dist/tools/visualize.d.ts.map +1 -0
- package/dist/tools/visualize.js +946 -0
- package/dist/tools/visualize.js.map +1 -0
- package/dist/types/index.d.ts +755 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +57 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,1298 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Main MCP server entry point
|
|
3
|
+
* Accessibility MCP Server
|
|
4
|
+
*/
|
|
5
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
7
|
+
import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
|
|
8
|
+
// Import tool implementations
|
|
9
|
+
import { auditUrl } from './tools/audit.js';
|
|
10
|
+
import { auditMultipleUrls } from './tools/audit.js';
|
|
11
|
+
import { createSession } from './tools/session.js';
|
|
12
|
+
import { auditWithSession } from './tools/session.js';
|
|
13
|
+
import { getAccessibilityScore } from './tools/analysis.js';
|
|
14
|
+
import { prioritizeIssues } from './tools/analysis.js';
|
|
15
|
+
import { explainIssue } from './tools/analysis.js';
|
|
16
|
+
import { getQuickFixes } from './tools/analysis.js';
|
|
17
|
+
import { generateComplianceReport } from './tools/analysis.js';
|
|
18
|
+
import { getWCAGCompliance } from './tools/analysis.js';
|
|
19
|
+
import { compareAccessibility } from './tools/comparison.js';
|
|
20
|
+
import { trackAccessibility } from './tools/comparison.js';
|
|
21
|
+
import { exportToCsv } from './tools/export.js';
|
|
22
|
+
import { exportToExcel } from './tools/export.js';
|
|
23
|
+
import { exportToJson } from './tools/export.js';
|
|
24
|
+
import { exportToHtmlReport } from './tools/export.js';
|
|
25
|
+
import { filterIssues } from './tools/filter.js';
|
|
26
|
+
import { searchIssues } from './tools/filter.js';
|
|
27
|
+
import { aggregateAuditResults } from './tools/aggregate.js';
|
|
28
|
+
import { getStatistics } from './tools/aggregate.js';
|
|
29
|
+
import { generateDashboard } from './tools/visualize.js';
|
|
30
|
+
import { generateSummaryReport } from './tools/visualize.js';
|
|
31
|
+
// Import error handling and progress utilities
|
|
32
|
+
import { handleErrorGracefully, retryWithBackoff, formatErrorMessage, } from './core/error-handler.js';
|
|
33
|
+
import { formatTimeRemaining } from './core/progress-streamer.js';
|
|
34
|
+
/**
|
|
35
|
+
* Create and configure the MCP server
|
|
36
|
+
*/
|
|
37
|
+
async function createServer() {
|
|
38
|
+
const server = new Server({
|
|
39
|
+
name: 'accessibility-audit',
|
|
40
|
+
version: '1.0.0',
|
|
41
|
+
}, {
|
|
42
|
+
capabilities: {
|
|
43
|
+
tools: {},
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
// Register tool handlers
|
|
47
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
48
|
+
const tools = [
|
|
49
|
+
{
|
|
50
|
+
name: 'audit_url',
|
|
51
|
+
description: 'Test a single URL for accessibility issues. Returns structured, conversational results with prioritized issues and fix suggestions.',
|
|
52
|
+
inputSchema: {
|
|
53
|
+
type: 'object',
|
|
54
|
+
properties: {
|
|
55
|
+
url: {
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: 'Full URL or relative path to test. If relative, domain must be provided.',
|
|
58
|
+
},
|
|
59
|
+
domain: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
description: 'Base domain if URL is relative (e.g., "https://example.com").',
|
|
62
|
+
},
|
|
63
|
+
tags: {
|
|
64
|
+
type: 'array',
|
|
65
|
+
items: {
|
|
66
|
+
type: 'string',
|
|
67
|
+
enum: [
|
|
68
|
+
'wcag2a',
|
|
69
|
+
'wcag2aa',
|
|
70
|
+
'wcag2aaa',
|
|
71
|
+
'wcag21a',
|
|
72
|
+
'wcag21aa',
|
|
73
|
+
'wcag21aaa',
|
|
74
|
+
'wcag22a',
|
|
75
|
+
'wcag22aa',
|
|
76
|
+
'wcag22aaa',
|
|
77
|
+
'best-practice',
|
|
78
|
+
],
|
|
79
|
+
},
|
|
80
|
+
description: 'Specific accessibility tags to check. If not provided, tags from env WCAG_LEVEL and BEST_PRACTICES are used.',
|
|
81
|
+
},
|
|
82
|
+
engine: {
|
|
83
|
+
type: 'string',
|
|
84
|
+
enum: ['axe', 'ace'],
|
|
85
|
+
description: 'Testing engine: "axe" (axe-core, default) or "ace" (IBM Equal Access). Overrides env A11Y_ENGINE when provided.',
|
|
86
|
+
},
|
|
87
|
+
waitForLoad: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
enum: ['networkidle', 'load', 'domcontentloaded'],
|
|
90
|
+
default: 'networkidle',
|
|
91
|
+
description: 'Wait strategy for page loading.',
|
|
92
|
+
},
|
|
93
|
+
timeout: {
|
|
94
|
+
type: 'number',
|
|
95
|
+
default: 30,
|
|
96
|
+
description: 'Timeout in seconds (default: 30).',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
required: ['url'],
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'audit_multiple_urls',
|
|
104
|
+
description: 'Test multiple URLs efficiently with optional parallel processing and progress tracking.',
|
|
105
|
+
inputSchema: {
|
|
106
|
+
type: 'object',
|
|
107
|
+
properties: {
|
|
108
|
+
urls: {
|
|
109
|
+
oneOf: [
|
|
110
|
+
{
|
|
111
|
+
type: 'array',
|
|
112
|
+
items: { type: 'string' },
|
|
113
|
+
description: 'Array of URLs to test.',
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
type: 'string',
|
|
117
|
+
description: 'Comma-separated string of URLs to test.',
|
|
118
|
+
},
|
|
119
|
+
],
|
|
120
|
+
description: 'URLs to test (array or comma-separated string).',
|
|
121
|
+
},
|
|
122
|
+
domain: {
|
|
123
|
+
type: 'string',
|
|
124
|
+
description: 'Base domain if URLs are relative (e.g., "https://example.com").',
|
|
125
|
+
},
|
|
126
|
+
parallel: {
|
|
127
|
+
type: 'number',
|
|
128
|
+
default: 1,
|
|
129
|
+
description: 'Number of parallel tests to run (default: 1).',
|
|
130
|
+
},
|
|
131
|
+
continueOnError: {
|
|
132
|
+
type: 'boolean',
|
|
133
|
+
default: true,
|
|
134
|
+
description: 'Continue processing if one URL fails (default: true).',
|
|
135
|
+
},
|
|
136
|
+
tags: {
|
|
137
|
+
type: 'array',
|
|
138
|
+
items: {
|
|
139
|
+
type: 'string',
|
|
140
|
+
enum: [
|
|
141
|
+
'wcag2a',
|
|
142
|
+
'wcag2aa',
|
|
143
|
+
'wcag2aaa',
|
|
144
|
+
'wcag21a',
|
|
145
|
+
'wcag21aa',
|
|
146
|
+
'wcag21aaa',
|
|
147
|
+
'wcag22a',
|
|
148
|
+
'wcag22aa',
|
|
149
|
+
'wcag22aaa',
|
|
150
|
+
'best-practice',
|
|
151
|
+
],
|
|
152
|
+
},
|
|
153
|
+
description: 'Specific accessibility tags to check. Applied to all URLs. If not provided, env WCAG_LEVEL and BEST_PRACTICES are used.',
|
|
154
|
+
},
|
|
155
|
+
engine: {
|
|
156
|
+
type: 'string',
|
|
157
|
+
enum: ['axe', 'ace'],
|
|
158
|
+
description: 'Testing engine: "axe" or "ace". Overrides env A11Y_ENGINE when provided.',
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
required: ['urls'],
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: 'create_session',
|
|
166
|
+
description: 'Create a reusable authenticated session by logging into a website. The session can be reused for multiple audits of protected pages.',
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: 'object',
|
|
169
|
+
properties: {
|
|
170
|
+
domain: {
|
|
171
|
+
type: 'string',
|
|
172
|
+
description: 'Base domain (e.g., "https://example.com" or "example.com").',
|
|
173
|
+
},
|
|
174
|
+
loginUrl: {
|
|
175
|
+
type: 'string',
|
|
176
|
+
description: 'Custom login URL. If not provided, defaults to {domain}/login.',
|
|
177
|
+
},
|
|
178
|
+
username: {
|
|
179
|
+
type: 'string',
|
|
180
|
+
description: 'Login username.',
|
|
181
|
+
},
|
|
182
|
+
password: {
|
|
183
|
+
type: 'string',
|
|
184
|
+
description: 'Login password.',
|
|
185
|
+
},
|
|
186
|
+
loginSelectors: {
|
|
187
|
+
type: 'object',
|
|
188
|
+
properties: {
|
|
189
|
+
usernameSelector: {
|
|
190
|
+
type: 'string',
|
|
191
|
+
description: 'CSS selector for username input field.',
|
|
192
|
+
},
|
|
193
|
+
passwordSelector: {
|
|
194
|
+
type: 'string',
|
|
195
|
+
description: 'CSS selector for password input field.',
|
|
196
|
+
},
|
|
197
|
+
submitSelector: {
|
|
198
|
+
type: 'string',
|
|
199
|
+
description: 'CSS selector for submit button.',
|
|
200
|
+
},
|
|
201
|
+
successIndicator: {
|
|
202
|
+
type: 'string',
|
|
203
|
+
description: 'CSS selector that appears after successful login.',
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
description: 'Custom selectors for login form. If not provided, defaults are used.',
|
|
207
|
+
},
|
|
208
|
+
sessionId: {
|
|
209
|
+
type: 'string',
|
|
210
|
+
description: 'Custom session identifier. If not provided, one is generated.',
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
required: ['domain', 'username', 'password'],
|
|
214
|
+
},
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
name: 'audit_with_session',
|
|
218
|
+
description: 'Run an accessibility audit on a URL using an existing authenticated session. This allows testing protected pages without re-authenticating for each audit.',
|
|
219
|
+
inputSchema: {
|
|
220
|
+
type: 'object',
|
|
221
|
+
properties: {
|
|
222
|
+
sessionId: {
|
|
223
|
+
type: 'string',
|
|
224
|
+
description: 'Session ID from create_session tool.',
|
|
225
|
+
},
|
|
226
|
+
url: {
|
|
227
|
+
type: 'string',
|
|
228
|
+
description: 'Full URL or relative path to test. If relative, domain must be provided.',
|
|
229
|
+
},
|
|
230
|
+
domain: {
|
|
231
|
+
type: 'string',
|
|
232
|
+
description: 'Base domain if URL is relative. If not provided, uses session domain.',
|
|
233
|
+
},
|
|
234
|
+
tags: {
|
|
235
|
+
type: 'array',
|
|
236
|
+
items: {
|
|
237
|
+
type: 'string',
|
|
238
|
+
enum: [
|
|
239
|
+
'wcag2a',
|
|
240
|
+
'wcag2aa',
|
|
241
|
+
'wcag2aaa',
|
|
242
|
+
'wcag21a',
|
|
243
|
+
'wcag21aa',
|
|
244
|
+
'wcag21aaa',
|
|
245
|
+
'best-practice',
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
description: 'Specific accessibility tags to check. If not provided, all tags are checked.',
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
required: ['sessionId', 'url'],
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
name: 'get_accessibility_score',
|
|
256
|
+
description: 'Calculate accessibility score (0-100) from audit results with detailed breakdowns by category and WCAG compliance levels. Supports custom weights for different issue types.',
|
|
257
|
+
inputSchema: {
|
|
258
|
+
type: 'object',
|
|
259
|
+
properties: {
|
|
260
|
+
results: {
|
|
261
|
+
oneOf: [
|
|
262
|
+
{
|
|
263
|
+
type: 'object',
|
|
264
|
+
description: 'Audit result object from a previous audit.',
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
type: 'string',
|
|
268
|
+
description: 'URL to audit and score. If provided, an audit will be run first.',
|
|
269
|
+
},
|
|
270
|
+
],
|
|
271
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
272
|
+
},
|
|
273
|
+
weights: {
|
|
274
|
+
type: 'object',
|
|
275
|
+
additionalProperties: {
|
|
276
|
+
type: 'number',
|
|
277
|
+
},
|
|
278
|
+
description: 'Custom weights for different issue types (e.g., {"critical": 5.0, "serious": 3.0}). If not provided, default weights are used.',
|
|
279
|
+
},
|
|
280
|
+
},
|
|
281
|
+
required: ['results'],
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
name: 'prioritize_issues',
|
|
286
|
+
description: 'Intelligently prioritize accessibility issues based on specified criteria, identifying quick wins (easy fixes with high impact) and critical blockers (must fix before launch).',
|
|
287
|
+
inputSchema: {
|
|
288
|
+
type: 'object',
|
|
289
|
+
properties: {
|
|
290
|
+
results: {
|
|
291
|
+
type: 'object',
|
|
292
|
+
description: 'Audit result object from a previous audit.',
|
|
293
|
+
},
|
|
294
|
+
criteria: {
|
|
295
|
+
type: 'string',
|
|
296
|
+
enum: ['impact', 'wcag', 'fixability', 'user-impact'],
|
|
297
|
+
default: 'impact',
|
|
298
|
+
description: 'Prioritization criteria: "impact" (by impact level), "wcag" (by WCAG compliance level), "fixability" (by ease of fix), or "user-impact" (by user experience impact).',
|
|
299
|
+
},
|
|
300
|
+
limit: {
|
|
301
|
+
type: 'number',
|
|
302
|
+
description: 'Top N issues to return. If not provided, all issues are returned.',
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
required: ['results'],
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
name: 'explain_issue',
|
|
310
|
+
description: 'Explain what an accessibility issue means in plain language. Provides educational information including why it matters, how to fix it, WCAG references, and code examples.',
|
|
311
|
+
inputSchema: {
|
|
312
|
+
type: 'object',
|
|
313
|
+
properties: {
|
|
314
|
+
ruleId: {
|
|
315
|
+
type: 'string',
|
|
316
|
+
description: 'Accessibility rule ID (e.g., "alt_missing", "contrast", "label_missing").',
|
|
317
|
+
},
|
|
318
|
+
context: {
|
|
319
|
+
type: 'string',
|
|
320
|
+
description: 'Additional context about the issue (optional). Can include element information or specific circumstances.',
|
|
321
|
+
},
|
|
322
|
+
},
|
|
323
|
+
required: ['ruleId'],
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
name: 'get_quick_fixes',
|
|
328
|
+
description: 'Get specific fix suggestions with before/after code examples from audit results. Returns actionable fixes formatted as markdown, HTML, or JSON.',
|
|
329
|
+
inputSchema: {
|
|
330
|
+
type: 'object',
|
|
331
|
+
properties: {
|
|
332
|
+
results: {
|
|
333
|
+
oneOf: [
|
|
334
|
+
{
|
|
335
|
+
type: 'object',
|
|
336
|
+
description: 'Audit result object from a previous audit.',
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
type: 'string',
|
|
340
|
+
description: 'URL to audit and get fixes for. If provided, an audit will be run first.',
|
|
341
|
+
},
|
|
342
|
+
],
|
|
343
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
344
|
+
},
|
|
345
|
+
format: {
|
|
346
|
+
type: 'string',
|
|
347
|
+
enum: ['markdown', 'html', 'json'],
|
|
348
|
+
default: 'json',
|
|
349
|
+
description: 'Output format: "markdown" for markdown-formatted fixes, "html" for HTML format, or "json" for structured data (default: json).',
|
|
350
|
+
},
|
|
351
|
+
includeCode: {
|
|
352
|
+
type: 'boolean',
|
|
353
|
+
default: true,
|
|
354
|
+
description: 'Include before/after code examples in the fixes (default: true).',
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
required: ['results'],
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
name: 'compare_accessibility',
|
|
362
|
+
description: 'Compare two accessibility audits to track improvements. Identifies issues that were fixed, introduced, or remain, with score improvement and visual diff summary.',
|
|
363
|
+
inputSchema: {
|
|
364
|
+
type: 'object',
|
|
365
|
+
properties: {
|
|
366
|
+
before: {
|
|
367
|
+
oneOf: [
|
|
368
|
+
{
|
|
369
|
+
type: 'object',
|
|
370
|
+
description: 'Previous audit result object from a previous audit.',
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
type: 'string',
|
|
374
|
+
description: 'URL of the previous audit. If provided, an audit will be run first.',
|
|
375
|
+
},
|
|
376
|
+
],
|
|
377
|
+
description: 'Previous audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
378
|
+
},
|
|
379
|
+
after: {
|
|
380
|
+
oneOf: [
|
|
381
|
+
{
|
|
382
|
+
type: 'object',
|
|
383
|
+
description: 'Current audit result object from a previous audit.',
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
type: 'string',
|
|
387
|
+
description: 'URL of the current audit. If provided, an audit will be run first.',
|
|
388
|
+
},
|
|
389
|
+
],
|
|
390
|
+
description: 'Current audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
391
|
+
},
|
|
392
|
+
format: {
|
|
393
|
+
type: 'string',
|
|
394
|
+
enum: ['summary', 'detailed', 'diff'],
|
|
395
|
+
default: 'summary',
|
|
396
|
+
description: 'Output format: "summary" for concise comparison, "detailed" or "diff" for comprehensive diff visualization (default: summary).',
|
|
397
|
+
},
|
|
398
|
+
},
|
|
399
|
+
required: ['before', 'after'],
|
|
400
|
+
},
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
name: 'track_accessibility',
|
|
404
|
+
description: 'Track accessibility metrics over time with trend analysis, predictions, and recommendations. Stores audit results for historical comparison.',
|
|
405
|
+
inputSchema: {
|
|
406
|
+
type: 'object',
|
|
407
|
+
properties: {
|
|
408
|
+
url: {
|
|
409
|
+
type: 'string',
|
|
410
|
+
description: 'URL to track accessibility metrics for.',
|
|
411
|
+
},
|
|
412
|
+
timeframe: {
|
|
413
|
+
type: 'string',
|
|
414
|
+
enum: ['7d', '30d', '90d', 'all'],
|
|
415
|
+
default: '30d',
|
|
416
|
+
description: 'Timeframe for historical data: "7d" (7 days), "30d" (30 days), "90d" (90 days), or "all" (all available data). Default: 30d.',
|
|
417
|
+
},
|
|
418
|
+
metric: {
|
|
419
|
+
type: 'string',
|
|
420
|
+
enum: ['score', 'issues', 'wcag-compliance'],
|
|
421
|
+
default: 'score',
|
|
422
|
+
description: 'Metric to track: "score" (accessibility score 0-100), "issues" (total number of issues), or "wcag-compliance" (average WCAG compliance percentage). Default: score.',
|
|
423
|
+
},
|
|
424
|
+
},
|
|
425
|
+
required: ['url'],
|
|
426
|
+
},
|
|
427
|
+
},
|
|
428
|
+
{
|
|
429
|
+
name: 'generate_compliance_report',
|
|
430
|
+
description: 'Generate compliance reports in VPAT, WCAG, ADA, or Section 508 format. Includes WCAG criterion mapping, compliance percentages, executive summary, and optional remediation plan.',
|
|
431
|
+
inputSchema: {
|
|
432
|
+
type: 'object',
|
|
433
|
+
properties: {
|
|
434
|
+
results: {
|
|
435
|
+
type: 'object',
|
|
436
|
+
description: 'Audit result object from a previous audit.',
|
|
437
|
+
},
|
|
438
|
+
format: {
|
|
439
|
+
type: 'string',
|
|
440
|
+
enum: ['VPAT', 'WCAG', 'ADA', 'Section508'],
|
|
441
|
+
default: 'WCAG',
|
|
442
|
+
description: 'Report format: "VPAT" (Voluntary Product Accessibility Template), "WCAG" (WCAG compliance report), "ADA" (Americans with Disabilities Act report), or "Section508" (Section 508 compliance report). Default: WCAG.',
|
|
443
|
+
},
|
|
444
|
+
level: {
|
|
445
|
+
type: 'string',
|
|
446
|
+
enum: ['A', 'AA', 'AAA'],
|
|
447
|
+
default: 'AA',
|
|
448
|
+
description: 'WCAG compliance level to assess: "A", "AA", or "AAA". Default: AA.',
|
|
449
|
+
},
|
|
450
|
+
includeRemediation: {
|
|
451
|
+
type: 'boolean',
|
|
452
|
+
default: false,
|
|
453
|
+
description: 'Include remediation plan with fix suggestions in the report (default: false).',
|
|
454
|
+
},
|
|
455
|
+
},
|
|
456
|
+
required: ['results'],
|
|
457
|
+
},
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
name: 'get_wcag_compliance',
|
|
461
|
+
description: 'Check WCAG compliance status with detailed per-criterion breakdown. Returns compliance status (pass/fail/partial), compliance percentage, violations per criterion, and missing requirements.',
|
|
462
|
+
inputSchema: {
|
|
463
|
+
type: 'object',
|
|
464
|
+
properties: {
|
|
465
|
+
results: {
|
|
466
|
+
oneOf: [
|
|
467
|
+
{
|
|
468
|
+
type: 'object',
|
|
469
|
+
description: 'Audit result object from a previous audit.',
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
type: 'string',
|
|
473
|
+
description: 'URL to audit and check compliance for. If provided, an audit will be run first.',
|
|
474
|
+
},
|
|
475
|
+
],
|
|
476
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
477
|
+
},
|
|
478
|
+
level: {
|
|
479
|
+
type: 'string',
|
|
480
|
+
enum: ['A', 'AA', 'AAA'],
|
|
481
|
+
default: 'AA',
|
|
482
|
+
description: 'WCAG compliance level to check: "A", "AA", or "AAA". Default: AA.',
|
|
483
|
+
},
|
|
484
|
+
},
|
|
485
|
+
required: ['results'],
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
name: 'export_to_csv',
|
|
490
|
+
description: 'Export audit results to CSV format for spreadsheet analysis. Includes metadata section and violation rows.',
|
|
491
|
+
inputSchema: {
|
|
492
|
+
type: 'object',
|
|
493
|
+
properties: {
|
|
494
|
+
results: {
|
|
495
|
+
oneOf: [
|
|
496
|
+
{
|
|
497
|
+
type: 'object',
|
|
498
|
+
description: 'Audit result object from a previous audit.',
|
|
499
|
+
},
|
|
500
|
+
{
|
|
501
|
+
type: 'string',
|
|
502
|
+
description: 'URL to audit and export. If provided, an audit will be run first.',
|
|
503
|
+
},
|
|
504
|
+
],
|
|
505
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
506
|
+
},
|
|
507
|
+
includeMetadata: {
|
|
508
|
+
type: 'boolean',
|
|
509
|
+
default: true,
|
|
510
|
+
description: 'Include test information and environment data (default: true).',
|
|
511
|
+
},
|
|
512
|
+
includeViolations: {
|
|
513
|
+
type: 'boolean',
|
|
514
|
+
default: true,
|
|
515
|
+
description: 'Include detailed violation rows (default: true).',
|
|
516
|
+
},
|
|
517
|
+
format: {
|
|
518
|
+
type: 'string',
|
|
519
|
+
enum: ['standard', 'detailed', 'minimal'],
|
|
520
|
+
default: 'standard',
|
|
521
|
+
description: 'Export format: "standard" (default), "detailed" (includes all fields), or "minimal" (essential fields only).',
|
|
522
|
+
},
|
|
523
|
+
},
|
|
524
|
+
required: ['results'],
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
name: 'export_to_excel',
|
|
529
|
+
description: 'Export audit results to Excel/XLSX format with formatting. Requires xlsx package.',
|
|
530
|
+
inputSchema: {
|
|
531
|
+
type: 'object',
|
|
532
|
+
properties: {
|
|
533
|
+
results: {
|
|
534
|
+
oneOf: [
|
|
535
|
+
{
|
|
536
|
+
type: 'object',
|
|
537
|
+
description: 'Audit result object from a previous audit.',
|
|
538
|
+
},
|
|
539
|
+
{
|
|
540
|
+
type: 'string',
|
|
541
|
+
description: 'URL to audit and export. If provided, an audit will be run first.',
|
|
542
|
+
},
|
|
543
|
+
],
|
|
544
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
545
|
+
},
|
|
546
|
+
includeCharts: {
|
|
547
|
+
type: 'boolean',
|
|
548
|
+
default: false,
|
|
549
|
+
description: 'Generate charts for score trends and category breakdown (default: false).',
|
|
550
|
+
},
|
|
551
|
+
formatting: {
|
|
552
|
+
type: 'boolean',
|
|
553
|
+
default: true,
|
|
554
|
+
description: 'Apply colors, headers, and styling (default: true).',
|
|
555
|
+
},
|
|
556
|
+
},
|
|
557
|
+
required: ['results'],
|
|
558
|
+
},
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
name: 'export_to_json',
|
|
562
|
+
description: 'Export audit results as structured JSON. Supports pretty-printing and optional raw results.',
|
|
563
|
+
inputSchema: {
|
|
564
|
+
type: 'object',
|
|
565
|
+
properties: {
|
|
566
|
+
results: {
|
|
567
|
+
oneOf: [
|
|
568
|
+
{
|
|
569
|
+
type: 'object',
|
|
570
|
+
description: 'Audit result object from a previous audit.',
|
|
571
|
+
},
|
|
572
|
+
{
|
|
573
|
+
type: 'string',
|
|
574
|
+
description: 'URL to audit and export. If provided, an audit will be run first.',
|
|
575
|
+
},
|
|
576
|
+
],
|
|
577
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
578
|
+
},
|
|
579
|
+
pretty: {
|
|
580
|
+
type: 'boolean',
|
|
581
|
+
default: true,
|
|
582
|
+
description: 'Pretty-print JSON (default: true).',
|
|
583
|
+
},
|
|
584
|
+
includeRaw: {
|
|
585
|
+
type: 'boolean',
|
|
586
|
+
default: false,
|
|
587
|
+
description: 'Include raw accessibility engine results (default: false).',
|
|
588
|
+
},
|
|
589
|
+
},
|
|
590
|
+
required: ['results'],
|
|
591
|
+
},
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
name: 'export_to_html_report',
|
|
595
|
+
description: 'Generate standalone HTML report with styling. Includes optional visual charts.',
|
|
596
|
+
inputSchema: {
|
|
597
|
+
type: 'object',
|
|
598
|
+
properties: {
|
|
599
|
+
results: {
|
|
600
|
+
oneOf: [
|
|
601
|
+
{
|
|
602
|
+
type: 'object',
|
|
603
|
+
description: 'Audit result object from a previous audit.',
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
type: 'string',
|
|
607
|
+
description: 'URL to audit and export. If provided, an audit will be run first.',
|
|
608
|
+
},
|
|
609
|
+
],
|
|
610
|
+
description: 'Audit results object or URL string. If URL is provided, an audit will be run first.',
|
|
611
|
+
},
|
|
612
|
+
template: {
|
|
613
|
+
type: 'string',
|
|
614
|
+
enum: ['default', 'minimal', 'detailed'],
|
|
615
|
+
default: 'default',
|
|
616
|
+
description: 'Report template: "default" (standard report), "minimal" (essential info only), or "detailed" (comprehensive report).',
|
|
617
|
+
},
|
|
618
|
+
includeCharts: {
|
|
619
|
+
type: 'boolean',
|
|
620
|
+
default: true,
|
|
621
|
+
description: 'Include visual charts (default: true).',
|
|
622
|
+
},
|
|
623
|
+
},
|
|
624
|
+
required: ['results'],
|
|
625
|
+
},
|
|
626
|
+
},
|
|
627
|
+
{
|
|
628
|
+
name: 'filter_issues',
|
|
629
|
+
description: 'Filter issues from audit results by various criteria (rule IDs, categories, impact levels, WCAG levels, etc.). Supports include/exclude modes.',
|
|
630
|
+
inputSchema: {
|
|
631
|
+
type: 'object',
|
|
632
|
+
properties: {
|
|
633
|
+
results: {
|
|
634
|
+
type: 'object',
|
|
635
|
+
description: 'Audit result object from a previous audit.',
|
|
636
|
+
},
|
|
637
|
+
filters: {
|
|
638
|
+
type: 'object',
|
|
639
|
+
properties: {
|
|
640
|
+
ruleIds: {
|
|
641
|
+
type: 'array',
|
|
642
|
+
items: { type: 'string' },
|
|
643
|
+
description: 'Array of rule IDs to include/exclude.',
|
|
644
|
+
},
|
|
645
|
+
categories: {
|
|
646
|
+
type: 'array',
|
|
647
|
+
items: { type: 'string' },
|
|
648
|
+
description: 'Array of categories (error, contrast, etc.).',
|
|
649
|
+
},
|
|
650
|
+
impactLevels: {
|
|
651
|
+
type: 'array',
|
|
652
|
+
items: {
|
|
653
|
+
type: 'string',
|
|
654
|
+
enum: ['critical', 'serious', 'moderate', 'minor'],
|
|
655
|
+
},
|
|
656
|
+
description: 'Array of impact levels to filter by.',
|
|
657
|
+
},
|
|
658
|
+
wcagLevels: {
|
|
659
|
+
type: 'array',
|
|
660
|
+
items: { type: 'string', enum: ['A', 'AA', 'AAA'] },
|
|
661
|
+
description: 'Array of WCAG levels to filter by.',
|
|
662
|
+
},
|
|
663
|
+
minCount: {
|
|
664
|
+
type: 'number',
|
|
665
|
+
description: 'Minimum occurrence count for an issue to be included.',
|
|
666
|
+
},
|
|
667
|
+
elementTypes: {
|
|
668
|
+
type: 'array',
|
|
669
|
+
items: { type: 'string' },
|
|
670
|
+
description: 'Filter by HTML element types (e.g., ["img", "input", "button"]).',
|
|
671
|
+
},
|
|
672
|
+
},
|
|
673
|
+
description: 'Filter criteria object.',
|
|
674
|
+
},
|
|
675
|
+
mode: {
|
|
676
|
+
type: 'string',
|
|
677
|
+
enum: ['include', 'exclude'],
|
|
678
|
+
default: 'include',
|
|
679
|
+
description: 'Filter mode: "include" (only include matching issues) or "exclude" (exclude matching issues).',
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
required: ['results', 'filters'],
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
name: 'search_issues',
|
|
687
|
+
description: 'Search issues by text content, selector, XPath, or description. Supports case-sensitive and case-insensitive search.',
|
|
688
|
+
inputSchema: {
|
|
689
|
+
type: 'object',
|
|
690
|
+
properties: {
|
|
691
|
+
results: {
|
|
692
|
+
type: 'object',
|
|
693
|
+
description: 'Audit result object from a previous audit.',
|
|
694
|
+
},
|
|
695
|
+
query: {
|
|
696
|
+
type: 'string',
|
|
697
|
+
description: 'Search query string.',
|
|
698
|
+
},
|
|
699
|
+
fields: {
|
|
700
|
+
type: 'array',
|
|
701
|
+
items: {
|
|
702
|
+
type: 'string',
|
|
703
|
+
enum: [
|
|
704
|
+
'description',
|
|
705
|
+
'element',
|
|
706
|
+
'xpath',
|
|
707
|
+
'selector',
|
|
708
|
+
'ruleId',
|
|
709
|
+
'userImpact',
|
|
710
|
+
'fix',
|
|
711
|
+
'all',
|
|
712
|
+
],
|
|
713
|
+
},
|
|
714
|
+
default: ['all'],
|
|
715
|
+
description: 'Fields to search: "description", "element", "xpath", "selector", "ruleId", "userImpact", "fix", or "all" (default: ["all"]).',
|
|
716
|
+
},
|
|
717
|
+
caseSensitive: {
|
|
718
|
+
type: 'boolean',
|
|
719
|
+
default: false,
|
|
720
|
+
description: 'Case-sensitive search (default: false).',
|
|
721
|
+
},
|
|
722
|
+
},
|
|
723
|
+
required: ['results', 'query'],
|
|
724
|
+
},
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
name: 'aggregate_audit_results',
|
|
728
|
+
description: 'Combine and aggregate multiple audit results. Groups issues by URL, category, rule, or none, and provides aggregated summary statistics.',
|
|
729
|
+
inputSchema: {
|
|
730
|
+
type: 'object',
|
|
731
|
+
properties: {
|
|
732
|
+
results: {
|
|
733
|
+
type: 'array',
|
|
734
|
+
items: {
|
|
735
|
+
type: 'object',
|
|
736
|
+
description: 'Audit result object from a previous audit.',
|
|
737
|
+
},
|
|
738
|
+
description: 'Array of audit result objects to aggregate.',
|
|
739
|
+
},
|
|
740
|
+
groupBy: {
|
|
741
|
+
type: 'string',
|
|
742
|
+
enum: ['url', 'category', 'rule', 'none'],
|
|
743
|
+
default: 'url',
|
|
744
|
+
description: 'Grouping strategy: "url" (group by URL), "category" (group by category), "rule" (group by rule ID), or "none" (no grouping). Default: "url".',
|
|
745
|
+
},
|
|
746
|
+
includeSummary: {
|
|
747
|
+
type: 'boolean',
|
|
748
|
+
default: true,
|
|
749
|
+
description: 'Include aggregated summary statistics (default: true).',
|
|
750
|
+
},
|
|
751
|
+
},
|
|
752
|
+
required: ['results'],
|
|
753
|
+
},
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
name: 'get_statistics',
|
|
757
|
+
description: 'Generate detailed statistics from audit results with breakdowns by category, impact, WCAG level, or rule ID. Supports single or multiple audit results.',
|
|
758
|
+
inputSchema: {
|
|
759
|
+
type: 'object',
|
|
760
|
+
properties: {
|
|
761
|
+
results: {
|
|
762
|
+
oneOf: [
|
|
763
|
+
{
|
|
764
|
+
type: 'object',
|
|
765
|
+
description: 'Audit result object from a previous audit.',
|
|
766
|
+
},
|
|
767
|
+
{
|
|
768
|
+
type: 'array',
|
|
769
|
+
items: {
|
|
770
|
+
type: 'object',
|
|
771
|
+
description: 'Audit result object from a previous audit.',
|
|
772
|
+
},
|
|
773
|
+
description: 'Array of audit result objects.',
|
|
774
|
+
},
|
|
775
|
+
],
|
|
776
|
+
description: 'Audit result object or array of audit results to analyze.',
|
|
777
|
+
},
|
|
778
|
+
breakdown: {
|
|
779
|
+
type: 'array',
|
|
780
|
+
items: {
|
|
781
|
+
type: 'string',
|
|
782
|
+
enum: ['category', 'impact', 'wcag', 'rule'],
|
|
783
|
+
},
|
|
784
|
+
default: ['category', 'impact', 'wcag', 'rule'],
|
|
785
|
+
description: 'Array of breakdown dimensions: "category", "impact", "wcag", "rule". Default: all dimensions.',
|
|
786
|
+
},
|
|
787
|
+
},
|
|
788
|
+
required: ['results'],
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
name: 'generate_dashboard',
|
|
793
|
+
description: 'Create a visual dashboard summary of audit results with key metrics, charts, and summaries. Supports multiple formats (text, markdown, HTML, JSON) and optional charts.',
|
|
794
|
+
inputSchema: {
|
|
795
|
+
type: 'object',
|
|
796
|
+
properties: {
|
|
797
|
+
results: {
|
|
798
|
+
oneOf: [
|
|
799
|
+
{
|
|
800
|
+
type: 'object',
|
|
801
|
+
description: 'Audit result object from a previous audit.',
|
|
802
|
+
},
|
|
803
|
+
{
|
|
804
|
+
type: 'array',
|
|
805
|
+
items: {
|
|
806
|
+
type: 'object',
|
|
807
|
+
description: 'Audit result object from a previous audit.',
|
|
808
|
+
},
|
|
809
|
+
description: 'Array of audit result objects.',
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
type: 'string',
|
|
813
|
+
description: 'URL to audit and generate dashboard for. If provided, an audit will be run first.',
|
|
814
|
+
},
|
|
815
|
+
{
|
|
816
|
+
type: 'array',
|
|
817
|
+
items: { type: 'string' },
|
|
818
|
+
description: 'Array of URLs to audit and generate dashboard for.',
|
|
819
|
+
},
|
|
820
|
+
],
|
|
821
|
+
description: 'Audit result object(s) or URL string(s). If URL(s) provided, audit(s) will be run first.',
|
|
822
|
+
},
|
|
823
|
+
format: {
|
|
824
|
+
type: 'string',
|
|
825
|
+
enum: ['text', 'markdown', 'html', 'json'],
|
|
826
|
+
default: 'markdown',
|
|
827
|
+
description: 'Output format: "text" (plain text), "markdown" (markdown format), "html" (HTML report), or "json" (structured JSON). Default: "markdown".',
|
|
828
|
+
},
|
|
829
|
+
includeCharts: {
|
|
830
|
+
type: 'boolean',
|
|
831
|
+
default: true,
|
|
832
|
+
description: 'Include ASCII/text charts in the dashboard (default: true).',
|
|
833
|
+
},
|
|
834
|
+
},
|
|
835
|
+
required: ['results'],
|
|
836
|
+
},
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
name: 'generate_summary_report',
|
|
840
|
+
description: 'Generate executive summary report with key findings and recommendations. Supports multiple formats (text, markdown, HTML) and detail levels (executive, detailed, technical).',
|
|
841
|
+
inputSchema: {
|
|
842
|
+
type: 'object',
|
|
843
|
+
properties: {
|
|
844
|
+
results: {
|
|
845
|
+
oneOf: [
|
|
846
|
+
{
|
|
847
|
+
type: 'object',
|
|
848
|
+
description: 'Audit result object from a previous audit.',
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
type: 'array',
|
|
852
|
+
items: {
|
|
853
|
+
type: 'object',
|
|
854
|
+
description: 'Audit result object from a previous audit.',
|
|
855
|
+
},
|
|
856
|
+
description: 'Array of audit result objects.',
|
|
857
|
+
},
|
|
858
|
+
{
|
|
859
|
+
type: 'string',
|
|
860
|
+
description: 'URL to audit and generate report for. If provided, an audit will be run first.',
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
type: 'array',
|
|
864
|
+
items: { type: 'string' },
|
|
865
|
+
description: 'Array of URLs to audit and generate report for.',
|
|
866
|
+
},
|
|
867
|
+
],
|
|
868
|
+
description: 'Audit result object(s) or URL string(s). If URL(s) provided, audit(s) will be run first.',
|
|
869
|
+
},
|
|
870
|
+
format: {
|
|
871
|
+
type: 'string',
|
|
872
|
+
enum: ['text', 'markdown', 'html'],
|
|
873
|
+
default: 'markdown',
|
|
874
|
+
description: 'Output format: "text" (plain text), "markdown" (markdown format), or "html" (HTML report). Default: "markdown".',
|
|
875
|
+
},
|
|
876
|
+
level: {
|
|
877
|
+
type: 'string',
|
|
878
|
+
enum: ['executive', 'detailed', 'technical'],
|
|
879
|
+
default: 'executive',
|
|
880
|
+
description: 'Detail level: "executive" (high-level summary for executives), "detailed" (comprehensive summary with breakdowns), or "technical" (technical details for developers). Default: "executive".',
|
|
881
|
+
},
|
|
882
|
+
},
|
|
883
|
+
required: ['results'],
|
|
884
|
+
},
|
|
885
|
+
},
|
|
886
|
+
];
|
|
887
|
+
return {
|
|
888
|
+
tools,
|
|
889
|
+
};
|
|
890
|
+
});
|
|
891
|
+
// Handle tool calls
|
|
892
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
893
|
+
const { name, arguments: args } = request.params;
|
|
894
|
+
try {
|
|
895
|
+
switch (name) {
|
|
896
|
+
case 'audit_url': {
|
|
897
|
+
const auditResult = await retryWithBackoff(async () => await auditUrl({
|
|
898
|
+
url: args?.url,
|
|
899
|
+
domain: args?.domain,
|
|
900
|
+
tags: args?.tags,
|
|
901
|
+
engine: args?.engine,
|
|
902
|
+
waitForLoad: args?.waitForLoad,
|
|
903
|
+
timeout: args?.timeout,
|
|
904
|
+
}), {
|
|
905
|
+
maxRetries: 2, // Fewer retries for single URL audits
|
|
906
|
+
});
|
|
907
|
+
return {
|
|
908
|
+
content: [
|
|
909
|
+
{
|
|
910
|
+
type: 'text',
|
|
911
|
+
text: JSON.stringify(auditResult, null, 2),
|
|
912
|
+
},
|
|
913
|
+
],
|
|
914
|
+
};
|
|
915
|
+
}
|
|
916
|
+
case 'audit_multiple_urls': {
|
|
917
|
+
// Collect progress updates for streaming
|
|
918
|
+
const progressUpdates = [];
|
|
919
|
+
// Create progress callback that logs and collects updates
|
|
920
|
+
const progressCallback = (progress) => {
|
|
921
|
+
progressUpdates.push(progress);
|
|
922
|
+
// Log progress to stderr so MCP clients can capture it
|
|
923
|
+
const timeRemainingText = progress.estimatedTimeRemaining
|
|
924
|
+
? ` (estimated ${formatTimeRemaining(progress.estimatedTimeRemaining)} remaining)`
|
|
925
|
+
: '';
|
|
926
|
+
console.error(`[PROGRESS] ${progress.current}/${progress.total} (${progress.percentage}%) - ${progress.status}${timeRemainingText}`);
|
|
927
|
+
};
|
|
928
|
+
const batchResult = await retryWithBackoff(async () => await auditMultipleUrls({
|
|
929
|
+
urls: args?.urls,
|
|
930
|
+
domain: args?.domain,
|
|
931
|
+
parallel: args?.parallel,
|
|
932
|
+
continueOnError: args?.continueOnError,
|
|
933
|
+
tags: args?.tags,
|
|
934
|
+
engine: args?.engine,
|
|
935
|
+
}, progressCallback), {
|
|
936
|
+
maxRetries: 1, // Only retry once for batch operations
|
|
937
|
+
});
|
|
938
|
+
// Include progress history in response
|
|
939
|
+
const response = {
|
|
940
|
+
...batchResult,
|
|
941
|
+
progressHistory: progressUpdates,
|
|
942
|
+
};
|
|
943
|
+
return {
|
|
944
|
+
content: [
|
|
945
|
+
{
|
|
946
|
+
type: 'text',
|
|
947
|
+
text: JSON.stringify(response, null, 2),
|
|
948
|
+
},
|
|
949
|
+
],
|
|
950
|
+
};
|
|
951
|
+
}
|
|
952
|
+
case 'create_session': {
|
|
953
|
+
const sessionResult = await createSession({
|
|
954
|
+
domain: args?.domain,
|
|
955
|
+
loginUrl: args?.loginUrl,
|
|
956
|
+
username: args?.username,
|
|
957
|
+
password: args?.password,
|
|
958
|
+
loginSelectors: args?.loginSelectors,
|
|
959
|
+
sessionId: args?.sessionId,
|
|
960
|
+
});
|
|
961
|
+
return {
|
|
962
|
+
content: [
|
|
963
|
+
{
|
|
964
|
+
type: 'text',
|
|
965
|
+
text: JSON.stringify(sessionResult, null, 2),
|
|
966
|
+
},
|
|
967
|
+
],
|
|
968
|
+
};
|
|
969
|
+
}
|
|
970
|
+
case 'audit_with_session': {
|
|
971
|
+
const authenticatedAuditResult = await auditWithSession({
|
|
972
|
+
sessionId: args?.sessionId,
|
|
973
|
+
url: args?.url,
|
|
974
|
+
domain: args?.domain,
|
|
975
|
+
tags: args?.tags,
|
|
976
|
+
});
|
|
977
|
+
return {
|
|
978
|
+
content: [
|
|
979
|
+
{
|
|
980
|
+
type: 'text',
|
|
981
|
+
text: JSON.stringify(authenticatedAuditResult, null, 2),
|
|
982
|
+
},
|
|
983
|
+
],
|
|
984
|
+
};
|
|
985
|
+
}
|
|
986
|
+
case 'get_accessibility_score': {
|
|
987
|
+
const scoreResult = await getAccessibilityScore({
|
|
988
|
+
results: args?.results, // Can be AuditResult or string URL
|
|
989
|
+
weights: args?.weights,
|
|
990
|
+
});
|
|
991
|
+
return {
|
|
992
|
+
content: [
|
|
993
|
+
{
|
|
994
|
+
type: 'text',
|
|
995
|
+
text: JSON.stringify(scoreResult, null, 2),
|
|
996
|
+
},
|
|
997
|
+
],
|
|
998
|
+
};
|
|
999
|
+
}
|
|
1000
|
+
case 'prioritize_issues': {
|
|
1001
|
+
const prioritizeResult = prioritizeIssues({
|
|
1002
|
+
results: args?.results, // AuditResult
|
|
1003
|
+
criteria: args?.criteria,
|
|
1004
|
+
limit: args?.limit,
|
|
1005
|
+
});
|
|
1006
|
+
return {
|
|
1007
|
+
content: [
|
|
1008
|
+
{
|
|
1009
|
+
type: 'text',
|
|
1010
|
+
text: JSON.stringify(prioritizeResult, null, 2),
|
|
1011
|
+
},
|
|
1012
|
+
],
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
case 'explain_issue': {
|
|
1016
|
+
const explanationResult = explainIssue({
|
|
1017
|
+
ruleId: args?.ruleId,
|
|
1018
|
+
context: args?.context,
|
|
1019
|
+
});
|
|
1020
|
+
return {
|
|
1021
|
+
content: [
|
|
1022
|
+
{
|
|
1023
|
+
type: 'text',
|
|
1024
|
+
text: JSON.stringify(explanationResult, null, 2),
|
|
1025
|
+
},
|
|
1026
|
+
],
|
|
1027
|
+
};
|
|
1028
|
+
}
|
|
1029
|
+
case 'get_quick_fixes': {
|
|
1030
|
+
const quickFixesResult = await getQuickFixes({
|
|
1031
|
+
results: args?.results, // AuditResult or string URL
|
|
1032
|
+
format: args?.format,
|
|
1033
|
+
includeCode: args?.includeCode,
|
|
1034
|
+
});
|
|
1035
|
+
return {
|
|
1036
|
+
content: [
|
|
1037
|
+
{
|
|
1038
|
+
type: 'text',
|
|
1039
|
+
text: JSON.stringify(quickFixesResult, null, 2),
|
|
1040
|
+
},
|
|
1041
|
+
],
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
case 'compare_accessibility': {
|
|
1045
|
+
const comparisonResult = await compareAccessibility({
|
|
1046
|
+
before: args?.before, // AuditResult or string URL
|
|
1047
|
+
after: args?.after, // AuditResult or string URL
|
|
1048
|
+
format: args?.format,
|
|
1049
|
+
});
|
|
1050
|
+
return {
|
|
1051
|
+
content: [
|
|
1052
|
+
{
|
|
1053
|
+
type: 'text',
|
|
1054
|
+
text: JSON.stringify(comparisonResult, null, 2),
|
|
1055
|
+
},
|
|
1056
|
+
],
|
|
1057
|
+
};
|
|
1058
|
+
}
|
|
1059
|
+
case 'track_accessibility': {
|
|
1060
|
+
const trackingResult = await trackAccessibility({
|
|
1061
|
+
url: args?.url,
|
|
1062
|
+
timeframe: args?.timeframe,
|
|
1063
|
+
metric: args?.metric,
|
|
1064
|
+
});
|
|
1065
|
+
return {
|
|
1066
|
+
content: [
|
|
1067
|
+
{
|
|
1068
|
+
type: 'text',
|
|
1069
|
+
text: JSON.stringify(trackingResult, null, 2),
|
|
1070
|
+
},
|
|
1071
|
+
],
|
|
1072
|
+
};
|
|
1073
|
+
}
|
|
1074
|
+
case 'generate_compliance_report': {
|
|
1075
|
+
const complianceReport = generateComplianceReport({
|
|
1076
|
+
results: args?.results, // AuditResult
|
|
1077
|
+
format: args?.format,
|
|
1078
|
+
level: args?.level,
|
|
1079
|
+
includeRemediation: args?.includeRemediation,
|
|
1080
|
+
});
|
|
1081
|
+
return {
|
|
1082
|
+
content: [
|
|
1083
|
+
{
|
|
1084
|
+
type: 'text',
|
|
1085
|
+
text: JSON.stringify(complianceReport, null, 2),
|
|
1086
|
+
},
|
|
1087
|
+
],
|
|
1088
|
+
};
|
|
1089
|
+
}
|
|
1090
|
+
case 'get_wcag_compliance': {
|
|
1091
|
+
const wcagComplianceResult = await getWCAGCompliance({
|
|
1092
|
+
results: args?.results, // AuditResult or string URL
|
|
1093
|
+
level: args?.level,
|
|
1094
|
+
});
|
|
1095
|
+
return {
|
|
1096
|
+
content: [
|
|
1097
|
+
{
|
|
1098
|
+
type: 'text',
|
|
1099
|
+
text: JSON.stringify(wcagComplianceResult, null, 2),
|
|
1100
|
+
},
|
|
1101
|
+
],
|
|
1102
|
+
};
|
|
1103
|
+
}
|
|
1104
|
+
case 'export_to_csv': {
|
|
1105
|
+
const csvResult = await exportToCsv({
|
|
1106
|
+
results: args?.results, // AuditResult or string URL
|
|
1107
|
+
includeMetadata: args?.includeMetadata,
|
|
1108
|
+
includeViolations: args?.includeViolations,
|
|
1109
|
+
format: args?.format,
|
|
1110
|
+
});
|
|
1111
|
+
return {
|
|
1112
|
+
content: [
|
|
1113
|
+
{
|
|
1114
|
+
type: 'text',
|
|
1115
|
+
text: JSON.stringify(csvResult, null, 2),
|
|
1116
|
+
},
|
|
1117
|
+
],
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
case 'export_to_excel': {
|
|
1121
|
+
const excelResult = await exportToExcel({
|
|
1122
|
+
results: args?.results, // AuditResult or string URL
|
|
1123
|
+
includeCharts: args?.includeCharts,
|
|
1124
|
+
formatting: args?.formatting,
|
|
1125
|
+
});
|
|
1126
|
+
return {
|
|
1127
|
+
content: [
|
|
1128
|
+
{
|
|
1129
|
+
type: 'text',
|
|
1130
|
+
text: JSON.stringify(excelResult, null, 2),
|
|
1131
|
+
},
|
|
1132
|
+
],
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
case 'export_to_json': {
|
|
1136
|
+
const jsonResult = await exportToJson({
|
|
1137
|
+
results: args?.results, // AuditResult or string URL
|
|
1138
|
+
pretty: args?.pretty,
|
|
1139
|
+
includeRaw: args?.includeRaw,
|
|
1140
|
+
});
|
|
1141
|
+
return {
|
|
1142
|
+
content: [
|
|
1143
|
+
{
|
|
1144
|
+
type: 'text',
|
|
1145
|
+
text: JSON.stringify(jsonResult, null, 2),
|
|
1146
|
+
},
|
|
1147
|
+
],
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
case 'export_to_html_report': {
|
|
1151
|
+
const htmlResult = await exportToHtmlReport({
|
|
1152
|
+
results: args?.results, // AuditResult or string URL
|
|
1153
|
+
template: args?.template,
|
|
1154
|
+
includeCharts: args?.includeCharts,
|
|
1155
|
+
});
|
|
1156
|
+
return {
|
|
1157
|
+
content: [
|
|
1158
|
+
{
|
|
1159
|
+
type: 'text',
|
|
1160
|
+
text: JSON.stringify(htmlResult, null, 2),
|
|
1161
|
+
},
|
|
1162
|
+
],
|
|
1163
|
+
};
|
|
1164
|
+
}
|
|
1165
|
+
case 'filter_issues': {
|
|
1166
|
+
const filterResult = filterIssues({
|
|
1167
|
+
results: args?.results, // AuditResult
|
|
1168
|
+
filters: args?.filters, // FilterCriteria
|
|
1169
|
+
mode: args?.mode,
|
|
1170
|
+
});
|
|
1171
|
+
return {
|
|
1172
|
+
content: [
|
|
1173
|
+
{
|
|
1174
|
+
type: 'text',
|
|
1175
|
+
text: JSON.stringify(filterResult, null, 2),
|
|
1176
|
+
},
|
|
1177
|
+
],
|
|
1178
|
+
};
|
|
1179
|
+
}
|
|
1180
|
+
case 'search_issues': {
|
|
1181
|
+
const searchResult = searchIssues({
|
|
1182
|
+
results: args?.results, // AuditResult
|
|
1183
|
+
query: args?.query,
|
|
1184
|
+
fields: args?.fields, // Array of field names
|
|
1185
|
+
caseSensitive: args?.caseSensitive,
|
|
1186
|
+
});
|
|
1187
|
+
return {
|
|
1188
|
+
content: [
|
|
1189
|
+
{
|
|
1190
|
+
type: 'text',
|
|
1191
|
+
text: JSON.stringify(searchResult, null, 2),
|
|
1192
|
+
},
|
|
1193
|
+
],
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
case 'aggregate_audit_results': {
|
|
1197
|
+
const aggregateResult = aggregateAuditResults({
|
|
1198
|
+
results: args?.results, // Array of AuditResult
|
|
1199
|
+
groupBy: args?.groupBy,
|
|
1200
|
+
includeSummary: args?.includeSummary,
|
|
1201
|
+
});
|
|
1202
|
+
return {
|
|
1203
|
+
content: [
|
|
1204
|
+
{
|
|
1205
|
+
type: 'text',
|
|
1206
|
+
text: JSON.stringify(aggregateResult, null, 2),
|
|
1207
|
+
},
|
|
1208
|
+
],
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
case 'get_statistics': {
|
|
1212
|
+
const statisticsResult = getStatistics({
|
|
1213
|
+
results: args?.results, // AuditResult or AuditResult[]
|
|
1214
|
+
breakdown: args?.breakdown,
|
|
1215
|
+
});
|
|
1216
|
+
return {
|
|
1217
|
+
content: [
|
|
1218
|
+
{
|
|
1219
|
+
type: 'text',
|
|
1220
|
+
text: JSON.stringify(statisticsResult, null, 2),
|
|
1221
|
+
},
|
|
1222
|
+
],
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
case 'generate_dashboard': {
|
|
1226
|
+
const dashboardResult = await generateDashboard({
|
|
1227
|
+
results: args?.results, // AuditResult | AuditResult[] | string | string[]
|
|
1228
|
+
format: args?.format,
|
|
1229
|
+
includeCharts: args?.includeCharts,
|
|
1230
|
+
});
|
|
1231
|
+
return {
|
|
1232
|
+
content: [
|
|
1233
|
+
{
|
|
1234
|
+
type: 'text',
|
|
1235
|
+
text: JSON.stringify(dashboardResult, null, 2),
|
|
1236
|
+
},
|
|
1237
|
+
],
|
|
1238
|
+
};
|
|
1239
|
+
}
|
|
1240
|
+
case 'generate_summary_report': {
|
|
1241
|
+
const summaryReportResult = await generateSummaryReport({
|
|
1242
|
+
results: args?.results, // AuditResult | AuditResult[] | string | string[]
|
|
1243
|
+
format: args?.format,
|
|
1244
|
+
level: args?.level,
|
|
1245
|
+
});
|
|
1246
|
+
return {
|
|
1247
|
+
content: [
|
|
1248
|
+
{
|
|
1249
|
+
type: 'text',
|
|
1250
|
+
text: JSON.stringify(summaryReportResult, null, 2),
|
|
1251
|
+
},
|
|
1252
|
+
],
|
|
1253
|
+
};
|
|
1254
|
+
}
|
|
1255
|
+
default:
|
|
1256
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
catch (error) {
|
|
1260
|
+
// Use comprehensive error handling
|
|
1261
|
+
const errorInfo = handleErrorGracefully(error, `Tool: ${name}`);
|
|
1262
|
+
const errorMessage = formatErrorMessage(error, `Tool: ${name}`);
|
|
1263
|
+
// Log error details
|
|
1264
|
+
console.error(`[ERROR] ${errorMessage}`);
|
|
1265
|
+
const errorPayload = {
|
|
1266
|
+
error: String(errorInfo.error),
|
|
1267
|
+
category: errorInfo.category,
|
|
1268
|
+
retryable: errorInfo.retryable,
|
|
1269
|
+
suggestion: errorInfo.suggestion,
|
|
1270
|
+
};
|
|
1271
|
+
return {
|
|
1272
|
+
content: [
|
|
1273
|
+
{
|
|
1274
|
+
type: 'text',
|
|
1275
|
+
text: JSON.stringify(errorPayload, null, 2),
|
|
1276
|
+
},
|
|
1277
|
+
],
|
|
1278
|
+
isError: true,
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
});
|
|
1282
|
+
return server;
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Main entry point
|
|
1286
|
+
*/
|
|
1287
|
+
async function main() {
|
|
1288
|
+
const server = await createServer();
|
|
1289
|
+
const transport = new StdioServerTransport();
|
|
1290
|
+
await server.connect(transport);
|
|
1291
|
+
console.error('Accessibility MCP Server running on stdio');
|
|
1292
|
+
}
|
|
1293
|
+
// Start the server
|
|
1294
|
+
main().catch((error) => {
|
|
1295
|
+
console.error('Fatal error starting server:', error);
|
|
1296
|
+
process.exit(1);
|
|
1297
|
+
});
|
|
1298
|
+
//# sourceMappingURL=server.js.map
|