@atlaskit/ads-mcp 0.2.5 → 0.4.0

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 (57) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +57 -1
  3. package/dist/cjs/index.js +16 -5
  4. package/dist/cjs/instructions.js +1 -1
  5. package/dist/cjs/tools/analyze-accessibility/index.js +483 -0
  6. package/dist/cjs/tools/get-accessibility-guidelines/index.js +204 -0
  7. package/dist/cjs/tools/{get-icons → get-all-icons}/index.js +6 -6
  8. package/dist/cjs/tools/{get-tokens → get-all-tokens}/index.js +7 -8
  9. package/dist/cjs/tools/search-icons/index.js +138 -0
  10. package/dist/cjs/tools/search-tokens/index.js +106 -0
  11. package/dist/cjs/tools/suggest-accessibility-fixes/fixes.js +387 -0
  12. package/dist/cjs/tools/suggest-accessibility-fixes/index.js +185 -0
  13. package/dist/cjs/tools/suggest-accessibility-fixes/keywords.js +34 -0
  14. package/dist/es2019/index.js +16 -5
  15. package/dist/es2019/instructions.js +12 -1
  16. package/dist/es2019/tools/analyze-accessibility/index.js +457 -0
  17. package/dist/es2019/tools/get-accessibility-guidelines/index.js +312 -0
  18. package/dist/es2019/tools/{get-icons → get-all-icons}/index.js +4 -4
  19. package/dist/es2019/tools/get-all-tokens/index.js +34 -0
  20. package/dist/es2019/tools/search-icons/index.js +126 -0
  21. package/dist/es2019/tools/search-tokens/index.js +96 -0
  22. package/dist/es2019/tools/suggest-accessibility-fixes/fixes.js +705 -0
  23. package/dist/es2019/tools/suggest-accessibility-fixes/index.js +143 -0
  24. package/dist/es2019/tools/suggest-accessibility-fixes/keywords.js +28 -0
  25. package/dist/esm/index.js +16 -5
  26. package/dist/esm/instructions.js +1 -1
  27. package/dist/esm/tools/analyze-accessibility/index.js +476 -0
  28. package/dist/esm/tools/get-accessibility-guidelines/index.js +197 -0
  29. package/dist/esm/tools/{get-icons → get-all-icons}/index.js +5 -5
  30. package/dist/esm/tools/{get-tokens → get-all-tokens}/index.js +6 -7
  31. package/dist/esm/tools/search-icons/index.js +131 -0
  32. package/dist/esm/tools/search-tokens/index.js +99 -0
  33. package/dist/esm/tools/suggest-accessibility-fixes/fixes.js +381 -0
  34. package/dist/esm/tools/suggest-accessibility-fixes/index.js +178 -0
  35. package/dist/esm/tools/suggest-accessibility-fixes/keywords.js +28 -0
  36. package/dist/types/instructions.d.ts +1 -1
  37. package/dist/types/tools/analyze-accessibility/index.d.ts +56 -0
  38. package/dist/types/tools/get-accessibility-guidelines/index.d.ts +26 -0
  39. package/dist/{types-ts4.5/tools/get-tokens → types/tools/get-all-icons}/index.d.ts +2 -2
  40. package/dist/types/tools/{get-tokens → get-all-tokens}/index.d.ts +2 -2
  41. package/dist/types/tools/search-icons/index.d.ts +38 -0
  42. package/dist/types/tools/search-tokens/index.d.ts +38 -0
  43. package/dist/types/tools/suggest-accessibility-fixes/fixes.d.ts +17 -0
  44. package/dist/types/tools/suggest-accessibility-fixes/index.d.ts +28 -0
  45. package/dist/types/tools/suggest-accessibility-fixes/keywords.d.ts +12 -0
  46. package/dist/types-ts4.5/instructions.d.ts +1 -1
  47. package/dist/types-ts4.5/tools/analyze-accessibility/index.d.ts +56 -0
  48. package/dist/types-ts4.5/tools/get-accessibility-guidelines/index.d.ts +26 -0
  49. package/dist/types-ts4.5/tools/{get-icons → get-all-icons}/index.d.ts +2 -2
  50. package/dist/{types/tools/get-icons → types-ts4.5/tools/get-all-tokens}/index.d.ts +2 -2
  51. package/dist/types-ts4.5/tools/search-icons/index.d.ts +38 -0
  52. package/dist/types-ts4.5/tools/search-tokens/index.d.ts +38 -0
  53. package/dist/types-ts4.5/tools/suggest-accessibility-fixes/fixes.d.ts +17 -0
  54. package/dist/types-ts4.5/tools/suggest-accessibility-fixes/index.d.ts +28 -0
  55. package/dist/types-ts4.5/tools/suggest-accessibility-fixes/keywords.d.ts +12 -0
  56. package/package.json +10 -3
  57. package/dist/es2019/tools/get-tokens/index.js +0 -35
