accessibility-server-mcp 1.0.7 → 1.0.8

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.
Files changed (55) hide show
  1. package/README.md +147 -6
  2. package/config/wcag-rules.json +22 -11
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +175 -31
  5. package/dist/index.js.map +1 -1
  6. package/dist/test-multi-standard.d.ts +6 -0
  7. package/dist/test-multi-standard.d.ts.map +1 -0
  8. package/dist/test-multi-standard.js +78 -0
  9. package/dist/test-multi-standard.js.map +1 -0
  10. package/dist/tools/accessibility-tester.d.ts +9 -1
  11. package/dist/tools/accessibility-tester.d.ts.map +1 -1
  12. package/dist/tools/accessibility-tester.js +75 -34
  13. package/dist/tools/accessibility-tester.js.map +1 -1
  14. package/dist/tools/wcag-validator.d.ts +19 -2
  15. package/dist/tools/wcag-validator.d.ts.map +1 -1
  16. package/dist/tools/wcag-validator.js +63 -1
  17. package/dist/tools/wcag-validator.js.map +1 -1
  18. package/dist/tools/website-accessibility-tester.d.ts +26 -4
  19. package/dist/tools/website-accessibility-tester.d.ts.map +1 -1
  20. package/dist/tools/website-accessibility-tester.js +122 -12
  21. package/dist/tools/website-accessibility-tester.js.map +1 -1
  22. package/dist/types/accessibility.d.ts +170 -5
  23. package/dist/types/accessibility.d.ts.map +1 -1
  24. package/dist/types/accessibility.js +67 -1
  25. package/dist/types/accessibility.js.map +1 -1
  26. package/dist/types/mcp.d.ts +13 -3
  27. package/dist/types/mcp.d.ts.map +1 -1
  28. package/dist/utils/ada-guidance.d.ts +22 -0
  29. package/dist/utils/ada-guidance.d.ts.map +1 -0
  30. package/dist/utils/ada-guidance.js +131 -0
  31. package/dist/utils/ada-guidance.js.map +1 -0
  32. package/dist/utils/browser-manager.d.ts +13 -0
  33. package/dist/utils/browser-manager.d.ts.map +1 -1
  34. package/dist/utils/browser-manager.js +67 -0
  35. package/dist/utils/browser-manager.js.map +1 -1
  36. package/dist/utils/index.d.ts +3 -0
  37. package/dist/utils/index.d.ts.map +1 -1
  38. package/dist/utils/index.js +3 -0
  39. package/dist/utils/index.js.map +1 -1
  40. package/dist/utils/report-generator.d.ts.map +1 -1
  41. package/dist/utils/report-generator.js +37 -2
  42. package/dist/utils/report-generator.js.map +1 -1
  43. package/dist/utils/standard-presets.d.ts +58 -0
  44. package/dist/utils/standard-presets.d.ts.map +1 -0
  45. package/dist/utils/standard-presets.js +188 -0
  46. package/dist/utils/standard-presets.js.map +1 -0
  47. package/dist/utils/standard-tag-metadata.d.ts +35 -0
  48. package/dist/utils/standard-tag-metadata.d.ts.map +1 -0
  49. package/dist/utils/standard-tag-metadata.js +416 -0
  50. package/dist/utils/standard-tag-metadata.js.map +1 -0
  51. package/dist/utils/website-crawler.d.ts +10 -0
  52. package/dist/utils/website-crawler.d.ts.map +1 -1
  53. package/dist/utils/website-crawler.js +40 -6
  54. package/dist/utils/website-crawler.js.map +1 -1
  55. package/package.json +1 -1
package/README.md CHANGED
@@ -7,7 +7,8 @@ A comprehensive Model Context Protocol (MCP) server for web accessibility testin
7
7
  - **🌐 URL Testing**: Test any public URL for accessibility issues using Puppeteer and axe-core
8
8
  - **🕷️ Website-Wide Testing**: Crawl and test entire websites for comprehensive accessibility audits
9
9
  - **📝 HTML Snippet Testing**: Analyze raw HTML strings for accessibility compliance
