accessibility-server-mcp 1.0.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.
- package/LICENSE +21 -0
- package/README.md +762 -0
- package/config/wcag-rules.json +252 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +437 -0
- package/dist/index.js.map +1 -0
- package/dist/test-manual.d.ts +6 -0
- package/dist/test-manual.d.ts.map +1 -0
- package/dist/test-manual.js +66 -0
- package/dist/test-manual.js.map +1 -0
- package/dist/tools/accessibility-tester.d.ts +56 -0
- package/dist/tools/accessibility-tester.d.ts.map +1 -0
- package/dist/tools/accessibility-tester.js +317 -0
- package/dist/tools/accessibility-tester.js.map +1 -0
- package/dist/tools/color-contrast.d.ts +49 -0
- package/dist/tools/color-contrast.d.ts.map +1 -0
- package/dist/tools/color-contrast.js +237 -0
- package/dist/tools/color-contrast.js.map +1 -0
- package/dist/tools/wcag-validator.d.ts +43 -0
- package/dist/tools/wcag-validator.d.ts.map +1 -0
- package/dist/tools/wcag-validator.js +249 -0
- package/dist/tools/wcag-validator.js.map +1 -0
- package/dist/tools/website-accessibility-tester.d.ts +103 -0
- package/dist/tools/website-accessibility-tester.d.ts.map +1 -0
- package/dist/tools/website-accessibility-tester.js +228 -0
- package/dist/tools/website-accessibility-tester.js.map +1 -0
- package/dist/types/accessibility.d.ts +172 -0
- package/dist/types/accessibility.d.ts.map +1 -0
- package/dist/types/accessibility.js +5 -0
- package/dist/types/accessibility.js.map +1 -0
- package/dist/types/index.d.ts +6 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +8 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/mcp.d.ts +70 -0
- package/dist/types/mcp.d.ts.map +1 -0
- package/dist/types/mcp.js +5 -0
- package/dist/types/mcp.js.map +1 -0
- package/dist/utils/browser-manager.d.ts +83 -0
- package/dist/utils/browser-manager.d.ts.map +1 -0
- package/dist/utils/browser-manager.js +292 -0
- package/dist/utils/browser-manager.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +8 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +107 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/report-generator.d.ts +31 -0
- package/dist/utils/report-generator.d.ts.map +1 -0
- package/dist/utils/report-generator.js +252 -0
- package/dist/utils/report-generator.js.map +1 -0
- package/dist/utils/website-crawler.d.ts +66 -0
- package/dist/utils/website-crawler.d.ts.map +1 -0
- package/dist/utils/website-crawler.js +306 -0
- package/dist/utils/website-crawler.js.map +1 -0
- package/package.json +80 -0
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
import { Logger } from './logger.js';
|
|
2
|
+
import { URL } from 'url';
|
|
3
|
+
export class WebsiteCrawler {
|
|
4
|
+
logger;
|
|
5
|
+
browserManager;
|
|
6
|
+
visited = new Set();
|
|
7
|
+
discovered = new Set();
|
|
8
|
+
failedUrls = [];
|
|
9
|
+
depthMap = new Map();
|
|
10
|
+
constructor(browserManager) {
|
|
11
|
+
this.logger = new Logger().child({ component: 'WebsiteCrawler' });
|
|
12
|
+
this.browserManager = browserManager;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Crawl a website starting from the given URL
|
|
16
|
+
*/
|
|
17
|
+
async crawlWebsite(startUrl, options = {}) {
|
|
18
|
+
const startTime = Date.now();
|
|
19
|
+
const { maxPages = 50, maxDepth = 3, excludePatterns = [
|
|
20
|
+
'/api/',
|
|
21
|
+
'.pdf',
|
|
22
|
+
'.jpg',
|
|
23
|
+
'.jpeg',
|
|
24
|
+
'.png',
|
|
25
|
+
'.gif',
|
|
26
|
+
'.svg',
|
|
27
|
+
'.zip',
|
|
28
|
+
'.exe',
|
|
29
|
+
'.dmg',
|
|
30
|
+
'mailto:',
|
|
31
|
+
'tel:',
|
|
32
|
+
'#'
|
|
33
|
+
], includePatterns = [], delay = 1000, stayOnDomain = true } = options;
|
|
34
|
+
// Reset state
|
|
35
|
+
this.visited.clear();
|
|
36
|
+
this.discovered.clear();
|
|
37
|
+
this.failedUrls.length = 0;
|
|
38
|
+
this.depthMap.clear();
|
|
39
|
+
// Normalize start URL
|
|
40
|
+
const baseUrl = new URL(startUrl);
|
|
41
|
+
const baseDomain = baseUrl.hostname;
|
|
42
|
+
this.logger.info('Starting website crawl', {
|
|
43
|
+
startUrl,
|
|
44
|
+
maxPages,
|
|
45
|
+
maxDepth,
|
|
46
|
+
baseDomain
|
|
47
|
+
});
|
|
48
|
+
try {
|
|
49
|
+
// Start crawling from the initial URL
|
|
50
|
+
await this.crawlPage(startUrl, 0, maxDepth, {
|
|
51
|
+
maxPages,
|
|
52
|
+
maxDepth,
|
|
53
|
+
excludePatterns,
|
|
54
|
+
includePatterns,
|
|
55
|
+
delay,
|
|
56
|
+
stayOnDomain,
|
|
57
|
+
respectRobots: options.respectRobots ?? true,
|
|
58
|
+
baseDomain
|
|
59
|
+
});
|
|
60
|
+
const crawlDuration = Date.now() - startTime;
|
|
61
|
+
const urls = Array.from(this.discovered).slice(0, maxPages);
|
|
62
|
+
// Calculate actual depth reached
|
|
63
|
+
const actualDepth = Math.max(0, ...Array.from(this.depthMap.values()));
|
|
64
|
+
this.logger.info('Website crawl completed', {
|
|
65
|
+
totalFound: this.discovered.size,
|
|
66
|
+
totalCrawled: urls.length,
|
|
67
|
+
failures: this.failedUrls.length,
|
|
68
|
+
duration: crawlDuration,
|
|
69
|
+
actualDepth
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
urls,
|
|
73
|
+
failedUrls: [...this.failedUrls],
|
|
74
|
+
crawlDuration,
|
|
75
|
+
metadata: {
|
|
76
|
+
startUrl,
|
|
77
|
+
maxPages,
|
|
78
|
+
maxDepth,
|
|
79
|
+
actualDepth
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
this.logger.error('Website crawl failed', error instanceof Error ? error : new Error(String(error)));
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Crawl a single page and discover links
|
|
90
|
+
*/
|
|
91
|
+
async crawlPage(url, depth, maxDepth, options) {
|
|
92
|
+
// Check limits
|
|
93
|
+
if (this.discovered.size >= options.maxPages) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (depth > maxDepth) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (this.visited.has(url)) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
// Check if URL should be excluded
|
|
103
|
+
if (this.shouldExcludeUrl(url, options.excludePatterns, options.includePatterns)) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
// Initial domain check (but allow for redirects)
|
|
107
|
+
if (options.stayOnDomain && depth > 0) {
|
|
108
|
+
try {
|
|
109
|
+
const urlObj = new URL(url);
|
|
110
|
+
if (!this.isDomainAllowed(urlObj.hostname, options.baseDomain)) {
|
|
111
|
+
this.logger.debug('URL rejected due to domain constraint (pre-navigation)', {
|
|
112
|
+
url,
|
|
113
|
+
hostname: urlObj.hostname,
|
|
114
|
+
baseDomain: options.baseDomain,
|
|
115
|
+
depth
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return; // Invalid URL
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this.visited.add(url);
|
|
125
|
+
this.discovered.add(url);
|
|
126
|
+
this.depthMap.set(url, depth);
|
|
127
|
+
let page = null;
|
|
128
|
+
try {
|
|
129
|
+
page = await this.browserManager.createPage({
|
|
130
|
+
viewport: { width: 1920, height: 1080 },
|
|
131
|
+
timeout: 30000
|
|
132
|
+
});
|
|
133
|
+
// Navigate to the page
|
|
134
|
+
await this.browserManager.navigateToURL(page, url, {
|
|
135
|
+
timeout: 20000,
|
|
136
|
+
waitUntil: 'domcontentloaded'
|
|
137
|
+
});
|
|
138
|
+
// Get the final URL after any redirects
|
|
139
|
+
const finalUrl = page.url();
|
|
140
|
+
const finalUrlObj = new URL(finalUrl);
|
|
141
|
+
// Update base domain for root page if this is the first page (depth 0)
|
|
142
|
+
if (depth === 0) {
|
|
143
|
+
options.baseDomain = finalUrlObj.hostname;
|
|
144
|
+
this.logger.info('Updated base domain after redirect', {
|
|
145
|
+
originalUrl: url,
|
|
146
|
+
finalUrl,
|
|
147
|
+
baseDomain: options.baseDomain
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
// Re-check domain constraint with final URL
|
|
151
|
+
if (options.stayOnDomain && depth > 0) {
|
|
152
|
+
if (!this.isDomainAllowed(finalUrlObj.hostname, options.baseDomain)) {
|
|
153
|
+
this.logger.debug('Page rejected due to domain constraint after redirect', {
|
|
154
|
+
finalUrl,
|
|
155
|
+
finalDomain: finalUrlObj.hostname,
|
|
156
|
+
baseDomain: options.baseDomain
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
// Extract links from the page using final URL
|
|
162
|
+
const links = await this.extractLinks(page, finalUrl);
|
|
163
|
+
this.logger.info(`Found ${links.length} links on page`, { url: finalUrl, depth });
|
|
164
|
+
// Add delay to be respectful
|
|
165
|
+
if (options.delay > 0) {
|
|
166
|
+
await new Promise(resolve => setTimeout(resolve, options.delay));
|
|
167
|
+
}
|
|
168
|
+
// Recursively crawl discovered links
|
|
169
|
+
for (const link of links) {
|
|
170
|
+
if (this.discovered.size >= options.maxPages) {
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
this.logger.debug('Considering link for crawling', {
|
|
174
|
+
link,
|
|
175
|
+
depth: depth + 1,
|
|
176
|
+
currentDiscovered: this.discovered.size
|
|
177
|
+
});
|
|
178
|
+
await this.crawlPage(link, depth + 1, maxDepth, options);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
183
|
+
this.logger.warn(`Failed to crawl page: ${url}`, { error: errorMessage });
|
|
184
|
+
this.failedUrls.push({ url, error: errorMessage });
|
|
185
|
+
}
|
|
186
|
+
finally {
|
|
187
|
+
if (page) {
|
|
188
|
+
await this.browserManager.closePage(page);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Extract links from a page
|
|
194
|
+
*/
|
|
195
|
+
async extractLinks(page, baseUrl) {
|
|
196
|
+
try {
|
|
197
|
+
const links = await page.evaluate((base) => {
|
|
198
|
+
const baseUrl = new URL(base);
|
|
199
|
+
const linkElements = Array.from(document.querySelectorAll('a[href]'));
|
|
200
|
+
const hrefs = linkElements
|
|
201
|
+
.map(link => link.getAttribute('href'))
|
|
202
|
+
.filter((href) => {
|
|
203
|
+
if (!href)
|
|
204
|
+
return false;
|
|
205
|
+
if (href.startsWith('javascript:'))
|
|
206
|
+
return false;
|
|
207
|
+
if (href.startsWith('#'))
|
|
208
|
+
return false;
|
|
209
|
+
return true;
|
|
210
|
+
});
|
|
211
|
+
const resolvedUrls = hrefs
|
|
212
|
+
.map(href => {
|
|
213
|
+
try {
|
|
214
|
+
return new URL(href, baseUrl).href;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
})
|
|
220
|
+
.filter((url) => url !== null);
|
|
221
|
+
// Return debug info along with links
|
|
222
|
+
return {
|
|
223
|
+
totalElements: linkElements.length,
|
|
224
|
+
filteredHrefs: hrefs.length,
|
|
225
|
+
resolvedUrls: resolvedUrls.length,
|
|
226
|
+
links: resolvedUrls
|
|
227
|
+
};
|
|
228
|
+
}, baseUrl);
|
|
229
|
+
this.logger.info('Link extraction results', {
|
|
230
|
+
baseUrl,
|
|
231
|
+
totalElements: links.totalElements,
|
|
232
|
+
filteredHrefs: links.filteredHrefs,
|
|
233
|
+
resolvedUrls: links.resolvedUrls,
|
|
234
|
+
sampleLinks: links.links.slice(0, 5)
|
|
235
|
+
});
|
|
236
|
+
// Remove duplicates
|
|
237
|
+
const uniqueLinks = [...new Set(links.links)];
|
|
238
|
+
this.logger.info(`Found ${uniqueLinks.length} unique links after deduplication`);
|
|
239
|
+
return uniqueLinks;
|
|
240
|
+
}
|
|
241
|
+
catch (error) {
|
|
242
|
+
this.logger.warn('Failed to extract links', { error: String(error), baseUrl });
|
|
243
|
+
return [];
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Check if a domain is allowed based on the base domain
|
|
248
|
+
* Handles various cases like subdomains, www prefixes, and related domains
|
|
249
|
+
*/
|
|
250
|
+
isDomainAllowed(hostname, baseDomain) {
|
|
251
|
+
// Exact match
|
|
252
|
+
if (hostname === baseDomain) {
|
|
253
|
+
return true;
|
|
254
|
+
}
|
|
255
|
+
// Remove www. prefix for comparison
|
|
256
|
+
const cleanHostname = hostname.replace(/^www\./, '');
|
|
257
|
+
const cleanBaseDomain = baseDomain.replace(/^www\./, '');
|
|
258
|
+
// Check clean versions
|
|
259
|
+
if (cleanHostname === cleanBaseDomain) {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
// Check if it's a subdomain of the clean base domain
|
|
263
|
+
if (cleanHostname.endsWith('.' + cleanBaseDomain)) {
|
|
264
|
+
return true;
|
|
265
|
+
}
|
|
266
|
+
// Check if clean base domain is a subdomain of current hostname (for redirects)
|
|
267
|
+
if (cleanBaseDomain.endsWith('.' + cleanHostname)) {
|
|
268
|
+
return true;
|
|
269
|
+
}
|
|
270
|
+
this.logger.debug('Domain not allowed', {
|
|
271
|
+
hostname,
|
|
272
|
+
baseDomain,
|
|
273
|
+
cleanHostname,
|
|
274
|
+
cleanBaseDomain
|
|
275
|
+
});
|
|
276
|
+
return false;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Check if a URL should be excluded based on patterns
|
|
280
|
+
*/
|
|
281
|
+
shouldExcludeUrl(url, excludePatterns, includePatterns) {
|
|
282
|
+
// If include patterns are specified, URL must match at least one
|
|
283
|
+
if (includePatterns.length > 0) {
|
|
284
|
+
const matches = includePatterns.some(pattern => {
|
|
285
|
+
try {
|
|
286
|
+
return new RegExp(pattern).test(url) || url.includes(pattern);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
return url.includes(pattern);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
if (!matches)
|
|
293
|
+
return true;
|
|
294
|
+
}
|
|
295
|
+
// Check exclude patterns
|
|
296
|
+
return excludePatterns.some(pattern => {
|
|
297
|
+
try {
|
|
298
|
+
return new RegExp(pattern).test(url) || url.includes(pattern);
|
|
299
|
+
}
|
|
300
|
+
catch {
|
|
301
|
+
return url.includes(pattern);
|
|
302
|
+
}
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
//# sourceMappingURL=website-crawler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"website-crawler.js","sourceRoot":"","sources":["../../src/utils/website-crawler.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "accessibility-server-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for web accessibility testing with WCAG compliance",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"bin": {
|
|
17
|
+
"accessibility-mcp-server": "./dist/index.js",
|
|
18
|
+
"accessibility-mcp": "./dist/index.js",
|
|
19
|
+
"a11y-mcp": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"dev": "tsx src/index.ts",
|
|
24
|
+
"dev:simple": "tsx src/index.ts --simple",
|
|
25
|
+
"start": "node dist/index.js",
|
|
26
|
+
"start:simple": "node dist/index.js --simple",
|
|
27
|
+
"lint": "eslint src/**/*.ts",
|
|
28
|
+
"prepare": "npm run build",
|
|
29
|
+
"clean": "rimraf dist",
|
|
30
|
+
"prepublishOnly": "npm run build",
|
|
31
|
+
"preversion": "npm run lint && npm run build",
|
|
32
|
+
"version": "npm run build",
|
|
33
|
+
"postversion": "git push && git push --tags"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"accessibility",
|
|
37
|
+
"wcag",
|
|
38
|
+
"mcp",
|
|
39
|
+
"a11y",
|
|
40
|
+
"testing",
|
|
41
|
+
"compliance",
|
|
42
|
+
"automation"
|
|
43
|
+
],
|
|
44
|
+
"author": "Utkarsh Nigam <nigamutkarsh@microsoft.com>",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
|
|
47
|
+
"dependencies": {
|
|
48
|
+
"@modelcontextprotocol/sdk": "^0.5.0",
|
|
49
|
+
"axe-core": "^4.8.2",
|
|
50
|
+
"puppeteer": "^21.5.2",
|
|
51
|
+
"jsdom": "^23.0.1",
|
|
52
|
+
"color": "^4.2.3",
|
|
53
|
+
"zod": "^3.22.4",
|
|
54
|
+
"winston": "^3.11.0"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/node": "^20.8.0",
|
|
58
|
+
"@types/jsdom": "^21.1.6",
|
|
59
|
+
"@types/color": "^3.0.6",
|
|
60
|
+
"@typescript-eslint/eslint-plugin": "^6.7.4",
|
|
61
|
+
"@typescript-eslint/parser": "^6.7.4",
|
|
62
|
+
"eslint": "^8.50.0",
|
|
63
|
+
"tsx": "^3.14.0",
|
|
64
|
+
"typescript": "^5.2.2",
|
|
65
|
+
"rimraf": "^5.0.5"
|
|
66
|
+
},
|
|
67
|
+
"engines": {
|
|
68
|
+
"node": ">=18.0.0"
|
|
69
|
+
},
|
|
70
|
+
"files": [
|
|
71
|
+
"dist/**/*",
|
|
72
|
+
"config/**/*",
|
|
73
|
+
"README.md",
|
|
74
|
+
"LICENSE"
|
|
75
|
+
],
|
|
76
|
+
"preferGlobal": false,
|
|
77
|
+
"publishConfig": {
|
|
78
|
+
"access": "public"
|
|
79
|
+
}
|
|
80
|
+
}
|