@@ -3,10 +3,15 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
5
5
  import { instructions } from './instructions';
6
+ import { analyzeAccessibilityTool, analyzeLocalhostAccessibilityTool, listAnalyzeAccessibilityTool, listAnalyzeLocalhostAccessibilityTool } from './tools/analyze-accessibility';
7
+ import { getAccessibilityGuidelinesTool, listGetAccessibilityGuidelinesTool } from './tools/get-accessibility-guidelines';
8
+ import { getAllIconsTool, listGetAllIconsTool } from './tools/get-all-icons';
9
+ import { getAllTokensTool, listGetAllTokensTool } from './tools/get-all-tokens';
6
10
  import { getComponentDetailsTool, listGetComponentDetailsTool } from './tools/get-component-details';
7
11
  import { getComponentsTool, listGetComponentsTool } from './tools/get-components';
8
- import { getIconsTool, listGetIconsTool } from './tools/get-icons';
9
- import { getTokensTool, listGetTokensTool } from './tools/get-tokens';
12
+ import { listSearchIconsTool, searchIconsTool } from './tools/search-icons';
13
+ import { listSearchTokensTool, searchTokensTool } from './tools/search-tokens';
14
+ import { listSuggestAccessibilityFixesTool, suggestAccessibilityFixesTool } from './tools/suggest-accessibility-fixes';
10
15
 
11
16
  // eslint-disable-next-line import/no-extraneous-dependencies -- this uses require because not all node versions this package supports use the same import assertions/attributes
12
17
  const pkgJson = require('@atlaskit/ads-mcp/package.json');
@@ -22,14 +27,20 @@ const server = new Server({
22
27
  });
23
28
  server.setRequestHandler(ListToolsRequestSchema, async () => {
24
29
  return {
25
- tools: [listGetTokensTool, listGetComponentsTool, listGetComponentDetailsTool, listGetIconsTool]
30
+ tools: [listGetAllTokensTool, listGetComponentsTool, listGetComponentDetailsTool, listGetAllIconsTool, listSearchIconsTool, listSearchTokensTool, listAnalyzeAccessibilityTool, listAnalyzeLocalhostAccessibilityTool, listGetAccessibilityGuidelinesTool, listSuggestAccessibilityFixesTool]
26
31
  };
27
32
  });
28
33
  const callTools = {
29
- get_tokens: getTokensTool,
34
+ get_all_tokens: getAllTokensTool,
35
+ search_tokens: searchTokensTool,
30
36
  get_components: getComponentsTool,
31
37
  get_component_details: getComponentDetailsTool,
32
- get_icons: getIconsTool
38
+ get_all_icons: getAllIconsTool,
39
+ search_icons: searchIconsTool,
40
+ analyze_accessibility: analyzeAccessibilityTool,
41
+ analyze_localhost_accessibility: analyzeLocalhostAccessibilityTool,
42
+ get_accessibility_guidelines: getAccessibilityGuidelinesTool,
43
+ suggest_accessibility_fixes: suggestAccessibilityFixesTool
33
44
  };