10
- - **📋 WCAG Compliance**: Support for WCAG 2.0, 2.1, and 2.2 standards (A, AA, AAA levels)
10
+ - **📋 Multi-Standard Support**: Test against WCAG 2.0/2.1/2.2, Section 508, ADA, EN 301 549, and more using axe-core tags
11
+ - **🎯 Flexible Standard Combinations**: Use presets (wcag-aa, ada, section508) or specify individual axe-core tags
11
12
  - **🎨 Color Contrast Analysis**: Check color combinations for WCAG contrast requirements
12
13
  - **♿ ARIA Validation**: Validate proper usage of ARIA attributes and roles
13
14
  - **📱 Mobile Testing**: Orientation lock detection and mobile accessibility issues
@@ -168,7 +169,69 @@ docker run -d --name accessibility-mcp \
168
169
  accessibility-mcp
169
170
  ```
170
171
 
171
- ## 🛠️ Available MCP Tools
172
+ ## Multi-Standard Support
173
+
174
+ The server supports testing against multiple accessibility standards simultaneously:
175
+
176
+ ### Standard Presets
177
+
178
+ Quick presets for common standard combinations:
179
+
180
+ - **`wcag-a`**: WCAG 2.0/2.1/2.2 Level A
181
+ - **`wcag-aa`**: WCAG 2.0/2.1/2.2 Level AA (default)
182
+ - **`wcag-aaa`**: WCAG 2.0/2.1/2.2 Level AAA
183
+ - **`section508`**: Section 508 compliance tags
184
+ - **`ada`**: ADA Title III compliance (WCAG 2.1 AA + legal guidance)
185
+ - **`en301549`**: EN 301 549 European standard
186
+ - **`all-standards`**: Comprehensive testing across all standards
187
+
188
+ ### Individual Standard Tags
189
+
190
+ Specify individual axe-core tags for fine-grained control (~150+ available):
191
+
192
+ **WCAG Tags:**
193
+ - `wcag2a`, `wcag2aa`, `wcag2aaa` - WCAG 2.0 levels
194
+ - `wcag21a`, `wcag21aa`, `wcag21aaa` - WCAG 2.1 levels
195
+ - `wcag22aa` - WCAG 2.2 Level AA
196
+ - `wcag111`, `wcag131`, `wcag143`, `wcag244`, etc. - Specific success criteria
197
+
198
+ **Other Standards:**
199
+ - `section508`, `section508.22.a`, `section508.22.g` - Section 508
200
+ - `EN-301-549` - European accessibility standard
201
+ - `TTv5` - Trusted Tester v5
202
+ - `RGAAv4` - French accessibility standard
203
+
204
+ **Category Tags:**
205
+ - `cat.color`, `cat.forms`, `cat.keyboard`, `cat.aria`, `cat.text-alternatives`
206
+ - `cat.name-role-value`, `cat.semantics`, `cat.language`, etc.
207
+
208
+ ### Standard Combination Logic
209
+
210
+ - **AND Logic** (default): Rules must match ALL specified standards (`requireAll: true`)
211
+ - **OR Logic**: Rules match ANY specified standard (`requireAll: false`)
212
+
213
+ ### Usage Examples
214
+
215
+ ```json
216
+ // Test against multiple presets
217
+ {
218
+ "standardPresets": ["wcag-aa", "section508", "ada"]
219
+ }
220
+
221
+ // Test against specific tags with AND logic
222
+ {
223
+ "standards": ["wcag21aa", "wcag244", "section508.22.a"],
224
+ "requireAll": true
225
+ }
226
+
227
+ // Test against category tags with OR logic
228
+ {
229
+ "standards": ["cat.color", "cat.forms"],
230
+ "requireAll": false
231
+ }
232
+ ```
233
+
234
+ ## �🛠️ Available MCP Tools
172
235
 
173
236
  The server provides four main tools for accessibility testing, with two operational modes:
174
237
 
@@ -189,7 +252,7 @@ The server provides four main tools for accessibility testing, with two operatio
189
252
 
190
253
  Test a website or HTML content for accessibility issues:
191
254
 
192
- **For URLs:**
255
+ **For URLs with standard presets:**
193
256
  ```json
194
257
  {
195
258
  "name": "test_accessibility",
@@ -197,12 +260,25 @@ Test a website or HTML content for accessibility issues:
197
260
  "target": "https://example.com",
198
261
  "type": "url",
199
262
  "level": "basic",
200
- "wcagLevel": "AA"
263
+ "standardPresets": ["wcag-aa", "section508"]
201
264
  }
