-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathaccessibility.ts
More file actions
106 lines (98 loc) · 3.39 KB
/
Copy pathaccessibility.ts
File metadata and controls
106 lines (98 loc) · 3.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
import { AccessibilityScanner } from "./accessiblity-utils/scanner.js";
import { AccessibilityReportFetcher } from "./accessiblity-utils/report-fetcher.js";
import { trackMCP } from "../lib/instrumentation.js";
import { parseAccessibilityReportFromCSV } from "./accessiblity-utils/report-parser.js";
import { DOMAINS } from "../lib/domains.js";
const scanner = new AccessibilityScanner();
const reportFetcher = new AccessibilityReportFetcher();
async function runAccessibilityScan(
name: string,
pageURL: string,
context: any,
): Promise<CallToolResult> {
// Start scan
const startResp = await scanner.startScan(name, [pageURL]);
const scanId = startResp.data!.id;
const scanRunId = startResp.data!.scanRunId;
// Notify scan start
await context.sendNotification({
method: "notifications/progress",
params: {
progressToken: context._meta?.progressToken ?? "NOT_FOUND",
message: `Accessibility scan "${name}" started`,
progress: 0,
total: 100,
},
});
// Wait until scan completes
const status = await scanner.waitUntilComplete(scanId, scanRunId, context);
if (status !== "completed") {
return {
content: [
{
type: "text",
text: `❌ Accessibility scan "${name}" failed with status: ${status} , check the BrowserStack dashboard for more details [${DOMAINS.SCANNER}/site-scanner/scan-details/${name}].`,
isError: true,
},
],
isError: true,
};
}
// Fetch CSV report link
const reportLink = await reportFetcher.getReportLink(scanId, scanRunId);
const { records, page_length, total_issues } =
await parseAccessibilityReportFromCSV(reportLink);
return {
content: [
{
type: "text",
text: `✅ Accessibility scan "${name}" completed. check the BrowserStack dashboard for more details [${DOMAINS.SCANNER}/site-scanner/scan-details/${name}].`,
},
{
type: "text",
text: `We found ${total_issues} issues. Below are the details of the ${page_length} most critical issues.`,
},
{
type: "text",
text: `Scan results: ${JSON.stringify(records, null, 2)}`,
},
],
};
}
export default function addAccessibilityTools(server: McpServer) {
server.tool(
"startAccessibilityScan",
"Start an accessibility scan via BrowserStack and retrieve a local CSV report path.",
{
name: z.string().describe("Name of the accessibility scan"),
pageURL: z.string().describe("The URL to scan for accessibility issues"),
},
async (args, context) => {
try {
trackMCP("startAccessibilityScan", server.server.getClientVersion()!);
return await runAccessibilityScan(args.name, args.pageURL, context);
} catch (error) {
trackMCP(
"startAccessibilityScan",
server.server.getClientVersion()!,
error,
);
return {
content: [
{
type: "text",
text: `Failed to start accessibility scan: ${
error instanceof Error ? error.message : "Unknown error"
}. Please open an issue on GitHub if the problem persists`,
isError: true,
},
],
isError: true,
};
}
},
);
}