34
45
 
35
46
  // Handle tool execution
@@ -1,5 +1,16 @@
1
1
  export const instructions = `
2
2
  You are an expert in the Atlassian Design System (aka ADS). You are able to answer questions about the design system and provide guidance on what offerings to use when building user interfaces.
3
3
 
4
- You are able to use the provided tools to help answer your questions, but may also access https://atlassian.design/llms.txt or https://atlassian.design/ directly for deeper research and information.
4
+ You have special expertise in accessibility and can help ensure that interfaces built with ADS components are accessible to all users. You can analyze code for accessibility violations, provide specific fix suggestions, and offer guidance on accessibility best practices.
5
+
6
+ You are able to use the provided tools to help answer your questions, but may also access https://atlassian.design/llms.txt, https://atlassian.design/llms-a11y.txt, or https://atlassian.design/ directly for deeper research and information.
7
+
8
+ Accessibility Tools Available:
9
+ - analyze_accessibility: Analyze React component code for accessibility violations
10
+ - get_accessibility_guidelines: Get specific accessibility guidelines and best practices
11
+ - suggest_accessibility_fixes: Get specific fix suggestions for accessibility violations
12
+ - get_all_tokens: Get all tokens and their example values
13
+ - search_tokens: Search for token(s) and their example value(s)
14
+ - get_all_icons: Get all icons and their usage
15
+ - search_icons: Search for icon(s) and their usage
5
16
  `;