202
265
  }
203
266
  ```
204
267
 
205
- **For HTML snippets:**
268
+ **For URLs with specific standard tags:**
269
+ ```json
270
+ {
271
+ "name": "test_accessibility",
272
+ "arguments": {
273
+ "target": "https://example.com",
274
+ "type": "url",
275
+ "level": "full",
276
+ "standards": ["wcag21aa", "wcag244", "section508.22.a", "EN-301-549"]
277
+ }
278
+ }
279
+ ```
280
+
281
+ **For HTML snippets (legacy wcagLevel still supported):**
206
282
  ```json
207
283
  {
208
284
  "name": "test_accessibility",
@@ -215,16 +291,30 @@ Test a website or HTML content for accessibility issues:
215
291
  }
216
292
  ```
217
293
 
294
+ **For ADA compliance testing:**
295
+ ```json
296
+ {
297
+ "name": "test_accessibility",
298
+ "arguments": {
299
+ "target": "https://example.com",
300
+ "type": "url",
301
+ "level": "full",
302
+ "standardPresets": ["ada"]
303
+ }
304
+ }
305
+ ```
306
+
218
307
  #### 2. Test Website Accessibility
219
308
 
220
309
  Test entire websites by crawling multiple pages:
221
310
 
311
+ **With standard presets:**
222
312
  ```json