@@ -0,0 +1,457 @@
1
+ import { AxePuppeteer } from '@axe-core/puppeteer';
2
+ import axe from 'axe-core';
3
+ import puppeteer from 'puppeteer';
4
+ import { z } from 'zod';
5
+ import { zodToJsonSchema } from 'zod-to-json-schema';
6
+ const inputSchema = z.object({
7
+ code: z.string().describe('React component code to analyze for accessibility'),
8
+ componentName: z.string().optional().describe('Name of the component being analyzed'),
9
+ context: z.string().optional().describe('Additional context about the component usage'),
10
+ includePatternAnalysis: z.boolean().optional().default(true).describe('Include pattern-based analysis in addition to axe-core')
11
+ });
12
+ export const listAnalyzeAccessibilityTool = {
13
+ name: 'analyze_accessibility',
14
+ description: `Analyze React component code for accessibility violations using axe-core and intelligently generate Atlassian Design System specific suggestions. This tool performs comprehensive accessibility testing and dynamically creates ADS-specific fixes based on violation patterns.
15
+
16
+ Use this tool when:
17
+ - Reviewing component code for accessibility compliance
18
+ - Getting suggestions for improving accessibility
19
+ - Understanding how to use ADS components accessibly
20
+ - Identifying potential WCAG violations
21
+ - Running automated accessibility testing
22
+
23
+ The tool will analyze the code and provide:
24
+ - Comprehensive axe-core accessibility analysis results
25
+ - List of accessibility violations found (WCAG 2.1 AA compliant)
26
+ - Intelligently generated ADS-specific fix suggestions
27
+ - References to relevant fix patterns in llms-a11y.txt
28
+ - Code examples for implementing fixes
29
+ - Severity levels and impact assessment
30
+
31
+ Features:
32
+ - Uses axe-core for industry-standard accessibility testing
33
+ - Converts JSX to HTML for accurate analysis
34
+ - Intelligently maps violations to ADS-specific fixes
35
+ - References fix patterns from llms-a11y.txt documentation
36
+ - Includes fallback pattern analysis if axe-core fails
37
+ - Provides detailed violation descriptions and help text
38
+ - Dynamically generates fix suggestions based on violation type`,
39
+ annotations: {
40
+ title: 'Analyze Accessibility',
41
+ readOnlyHint: true,
42
+ destructiveHint: false,
43
+ idempotentHint: true,
44
+ openWorldHint: true
45
+ },
46
+ inputSchema: zodToJsonSchema(inputSchema)
47
+ };
48
+ const urlInputSchema = z.object({
49
+ url: z.string().describe('The URL to analyze for accessibility (e.g. http://localhost:9000)'),
50
+ componentName: z.string().optional().describe('Name of the component being analyzed'),
51
+ context: z.string().optional().describe('Additional context about the component usage'),
52
+ selector: z.string().optional().describe('CSS selector to target a specific element for analysis (e.g. "#my-form", ".component-class")')
53
+ });
54
+ export const listAnalyzeLocalhostAccessibilityTool = {
55
+ name: 'analyze_localhost_accessibility',
56
+ description: `Analyze a live web page (e.g. localhost:9000) for accessibility violations using axe-core and generate Atlassian Design System specific suggestions.
57
+
58
+ Use this tool to:
59
+ - Analyze running local dev servers or deployed URLs
60
+ - Get comprehensive accessibility reports for any web page
61
+ - Receive ADS-specific fix suggestions and code examples
62
+ - Target specific elements using CSS selectors for focused analysis
63
+
64
+ Parameters:
65
+ - url: The URL to analyze (must be accessible from the server)
66
+ - componentName: (optional) Name of the component/page
67
+ - context: (optional) Additional context about the usage
68
+ - selector: (optional) CSS selector to target a specific element (e.g. "#my-form", ".component-class")
69
+
70
+ Returns:
71
+ - Accessibility violations, suggestions, and ADS-specific fixes
72
+ - References to relevant fix patterns in llms-a11y.txt
73
+ - Code examples for implementing fixes
74
+ - Severity levels and impact assessment
75
+ `,
76
+ annotations: {
77
+ title: 'Analyze Localhost Accessibility',
78
+ readOnlyHint: true,
79
+ destructiveHint: false,
80
+ idempotentHint: true,
81
+ openWorldHint: true
82
+ },
83
+ inputSchema: zodToJsonSchema(urlInputSchema)
84
+ };
85
+
86
+ // Common accessibility patterns to detect in code
87
+ const accessibilityPatterns = [{
88
+ pattern: /<button[^>]*>(?!.*aria-label|.*>.*<\/button>)/g,
89
+ violation: 'Button without accessible text',
90
+ severity: 'error',
91
+ suggestion: 'Use the suggest-accessibility-fixes tool for ADS Button solutions. Describe the issue as "button missing label", "empty button", or "button needs text".'
92
+ }, {
93
+ pattern: /<img[^>]*>(?!.*alt=)/g,
94
+ violation: 'Image without alt text',
95
+ severity: 'error',
96
+ suggestion: 'Use the suggest-accessibility-fixes tool for ADS Image solutions. Describe the issue as "image missing alt", "missing alt text", or "image accessibility".'
97
+ }, {
98
+ pattern: /<div[^>]*onClick[^>]*>/g,
99
+ violation: 'Clickable div without accessibility',
100
+ severity: 'warning',
101
+ suggestion: 'Use the suggest-accessibility-fixes tool for ADS solutions. Describe the issue as "clickable div", "interactive div", or "div with click handler".'
102
+ }, {
103
+ pattern: /color:\s*['"]#[0-9a-fA-F]{3,6}['"]/g,
104
+ violation: 'Hardcoded color values',
105
+ severity: 'warning',
106
+ suggestion: 'Use the suggest-accessibility-fixes tool for design token solutions. Describe the issue as "hardcoded colors", "hex colors", or "design tokens".'
107
+ }, {
108
+ pattern: /<input[^>]*>(?!.*id=)/g,
109
+ violation: 'Input without associated label',
110
+ severity: 'error',
111
+ suggestion: 'Use the suggest-accessibility-fixes tool for ADS form solutions. Describe the issue as "input missing label", "form field without label", or "unlabeled input".'
112
+ }, {
113
+ pattern: /<div[^>]*role="button"[^>]*>/g,
114
+ violation: 'Custom button without full accessibility',
115
+ severity: 'warning',
116
+ suggestion: 'Use the suggest-accessibility-fixes tool for ADS Button/Focusable solutions. Describe the issue as "custom button", "div with button role", or "interactive element".'
117
+ }, {
118
+ pattern: /style=\{[^}]*color[^}]*\}/g,
119
+ violation: 'Inline color styles',
120
+ severity: 'warning',
121
+ suggestion: 'Use the suggest-accessibility-fixes tool for design token solutions. Describe the issue as "inline styles", "hardcoded colors", or "color tokens".'
122
+ }];
123
+
124
+ // ADS accessibility guidelines reference
125
+ const adsGuidelines = {
126
+ buttons: {
127
+ title: 'Button Accessibility',
128
+ guidelines: ['Always provide accessible labels for buttons', 'Use Button component for standard interactions', 'Use Focusable component for custom interactive elements', 'Avoid disabled buttons with tooltips', 'Ensure focus indicators are visible']
129
+ },
130
+ forms: {
131
+ title: 'Form Accessibility',
132
+ guidelines: ['Use TextField component for consistent labeling', 'Associate labels with inputs using id and htmlFor', 'Provide clear error messages with aria-describedby', 'Use MessageWrapper for form validation announcements']
133
+ },
134
+ images: {
135
+ title: 'Image Accessibility',
136
+ guidelines: ['Use Image component with proper alt text', 'Keep alt text under 125 characters', 'Leave alt="" for decorative images', 'Describe the purpose, not just the content']
137
+ },
138
+ colors: {
139
+ title: 'Color and Contrast',
140
+ guidelines: ['Use design tokens for consistent contrast ratios', 'Never rely on color alone for information', 'Use color.text tokens for proper contrast', 'Test with high contrast mode']
141
+ }
142
+ };
143
+
144
+ // Helper function to map axe-core violations to ADS-specific fixes
145
+ function mapAxeViolationsToADSFixes(violations) {
146
+ return violations.map(violation => {
147
+ const adsFix = generateADSFixForViolation(violation);
148
+ return {
149
+ ...violation,
150
+ type: adsFix.title,
151
+ // Use the specific fix key that matches fixes.ts
152
+ adsFix,
153
+ severity: violation.impact === 'critical' || violation.impact === 'serious' ? 'error' : 'warning'
154
+ };
155
+ });
156
+ }
157
+
158
+ // Helper function to provide ADS-specific guidance for axe-core violations
159
+ function generateADSFixForViolation(violation) {
160
+ const {
161
+ id,
162
+ description,
163
+ help,
164
+ tags
165
+ } = violation;
166
+
167
+ // Provide general guidance without trying to map to specific fixes.ts keys
168
+ const adsFix = `Use the suggest-accessibility-fixes tool to get specific ADS component solutions. Describe the issue using the violation details: "${help}" or in your own words (e.g., "button has no text", "missing alt text", "form field needs label").`;
169
+ return {
170
+ title: help,
171
+ // Use axe-core's human-readable description
172
+ description: description,
173
+ adsFix,
174
+ example: 'The suggest-accessibility-fixes tool provides detailed code examples and ADS component solutions',
175
+ violationId: id,
176
+ axeHelp: help,
177
+ tags,
178
+ wcagTags: tags.filter(tag => tag.startsWith('wcag')),
179
+ // Extract WCAG compliance info
180
+ reference: `https://atlassian.design/llms-a11y.txt`,
181
+ recommendations: ['Use ADS components for better accessibility out of the box', 'Reference the suggest-accessibility-fixes tool for specific solutions', 'Test with keyboard navigation and screen readers', 'Use automated accessibility testing tools']
182
+ };
183
+ }
184
+ export const analyzeAccessibilityTool = async params => {
185
+ const {
186
+ code,
187
+ componentName,
188
+ context,
189
+ includePatternAnalysis = true
190
+ } = params;
191
+ const violations = [];
192
+ const suggestions = [];
193
+ const axeResults = {};
194
+ try {
195
+ var _axeResults$violation, _axeResults$passes, _axeResults$incomplet;
196
+ // Run axe-core analysis
197
+ const results = await axe.run({
198
+ fromFrames: ['iframe', 'html']
199
+ });
200
+
201
+ // Process axe-core results
202
+ if (results.violations && results.violations.length > 0) {
203
+ const adsViolations = mapAxeViolationsToADSFixes(results.violations);
204
+ violations.push(...adsViolations);
205
+ axeResults.violations = results.violations;
206
+ axeResults.passes = results.passes;
207
+ axeResults.incomplete = results.incomplete;
208
+ }
209
+
210
+ // Include pattern-based analysis if requested
211
+ if (includePatternAnalysis) {
212
+ accessibilityPatterns.forEach(pattern => {
213
+ const matches = code.match(pattern.pattern);
214
+ if (matches) {
215
+ violations.push({
216
+ type: pattern.violation,
217
+ severity: pattern.severity,
218
+ count: matches.length,
219
+ suggestion: pattern.suggestion,
220
+ adsFix: 'Use the suggest-accessibility-fixes tool for specific ADS component solutions',
221
+ example: 'The suggest-accessibility-fixes tool provides detailed code examples',
222
+ source: 'pattern-analysis'
223
+ });
224
+ }
225
+ });
226
+ }
227
+
228
+ // Generate ADS-specific suggestions
229
+ if (violations.length > 0) {
230
+ suggestions.push({
231
+ title: 'Accessibility Improvements Needed',
232
+ description: `Found ${violations.length} accessibility issues in your code.`,
233
+ violations,
234
+ nextSteps: ['Review each violation and apply the suggested fixes', 'Use ADS components instead of custom implementations', 'Test with screen readers and keyboard navigation', 'Run automated accessibility tests']
235
+ });
236
+ }
237
+
238
+ // Provide relevant ADS guidelines
239
+ const relevantGuidelines = [];
240
+ if (code.includes('button') || code.includes('onClick')) {
241
+ relevantGuidelines.push(adsGuidelines.buttons);
242
+ }
243
+ if (code.includes('input') || code.includes('form')) {
244
+ relevantGuidelines.push(adsGuidelines.forms);
245
+ }
246
+ if (code.includes('img') || code.includes('image')) {
247
+ relevantGuidelines.push(adsGuidelines.images);
248
+ }
249
+ if (code.includes('color') || code.includes('style')) {
250
+ relevantGuidelines.push(adsGuidelines.colors);
251
+ }
252
+
253
+ // Generate summary
254
+ const summary = {
255
+ componentName: componentName || 'Unknown component',
256
+ totalViolations: violations.length,
257
+ severityBreakdown: {
258
+ error: violations.filter(v => v.severity === 'error').length,
259
+ warning: violations.filter(v => v.severity === 'warning').length
260
+ },
261
+ context: context || 'No additional context provided',
262
+ axeResults: {
263
+ violations: ((_axeResults$violation = axeResults.violations) === null || _axeResults$violation === void 0 ? void 0 : _axeResults$violation.length) || 0,
264
+ passes: ((_axeResults$passes = axeResults.passes) === null || _axeResults$passes === void 0 ? void 0 : _axeResults$passes.length) || 0,
265
+ incomplete: ((_axeResults$incomplet = axeResults.incomplete) === null || _axeResults$incomplet === void 0 ? void 0 : _axeResults$incomplet.length) || 0
266
+ }
267
+ };
268
+ return {
269
+ content: [{
270
+ type: 'text',
271
+ text: JSON.stringify({
272
+ summary,
273
+ violations,
274
+ suggestions,
275
+ relevantGuidelines,
276
+ axeResults,
277
+ recommendations: ['Use ADS components for better accessibility out of the box', 'Reference https://atlassian.design/llms-a11y.txt for detailed guidelines', 'Test with keyboard navigation and screen readers', 'Use automated accessibility testing tools']
278
+ }, null, 2)
279
+ }]
280
+ };
281
+ } catch (error) {
282
+ // Fallback to pattern-based analysis if axe-core fails
283
+ // console.warn('Axe-core analysis failed, falling back to pattern analysis:', error);
284
+
285
+ // Run pattern analysis as fallback
286
+ accessibilityPatterns.forEach(pattern => {
287
+ const matches = code.match(pattern.pattern);
288
+ if (matches) {
289
+ violations.push({
290
+ type: pattern.violation,
291
+ severity: pattern.severity,
292
+ count: matches.length,
293
+ suggestion: pattern.suggestion,
294
+ adsFix: 'Use the suggest-accessibility-fixes tool for specific ADS component solutions',
295
+ example: 'The suggest-accessibility-fixes tool provides detailed code examples',
296
+ source: 'pattern-analysis-fallback'
297
+ });
298
+ }
299
+ });
300
+ return {
301
+ content: [{
302
+ type: 'text',
303
+ text: JSON.stringify({
304
+ summary: {
305
+ componentName: componentName || 'Unknown component',
306
+ totalViolations: violations.length,
307
+ severityBreakdown: {
308
+ error: violations.filter(v => v.severity === 'error').length,
309
+ warning: violations.filter(v => v.severity === 'warning').length
310
+ },
311
+ context: context || 'No additional context provided',
312
+ note: 'Analysis completed using pattern matching (axe-core analysis failed)'
313
+ },
314
+ violations,
315
+ suggestions: violations.length > 0 ? [{
316
+ title: 'Accessibility Improvements Needed',
317
+ description: `Found ${violations.length} accessibility issues in your code.`,
318
+ violations,
319
+ nextSteps: ['Review each violation and apply the suggested fixes', 'Use ADS components instead of custom implementations', 'Test with screen readers and keyboard navigation', 'Run automated accessibility tests']
320
+ }] : [],
321
+ error: 'Axe-core analysis failed, used pattern-based analysis as fallback',
322
+ recommendations: ['Use ADS components for better accessibility out of the box', 'Reference https://atlassian.design/llms-a11y.txt for detailed guidelines', 'Test with keyboard navigation and screen readers', 'Use automated accessibility testing tools']
323
+ }, null, 2)
324
+ }]
325
+ };
326
+ }
327
+ };
328
+ export const analyzeLocalhostAccessibilityTool = async params => {
329
+ const {
330
+ url,
331
+ componentName,
332
+ context,
333
+ selector
334
+ } = params;
335
+ const violations = [];
336
+ const suggestions = [];
337
+ const axeResults = {};
338
+ const browser = await puppeteer.launch();
339
+ const page = await browser.newPage();
340
+ try {
341
+ var _axeResults$violation2, _axeResults$passes2, _axeResults$incomplet2;
342
+ await page.goto(url, {
343
+ waitUntil: 'networkidle0'
344
+ });
345
+
346
+ // If a selector is provided, check if the element exists
347
+ if (selector) {
348
+ const elementExists = await page.$(selector);
349
+ if (!elementExists) {
350
+ // Get list of available elements with IDs for helpful error message
351
+ const availableElements = await page.evaluate(() => {
352
+ const elements = Array.from(document.querySelectorAll('[id]'));
353
+ return elements.map(el => `#${el.id}`);
354
+ });
355
+ throw new Error(`Element with selector "${selector}" not found on the page after waiting. Available elements: ${availableElements.join(', ')}`);
356
+ }
357
+ }
358
+
359
+ // Run axe-core accessibility analysis
360
+ const axePuppeteer = new AxePuppeteer(page);
361
+
362
+ // If selector is provided, analyze only that element
363
+ if (selector) {
364
+ axePuppeteer.include(selector);
365
+ }
366
+ const results = await axePuppeteer.analyze();
367
+ if (results.violations && results.violations.length > 0) {
368
+ const adsViolations = mapAxeViolationsToADSFixes(results.violations);
369
+ violations.push(...adsViolations);
370
+ axeResults.violations = results.violations;
371
+ axeResults.passes = results.passes;
372
+ axeResults.incomplete = results.incomplete;
373
+ }
374
+
375
+ // Generate ADS-specific suggestions
376
+ if (violations.length > 0) {
377
+ suggestions.push({
378
+ title: 'Accessibility Improvements Needed',
379
+ description: `Found ${violations.length} accessibility issues in your code.`,
380
+ violations,
381
+ nextSteps: ['Review each violation and apply the suggested fixes', 'Use ADS components instead of custom implementations', 'Test with screen readers and keyboard navigation', 'Run automated accessibility tests']
382
+ });
383
+ }
384
+
385
+ // Provide relevant ADS guidelines
386
+ const relevantGuidelines = [];
387
+ if (url.includes('button') || url.includes('onClick')) {
388
+ relevantGuidelines.push(adsGuidelines.buttons);
389
+ }
390
+ if (url.includes('input') || url.includes('form')) {
391
+ relevantGuidelines.push(adsGuidelines.forms);
392
+ }
393
+ if (url.includes('img') || url.includes('image')) {
394
+ relevantGuidelines.push(adsGuidelines.images);
395
+ }
396
+ if (url.includes('color') || url.includes('style')) {
397
+ relevantGuidelines.push(adsGuidelines.colors);
398
+ }
399
+
400
+ // Generate summary
401
+ const summary = {
402
+ url,
403
+ selector: selector || 'Entire page analyzed',
404
+ componentName: componentName || 'Unknown component',
405
+ totalViolations: violations.length,
406
+ severityBreakdown: {
407
+ error: violations.filter(v => v.severity === 'error').length,
408
+ warning: violations.filter(v => v.severity === 'warning').length
409
+ },
410
+ context: context || 'No additional context provided',
411
+ axeResults: {
412
+ violations: ((_axeResults$violation2 = axeResults.violations) === null || _axeResults$violation2 === void 0 ? void 0 : _axeResults$violation2.length) || 0,
413
+ passes: ((_axeResults$passes2 = axeResults.passes) === null || _axeResults$passes2 === void 0 ? void 0 : _axeResults$passes2.length) || 0,
414
+ incomplete: ((_axeResults$incomplet2 = axeResults.incomplete) === null || _axeResults$incomplet2 === void 0 ? void 0 : _axeResults$incomplet2.length) || 0
415
+ }
416
+ };
417
+ await browser.close();
418
+ return {
419
+ content: [{
420
+ type: 'text',
421
+ text: JSON.stringify({
422
+ summary,
423
+ violations,
424
+ suggestions,
425
+ relevantGuidelines,
426
+ axeResults,
427
+ recommendations: ['Use ADS components for better accessibility out of the box', 'Reference https://atlassian.design/llms-a11y.txt for detailed guidelines', 'Test with keyboard navigation and screen readers', 'Use automated accessibility testing tools']
428
+ }, null, 2)
429
+ }]
430
+ };
431
+ } catch (error) {
432
+ await browser.close();
433
+ return {
434
+ content: [{
435
+ type: 'text',
436
+ text: JSON.stringify({
437
+ summary: {
438
+ url,
439
+ selector: selector || 'Entire page analyzed',
440
+ componentName: componentName || 'Unknown component',
441
+ totalViolations: violations.length,
442
+ severityBreakdown: {
443
+ error: violations.filter(v => v.severity === 'error').length,
444
+ warning: violations.filter(v => v.severity === 'warning').length
445
+ },
446
+ context: context || 'No additional context provided',
447
+ note: 'Analysis failed to run on the provided URL'
448
+ },
449
+ violations,
450
+ suggestions: [],
451
+ error: String(error),
452
+ recommendations: ['Use ADS components for better accessibility out of the box', 'Reference https://atlassian.design/llms-a11y.txt for detailed guidelines', 'Test with keyboard navigation and screen readers', 'Use automated accessibility testing tools']
453
+ }, null, 2)
454
+ }]
455
+ };
456
+ }
457
+ };