223
313
  {
224
314
  "name": "test_website_accessibility",
225
315
  "arguments": {
226
316
  "baseUrl": "https://example.com",
227
- "wcagLevel": "AA",
317
+ "standardPresets": ["wcag-aa", "section508"],
228
318
  "maxPages": 20,
229
319
  "maxDepth": 3,
230
320
  "concurrency": 3,
@@ -235,6 +325,32 @@ Test entire websites by crawling multiple pages:
235
325
  }
236
326
  ```
237
327
 
328
+ **With specific standard tags:**
329
+ ```json
330
+ {
331
+ "name": "test_website_accessibility",
332
+ "arguments": {
333
+ "baseUrl": "https://example.com",
334
+ "standards": ["wcag21aa", "wcag244", "EN-301-549"],
335
+ "maxPages": 10,
336
+ "maxDepth": 2
337
+ }
338
+ }
339
+ ```
340
+
341
+ **Legacy wcagLevel parameter (still supported):**
342
+ ```json
343
+ {
344
+ "name": "test_website_accessibility",
345
+ "arguments": {
346
+ "baseUrl": "https://example.com",
347
+ "wcagLevel": "AA",
348
+ "maxPages": 20,
349
+ "maxDepth": 3
350
+ }
351
+ }
352
+ ```
353
+
238
354
  **Key Features of Website Testing:**
239
355
  - 🕷️ **Automatic Crawling**: Discovers pages by following links
240
356
  - 📊 **Site-wide Reports**: Aggregated accessibility metrics across all pages
@@ -263,7 +379,32 @@ Validate color combinations for WCAG compliance:
263
379
  #### 4. Get WCAG Rules (Full Mode Only)
264
380
 
265
381
  Retrieve information about WCAG accessibility rules:
382
+ **Query rules by standard presets:**
383
+ ```json
384
+ {
385
+ "name": "get_wcag_rules",
386
+ "arguments": {
387
+ "standardPresets": ["wcag-aa", "section508"],
388
+ "category": "color",
389
+ "search": "contrast",
390
+ "limit": 10
391
+ }
392
+ }
393
+ ```
394
+
395
+ **Query rules by specific standard tags:**
396
+ ```json
397
+ {
398
+ "name": "get_wcag_rules",
399
+ "arguments": {
400
+ "standards": ["wcag21aa", "wcag244", "EN-301-549"],
401
+ "requireAll": true,
402
+ "limit": 20
403
+ }
404
+ }
405
+ ```
266
406
 
407
+ **Legacy wcagLevel parameter (still supported):**
267
408
  ```json
268
409
  {
269
410
  "name": "get_wcag_rules",
@@ -158,67 +158,78 @@
158
158
  "title": "Color Contrast",
159
159
  "description": "Ensures the contrast between foreground and background colors meets WCAG 2 AA contrast ratio thresholds",
160
160
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/color-contrast",
161
- "successCriteria": "1.4.3"
161
+ "successCriteria": "1.4.3",
162
+ "applicableStandards": ["wcag2aa", "wcag21aa", "wcag22aa", "wcag143", "section508", "section508.22.g", "EN-301-549", "TTv5", "cat.color"]
162
163
  },
163
164
  "image-alt": {
164
165
  "title": "Images must have alternate text",
165
166
  "description": "Ensures <img> elements have alternate text or a role of none or presentation",
166
167
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/image-alt",
167
- "successCriteria": "1.1.1"
168
+ "successCriteria": "1.1.1",
169
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag111", "section508", "section508.22.a", "EN-301-549", "TTv5", "cat.text-alternatives"]
168
170
  },
169
171
  "label": {
170
172
  "title": "Form elements must have labels",
171
173
  "description": "Ensures every form element has a label",
172
174
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/label",
173
- "successCriteria": "1.3.1, 3.3.2, 4.1.2"
175
+ "successCriteria": "1.3.1, 3.3.2, 4.1.2",
176
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag131", "wcag332", "wcag412", "section508", "section508.22.n", "EN-301-549", "TTv5", "cat.forms"]
174
177
  },
175
178
  "link-name": {
176
179
  "title": "Links must have discernible text",
177
180
  "description": "Ensures links have discernible text",
178
181
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/link-name",
179
- "successCriteria": "2.4.4, 4.1.2"
182
+ "successCriteria": "2.4.4, 4.1.2",
183
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag244", "wcag412", "section508", "section508.22.a", "EN-301-549", "TTv5", "cat.name-role-value"]
180
184
  },
181
185
  "button-name": {
182
186
  "title": "Buttons must have discernible text",
183
187
  "description": "Ensures buttons have discernible text",
184
188
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/button-name",
185
- "successCriteria": "4.1.2"
189
+ "successCriteria": "4.1.2",
190
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag412", "section508", "section508.22.a", "EN-301-549", "TTv5", "cat.name-role-value"]
186
191
  },
187
192
  "heading-order": {
188
193
  "title": "Heading levels should only increase by one",
189
194
  "description": "Ensures the order of headings is semantically correct",
190
195
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/heading-order",
191
- "successCriteria": "1.3.1"
196
+ "successCriteria": "1.3.1",
197
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag131", "EN-301-549", "cat.semantics"]
192
198
  },
193
199
  "html-has-lang": {
194
200
  "title": "<html> element must have a lang attribute",
195
201
  "description": "Ensures every HTML document has a lang attribute",
196
202
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/html-has-lang",
197
- "successCriteria": "3.1.1"
203
+ "successCriteria": "3.1.1",
204
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag311", "section508", "section508.22.q", "EN-301-549", "TTv5", "cat.language"]
198
205
  },
199
206
  "aria-allowed-attr": {
200
207
  "title": "ARIA attributes must conform to valid names",
201
208
  "description": "Ensures ARIA attributes are allowed for an element's role",
202
209
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/aria-allowed-attr",
203
- "successCriteria": "4.1.2"
210
+ "successCriteria": "4.1.2",
211
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag412", "section508", "section508.22.a", "EN-301-549", "TTv5", "cat.aria"]
204
212
  },
205
213
  "aria-required-attr": {
206
214
  "title": "Required ARIA attributes must be provided",
207
215
  "description": "Ensures elements with ARIA roles have required ARIA attributes",
208
216
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/aria-required-attr",
209
- "successCriteria": "4.1.2"
217
+ "successCriteria": "4.1.2",
218
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag412", "section508", "section508.22.a", "EN-301-549", "TTv5", "cat.aria"]
210
219
  },
211
220
  "region": {
212
221
  "title": "All page content should be contained by landmarks",
213
222
  "description": "Ensures all page content is contained by landmarks",
214
223
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/region",
215
- "successCriteria": "1.3.1"
224
+ "successCriteria": "1.3.1",
225
+ "applicableStandards": ["wcag2a", "wcag21a", "wcag22a", "wcag131", "EN-301-549", "cat.keyboard"]
216
226
  },
217
227
  "target-size": {
218
228
  "title": "Ensure touch targets have sufficient size and spacing",
219
229
  "description": "Ensures touch targets are at least 24px by 24px",
220
230
  "helpUrl": "https://dequeuniversity.com/rules/axe/4.6/target-size",
221
- "successCriteria": "2.5.8"
231
+ "successCriteria": "2.5.8",
232
+ "applicableStandards": ["wcag22aa", "wcag258", "EN-301-549", "cat.sensory-and-visual-cues"]
222
233
  }
223
234
  },
224
235
  "defaultSettings": {
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAuBA,KAAK,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpC,UAAU,YAAY;IACpB,IAAI,EAAE,UAAU,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAuCD;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IAGtC,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAClD,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAClD,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,0BAA0B,CAAC,CAA6B;gBAEpD,MAAM,GAAE,YAAoD;IAwBxE;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAOrC;;OAEG;YACW,wBAAwB;IA8CtC;;OAEG;IACH,OAAO,CAAC,aAAa;IAwPrB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0B7B;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAW1B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA8BA,KAAK,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEpC,UAAU,YAAY;IACpB,IAAI,EAAE,UAAU,CAAC;IACjB,aAAa,EAAE,OAAO,CAAC;CACxB;AAuGD;;;GAGG;AACH,qBAAa,sBAAsB;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IAGtC,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAClD,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAClD,OAAO,CAAC,aAAa,CAAC,CAAgB;IACtC,OAAO,CAAC,0BAA0B,CAAC,CAA6B;gBAEpD,MAAM,GAAE,YAAoD;IAwBxE;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAO9B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAOxB;;OAEG;IACH,OAAO,CAAC,6BAA6B;IAOrC;;OAEG;YACW,wBAAwB;IA8CtC;;OAEG;IACH,OAAO,CAAC,aAAa;IA6VrB;;OAEG;IACH,OAAO,CAAC,qBAAqB;IA0B7B;;OAEG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC;IAW1B;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;CAS/B"}
package/dist/index.js CHANGED
@@ -9,13 +9,56 @@ import { ColorContrastTester } from './tools/color-contrast.js';
9
9
  import { WCAGValidator } from './tools/wcag-validator.js';
10
10
  import { WebsiteAccessibilityTester } from './tools/website-accessibility-tester.js';
11
11
  // Import utilities
12
- import { Logger, BrowserManager } from './utils/index.js';
13
- // Validation schemas
12
+ import { Logger, BrowserManager, combineStandardsAndPresets, shouldGenerateAdaGuidance, generateAdaGuidance } from './utils/index.js';
13
+ // Shared auth schemas
14
+ const CookieSchema = z.object({
15
+ name: z.string().min(1),
16
+ value: z.string().min(1),
17
+ domain: z.string().optional(),
18
+ path: z.string().default('/'),
19
+ expires: z.number().optional(),
20
+ httpOnly: z.boolean().default(false),
21
+ secure: z.boolean().default(true),
22
+ sameSite: z.enum(['Strict', 'Lax', 'None']).default('Lax')
23
+ });
24
+ const StorageStateSchema = z.object({
25
+ origin: z.string().url().optional(),
26
+ localStorage: z.record(z.string()).optional(),
27
+ sessionStorage: z.record(z.string()).optional()
28
+ });
29
+ const LoginStepSchema = z.object({
30
+ action: z.enum(['goto', 'type', 'click', 'waitForSelector', 'waitForNavigation', 'waitForTimeout']),
31
+ selector: z.string().optional(),
32
+ value: z.string().optional(),
33
+ timeout: z.number().optional()
34
+ });
35
+ const LoginFlowSchema = z.object({
36
+ loginUrl: z.string().url('Must be a valid login URL'),
37
+ steps: z.array(LoginStepSchema).min(1),
38
+ successSelector: z.string().optional(),
39
+ successUrlContains: z.string().optional()
40
+ });
41
+ const AuthSchema = z.object({
42
+ headers: z.record(z.string()).optional(),
43
+ cookies: z.array(CookieSchema).optional(),
44
+ storageState: z.array(StorageStateSchema).optional(),
45
+ loginFlow: LoginFlowSchema.optional(),
46
+ preNavigationScripts: z.array(z.string()).optional()
47
+ });
48
+ // Simplified validation schemas
14
49
  const TestAccessibilitySchema = z.object({
15
50
  target: z.string().min(1, 'Target URL or HTML is required'),
16
51
  type: z.enum(['url', 'html']).default('url'),
17
52
  level: z.enum(['basic', 'full']).default('basic'),
18
- wcagLevel: z.enum(['A', 'AA', 'AAA']).default('AA')
53
+ auth: AuthSchema.optional(),
54
+ standards: z.array(z.string()).optional(),
55
+ standardPresets: z.array(z.enum([
56
+ 'wcag-a', 'wcag-aa', 'wcag-aaa',
57
+ 'section508', 'section508-full',
58
+ 'en301549', 'trustedtester', 'rgaa',
59
+ 'ada', 'best-practice', 'all-standards'
60
+ ])).optional(),
61
+ requireAll: z.boolean().default(true)
19
62
  });
20
63
  const ColorContrastSchema = z.object({
21
64
  foreground: z.string().min(1, 'Foreground color is required'),
@@ -24,14 +67,20 @@ const ColorContrastSchema = z.object({
24
67
  isBold: z.boolean().default(false)
25
68
  });
26
69
  const GetWCAGRulesSchema = z.object({
27
- wcagLevel: z.enum(['A', 'AA', 'AAA']).optional(),
28
70
  category: z.string().optional(),
29
71
  search: z.string().optional(),
30
- limit: z.number().min(1).max(50).default(20)
72
+ limit: z.number().min(1).max(50).default(20),
73
+ standards: z.array(z.string()).optional(),
74
+ standardPresets: z.array(z.enum([
75
+ 'wcag-a', 'wcag-aa', 'wcag-aaa',
76
+ 'section508', 'section508-full',
77
+ 'en301549', 'trustedtester', 'rgaa',
78
+ 'ada', 'best-practice', 'all-standards'
79
+ ])).optional(),
80
+ requireAll: z.boolean().default(true)
31
81
  });
32
82
  const TestWebsiteSchema = z.object({
33
83
  baseUrl: z.string().url('Must be a valid URL'),
34
- wcagLevel: z.enum(['A', 'AA', 'AAA']).default('AA'),
35
84
  fullAnalysis: z.boolean().default(false),
36
85
  maxPages: z.number().min(1).max(100).default(20),
37
86
  maxDepth: z.number().min(1).max(5).default(3),
@@ -41,7 +90,17 @@ const TestWebsiteSchema = z.object({
41
90
  continueOnError: z.boolean().default(true),
42
91
  respectRobots: z.boolean().default(true),
43
92
  delay: z.number().min(0).max(10000).default(1000),
44
- stayOnDomain: z.boolean().default(true)
93
+ stayOnDomain: z.boolean().default(true),
94
+ allowedDomains: z.array(z.string()).optional(),
95
+ auth: AuthSchema.optional(),
96
+ standards: z.array(z.string()).optional(),
97
+ standardPresets: z.array(z.enum([
98
+ 'wcag-a', 'wcag-aa', 'wcag-aaa',
99
+ 'section508', 'section508-full',
100
+ 'en301549', 'trustedtester', 'rgaa',
101
+ 'ada', 'best-practice', 'all-standards'
102
+ ])).optional(),
103
+ requireAll: z.boolean().default(true)
45
104
  });
46
105
  /**
47
106
  * Unified MCP server class for accessibility testing
@@ -65,7 +124,7 @@ export class AccessibilityMCPServer {
65
124
  this.browserManager = new BrowserManager();
66
125
  this.server = new Server({
67
126
  name: 'accessibility-mcp-server',
68
- version: '1.0.7',
127
+ version: '1.0.6',
69
128
  }, {
70
129
  capabilities: {
71
130
  tools: {},
@@ -157,7 +216,7 @@ export class AccessibilityMCPServer {
157
216
  const basicTools = [
158
217
  {
159
218
  name: 'test_accessibility',
160
- description: 'Test URL or HTML content for accessibility issues',
219
+ description: 'Test URL or HTML content for accessibility issues using multiple standards (WCAG, Section 508, EN 301 549, etc.)',
161
220
  inputSchema: {
162
221
  type: 'object',
163
222
  properties: {
@@ -177,11 +236,27 @@ export class AccessibilityMCPServer {
177
236
  default: 'basic',
178
237
  description: 'Testing depth level'
179
238
  },
180
- wcagLevel: {
181
- type: 'string',
182
- enum: ['A', 'AA', 'AAA'],
183
- default: 'AA',
184
- description: 'WCAG compliance level'
239
+ standards: {
240
+ type: 'array',
241
+ items: { type: 'string' },
242
+ description: 'Specific standard tags to test (e.g., ["wcag2aa", "section508", "EN-301-549"])'
243
+ },
244
+ standardPresets: {
245
+ type: 'array',
246
+ items: {
247
+ type: 'string',
248
+ enum: ['wcag-a', 'wcag-aa', 'wcag-aaa', 'section508', 'section508-full', 'en301549', 'trustedtester', 'rgaa', 'ada', 'best-practice', 'all-standards']
249
+ },
250
+ description: 'Standard presets to test against (defaults to wcag-aa if not specified)'
251
+ },
252
+ requireAll: {
253
+ type: 'boolean',
254
+ default: true,
255
+ description: 'Whether all standards must match (AND logic) or any standard (OR logic)'
256
+ },
257
+ auth: {
258
+ type: 'object',
259
+ description: 'Optional authentication context for protected pages'
185
260
  }
186
261
  },
187
262
  required: ['target']
@@ -197,12 +272,6 @@ export class AccessibilityMCPServer {
197
272
  type: 'string',
198
273
  description: 'Base URL of the website to test'
199
274
  },
200
- wcagLevel: {
201
- type: 'string',
202
- enum: ['A', 'AA', 'AAA'],
203
- default: 'AA',
204
- description: 'WCAG compliance level'
205
- },
206
275
  fullAnalysis: {
207
276
  type: 'boolean',
208
277
  default: false,
@@ -260,6 +329,33 @@ export class AccessibilityMCPServer {
260
329
  type: 'boolean',
261
330
  default: true,
262
331
  description: 'Whether to restrict crawl to the main domain'
332
+ },
333
+ allowedDomains: {
334
+ type: 'array',
335
+ items: { type: 'string' },
336
+ description: 'Additional domains allowed during crawl (e.g., IdP)'
337
+ },
338
+ standards: {
339
+ type: 'array',
340
+ items: { type: 'string' },
341
+ description: 'Specific standard tags to test (e.g., [\"wcag2aa\", \"section508\"])'
342
+ },
343
+ standardPresets: {
344
+ type: 'array',
345
+ items: {
346
+ type: 'string',
347
+ enum: ['wcag-a', 'wcag-aa', 'wcag-aaa', 'section508', 'section508-full', 'en301549', 'trustedtester', 'rgaa', 'ada', 'best-practice', 'all-standards']
348
+ },
349
+ description: 'Standard presets to test against (defaults to wcag-aa)'
350
+ },
351
+ requireAll: {
352
+ type: 'boolean',
353
+ default: true,
354
+ description: 'Whether all standards must match (AND logic)'
355
+ },
356
+ auth: {
357
+ type: 'object',
358
+ description: 'Optional authentication context for protected sites'
263
359
  }
264
360
  },
265
361
  required: ['baseUrl']
@@ -299,15 +395,10 @@ export class AccessibilityMCPServer {
299
395
  ...basicTools,
300
396
  {
301
397
  name: 'get_wcag_rules',
302
- description: 'Get information about WCAG accessibility rules',
398
+ description: 'Get information about accessibility rules across multiple standards (WCAG, Section 508, EN 301 549, etc.)',
303
399
  inputSchema: {
304
400
  type: 'object',
305
401
  properties: {
306
- wcagLevel: {
307
- type: 'string',
308
- enum: ['A', 'AA', 'AAA'],
309
- description: 'Filter rules by WCAG level'
310
- },
311
402
  category: {
312
403
  type: 'string',
313
404
  description: 'Filter rules by category'
@@ -322,6 +413,24 @@ export class AccessibilityMCPServer {
322
413
  maximum: 50,
323
414
  default: 20,
324
415
  description: 'Maximum number of rules to return'
416
+ },
417
+ standards: {
418
+ type: 'array',
419
+ items: { type: 'string' },
420
+ description: 'Specific standard tags to filter by'
421
+ },
422
+ standardPresets: {
423
+ type: 'array',
424
+ items: {
425
+ type: 'string',
426
+ enum: ['wcag-a', 'wcag-aa', 'wcag-aaa', 'section508', 'section508-full', 'en301549', 'trustedtester', 'rgaa', 'ada', 'best-practice', 'all-standards']
427
+ },
428
+ description: 'Standard presets to filter by'
429
+ },
430
+ requireAll: {
431
+ type: 'boolean',
432
+ default: true,
433
+ description: 'Whether all standards must match (AND logic)'
325
434
  }
326
435
  }
327
436
  }
@@ -334,12 +443,22 @@ export class AccessibilityMCPServer {
334
443
  // Handle tool calls with centralized error handling
335
444
  this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
336
445
  const { name, arguments: args } = request.params;
337
- this.logger.info(`Executing tool: ${name}`, { args });
446
+ const safeArgs = args && typeof args === 'object'
447
+ ? { ...args, auth: args?.auth ? '[redacted]' : undefined }
448
+ : args;
449
+ this.logger.info(`Executing tool: ${name}`, { args: safeArgs });
338
450
  let result;
339
451
  switch (name) {
340
452
  case 'test_accessibility': {
341
453
  const params = TestAccessibilitySchema.parse(args);
342
- result = await this.executeWithErrorHandling(() => this.getAccessibilityTester().testTarget(params), 'Accessibility test');
454
+ result = await this.executeWithErrorHandling(async () => {
455
+ const testResult = await this.getAccessibilityTester().testTarget(params);
456
+ // Generate ADA guidance if ada preset is used
457
+ if (params.standardPresets && shouldGenerateAdaGuidance(params.standardPresets)) {
458
+ testResult.adaGuidance = generateAdaGuidance(testResult);
459
+ }
460
+ return testResult;
461
+ }, 'Accessibility test');
343
462
  break;
344
463
  }
345
464
  case 'check_color_contrast': {
@@ -357,7 +476,32 @@ export class AccessibilityMCPServer {
357
476
  throw new McpError(ErrorCode.MethodNotFound, 'WCAG rules not available in simple mode');
358
477
  }
359
478
  const params = GetWCAGRulesSchema.parse(args || {});
360
- result = await this.executeWithErrorHandling(() => this.getWCAGValidator().getRules(params), 'WCAG rules retrieval');
479
+ result = await this.executeWithErrorHandling(async () => {
480
+ const validator = this.getWCAGValidator();
481
+ // If standards or presets provided, use standards-based filtering
482
+ if (params.standards || params.standardPresets) {
483
+ const standards = combineStandardsAndPresets(params.standards, params.standardPresets);
484
+ const rules = await validator.getRulesByStandards(standards, params.requireAll ?? true);
485
+ // Apply additional filters
486
+ let filteredRules = rules;
487
+ if (params.category) {
488
+ filteredRules = filteredRules.filter(rule => rule.categories.some(cat => cat.toLowerCase().includes(params.category.toLowerCase())));
489
+ }
490
+ if (params.search) {
491
+ const searchLower = params.search.toLowerCase();
492
+ filteredRules = filteredRules.filter(rule => rule.title.toLowerCase().includes(searchLower) ||
493
+ rule.description.toLowerCase().includes(searchLower) ||
494
+ rule.id.toLowerCase().includes(searchLower));
495
+ }
496
+ if (params.limit && filteredRules.length > params.limit) {
497
+ filteredRules = filteredRules.slice(0, params.limit);
498
+ }
499
+ return filteredRules;
500
+ }
501
+ // Fallback to legacy getRules method
502
+ const response = await validator.getRules(params);
503
+ return response.data;
504
+ }, 'WCAG rules retrieval');
361
505
  break;
362
506
  }
363
507
  default:
@@ -434,7 +578,7 @@ const args = process.argv.slice(2);
434
578
  // Show help information
435
579
  if (args.includes('--help') || args.includes('-h')) {
436
580
  console.log(`
437
- Accessibility MCP Server v1.0.7
581
+ Accessibility MCP Server v1.0.6
438
582
  A Model Context Protocol server for web accessibility testing with WCAG compliance.
439
583
 
440
584
  Usage:
@@ -469,7 +613,7 @@ For more information, visit: https://github.com/your-repo/accessibility-mcp
469
613
  }
470
614
  // Show version
471
615
  if (args.includes('--version') || args.includes('-v')) {
472
- console.log('1.0.7');
616
+ console.log('1.0.6');
473
617
  process.exit(0);
474
618
  }
475
619
  // Set MCP mode environment variable when running as MCP server