@weaaare/mcp-virtual-screen-reader-auditor 0.0.1

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/README.md ADDED
@@ -0,0 +1,81 @@
1
+ # @weaaare/mcp-virtual-screen-reader-auditor
2
+
3
+ MCP (Model Context Protocol) server for **headless virtual screen reader accessibility audits**. Works on any OS — no native screen reader required. Launches a real browser, injects a virtual screen reader, and navigates the live accessibility tree including dynamic/SPA content.
4
+
5
+ Covers **WCAG 2.2** criteria using the same audit, findings, and reporting framework as `@weaaare/mcp-voiceover-auditor`.
6
+
7
+ ## Tools
8
+
9
+ | Tool | Description |
10
+ | --- | --- |
11
+ | `virtual_start` | Start the Virtual Screen Reader on a URL or raw HTML (launches headless browser) |
12
+ | `virtual_stop` | Stop the Virtual Screen Reader and release resources |
13
+ | `virtual_next` | Move cursor to the next item in the accessibility tree |
14
+ | `virtual_previous` | Move cursor to the previous item in the accessibility tree |
15
+ | `virtual_act` | Perform default action for the current item (e.g., activate a link/button) |
16
+ | `virtual_interact` | Interact with the current container item |
17
+ | `virtual_stop_interacting` | Stop interacting with the current container item |
18
+ | `virtual_press` | Press a key on the focused item (e.g. `Enter`, `Tab`, `ArrowDown`) |
19
+ | `virtual_type` | Type text into the currently focused item |
20
+ | `virtual_perform` | Semantic navigation by element type: headings, links, landmarks, forms, figures |
21
+ | `virtual_item_text` | Get text of the item under the Virtual Screen Reader cursor |
22
+ | `virtual_last_spoken_phrase` | Get the last phrase spoken by the Virtual Screen Reader |
23
+ | `virtual_spoken_phrase_log` | Get full spoken phrase history for this session |
24
+ | `virtual_item_text_log` | Get full visited item text history for this session |
25
+ | `virtual_clear_spoken_phrase_log` | Clear the spoken phrase log |
26
+ | `virtual_clear_item_text_log` | Clear the visited item text log |
27
+ | `virtual_click` | Click the mouse at the current position |
28
+ | `start_audit` | Start a structured audit session with metadata |
29
+ | `log_finding` | Log violations/warnings/passes with WCAG criteria and recommendations |
30
+ | `get_audit_status` | Get current audit progress and finding counters |
31
+ | `get_findings` | Retrieve findings from current or latest session |
32
+ | `end_audit` | End audit session and return summary data |
33
+ | `generate_report` | Generate reports in Markdown, JSON, or CSV |
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ npm install -g @weaaare/mcp-virtual-screen-reader-auditor
39
+ ```
40
+
41
+ Or use directly with `npx`:
42
+
43
+ ```bash
44
+ npx @weaaare/mcp-virtual-screen-reader-auditor
45
+ ```
46
+
47
+ ## Configuration
48
+
49
+ ### VS Code (GitHub Copilot)
50
+
51
+ Add to `.vscode/mcp.json`:
52
+
53
+ ```json
54
+ {
55
+ "servers": {
56
+ "virtual-screen-reader-auditor": {
57
+ "command": "npx",
58
+ "args": ["-y", "@weaaare/mcp-virtual-screen-reader-auditor"]
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ ### Claude Desktop
65
+
66
+ Add to `claude_desktop_config.json`:
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "virtual-screen-reader-auditor": {
72
+ "command": "npx",
73
+ "args": ["-y", "@weaaare/mcp-virtual-screen-reader-auditor"]
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ ## License
80
+
81
+ MIT - [weAAAre](https://weAAAre.com)
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,13 @@
1
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
2
+ import { createServer } from './server.js';
3
+ const main = async () => {
4
+ const server = createServer();
5
+ const transport = new StdioServerTransport();
6
+ await server.connect(transport);
7
+ console.error('virtual-screen-reader-auditor MCP server running on stdio');
8
+ };
9
+ main().catch((error) => {
10
+ console.error('Fatal error:', error);
11
+ process.exit(1);
12
+ });
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,IAAI,GAAG,KAAK,IAAmB,EAAE;IACrC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,2DAA2D,CAAC,CAAC;AAC7E,CAAC,CAAC;AAEF,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { PromptDefinition } from '@weaaare/mcp-auditor-core';
2
+ import { getPromptMessages, listPrompts } from '@weaaare/mcp-auditor-core';
3
+ export declare const VIRTUAL_PROMPTS: ReadonlyMap<string, PromptDefinition>;
4
+ export declare const listVirtualPrompts: () => ReturnType<typeof listPrompts>;
5
+ export declare const getVirtualPromptMessages: (name: string, args: Record<string, string | undefined>) => ReturnType<typeof getPromptMessages>;
6
+ //# sourceMappingURL=virtual-prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-prompts.d.ts","sourceRoot":"","sources":["../../src/prompts/virtual-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAyR3E,eAAO,MAAM,eAAe,EAAE,WAAW,CAAC,MAAM,EAAE,gBAAgB,CAMhE,CAAC;AAEH,eAAO,MAAM,kBAAkB,QAAO,UAAU,CAAC,OAAO,WAAW,CACrC,CAAC;AAE/B,eAAO,MAAM,wBAAwB,GACnC,MAAM,MAAM,EACZ,MAAM,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,KACvC,UAAU,CAAC,OAAO,iBAAiB,CAAmD,CAAC"}
@@ -0,0 +1,272 @@
1
+ import { getPromptMessages, listPrompts } from '@weaaare/mcp-auditor-core';
2
+ // ─── Virtual Screen Reader Prompts ───────────────────────────────────────────
3
+ // These use the virtual screen reader (headless browser + injected SR).
4
+ // Workflow: virtual_start → navigate → log_finding → virtual_stop → report
5
+ const virtualAccessibilityAudit = {
6
+ prompt: {
7
+ name: 'virtual_accessibility_audit',
8
+ description: 'Run an accessibility audit using the Virtual Screen Reader. Choose the page and the type of test. Works on any OS — no real screen reader required.',
9
+ arguments: [
10
+ {
11
+ name: 'url',
12
+ description: 'URL of the page to audit',
13
+ required: true,
14
+ },
15
+ {
16
+ name: 'testType',
17
+ description: 'Type of test to run: full | headings | forms | navigation | links | images',
18
+ required: true,
19
+ },
20
+ {
21
+ name: 'wcagLevel',
22
+ description: 'WCAG conformance level: A, AA, or AAA (default: AA)',
23
+ required: false,
24
+ },
25
+ ],
26
+ },
27
+ getMessage: (args) => {
28
+ const url = args.url ?? 'UNKNOWN_URL';
29
+ const testType = args.testType ?? 'full';
30
+ const wcagLevel = args.wcagLevel ?? 'AA';
31
+ const testBlocks = {
32
+ full: `## Phase 2 — Audit Workflow
33
+
34
+ ### 2.1 Page Title & Language
35
+ - \`virtual_item_text\` — check what the screen reader announces on page load
36
+ - Verify the page title is descriptive (WCAG 2.4.2)
37
+ - \`log_finding\`
38
+
39
+ ### 2.2 Landmark Regions
40
+ - \`virtual_perform\` → moveToNextLandmark (repeat until exhausted) to get overview
41
+ - Then check specific landmark types directly:
42
+ - \`virtual_perform\` → moveToNextMain (required — verify it exists)
43
+ - \`virtual_perform\` → moveToNextNavigation (recommended)
44
+ - \`virtual_perform\` → moveToNextBanner (header)
45
+ - \`virtual_perform\` → moveToNextContentinfo (footer)
46
+ - \`virtual_perform\` → moveToNextComplementary (aside)
47
+ - \`virtual_perform\` → moveToNextSearch (search region)
48
+ - \`log_finding\` for WCAG 1.3.1
49
+
50
+ ### 2.3 Heading Structure
51
+ - \`virtual_perform\` → moveToNextHeading (repeat until exhausted)
52
+ - Record each heading level and text via \`virtual_last_spoken_phrase\` and \`virtual_item_text\`
53
+ - Verify: exactly one h1, no skipped levels
54
+ - \`log_finding\` for WCAG 1.3.1, 2.4.6
55
+
56
+ ### 2.4 Links
57
+ - \`virtual_perform\` → moveToNextLink (repeat)
58
+ - Verify descriptive link text (not "click here", "read more", "here")
59
+ - \`log_finding\` for WCAG 2.4.4
60
+
61
+ ### 2.5 Forms
62
+ - \`virtual_perform\` → moveToNextForm (repeat) — find form containers
63
+ - Within each form: \`virtual_perform\` → findNextControl (repeat) — find individual controls
64
+ - For each control: \`virtual_last_spoken_phrase\` to verify label, required state
65
+ - \`log_finding\` for WCAG 1.3.1, 3.3.2, 4.1.2
66
+
67
+ ### 2.6 Images
68
+ - \`virtual_perform\` → moveToNextFigure (repeat until exhausted) — jump directly from image to image
69
+ - For each image:
70
+ a. \`virtual_last_spoken_phrase\` — check what is announced
71
+ b. \`virtual_item_text\` — check the text content
72
+ c. Informative images: verify alt text exists and is descriptive
73
+ d. Decorative images: verify they are hidden (role="presentation" or alt="")
74
+ - \`log_finding\` for WCAG 1.1.1
75
+
76
+ ### 2.7 Keyboard Navigation
77
+ - Use \`virtual_press\` with "Tab" to tab through the page
78
+ - Verify logical focus order, no keyboard traps, interactive elements reachable
79
+ - \`log_finding\` for WCAG 2.1.1, 2.1.2, 2.4.3`,
80
+ headings: `## Phase 2 — Heading Audit
81
+
82
+ - \`virtual_perform\` → moveToNextHeading (repeat until exhausted) — collect all headings
83
+ - For each heading record: level and text via \`virtual_last_spoken_phrase\` and \`virtual_item_text\`
84
+ - Then verify h1 count with a targeted pass:
85
+ - \`virtual_perform\` → moveToNextHeadingLevel1 (repeat) — count all h1s (must be exactly one)
86
+ - If skipped levels suspected, verify with level-specific commands:
87
+ - moveToNextHeadingLevel2, moveToNextHeadingLevel3, etc.
88
+ - Verify:
89
+ - Exactly one h1 on the page
90
+ - No skipped levels (h1→h2→h3, not h1→h3)
91
+ - Headings are descriptive (not empty, not just "Section")
92
+ - Heading hierarchy reflects content structure
93
+ - \`log_finding\` for WCAG 1.3.1, 2.4.6`,
94
+ forms: `## Phase 2 — Form Audit
95
+
96
+ - \`virtual_perform\` → moveToNextForm (repeat) — find form containers
97
+ - Within each form, find individual controls:
98
+ a. \`virtual_perform\` → findNextControl (repeat until exhausted)
99
+ - For each control:
100
+ a. Record announcement via \`virtual_last_spoken_phrase\`
101
+ b. \`virtual_item_text\` — verify label association
102
+ c. Check required state is announced
103
+ d. For text inputs: \`virtual_type\` to enter text, check validation
104
+ e. \`virtual_press\` with "Tab" to verify keyboard flow
105
+ - Also check ARIA error relationships: \`virtual_perform\` → jumpToErrorMessageElement
106
+ - Verify:
107
+ - All inputs have labels (WCAG 1.3.1, 3.3.2)
108
+ - Required fields indicated (WCAG 3.3.2)
109
+ - Error messages announced (WCAG 3.3.1)
110
+ - Form completable entirely by keyboard (WCAG 2.1.1)
111
+ - Submit button reachable by keyboard
112
+ - \`log_finding\` for each issue`,
113
+ navigation: `## Phase 2 — Navigation Audit
114
+
115
+ ### Skip Links
116
+ - \`virtual_press\` with "Tab" once from start — check for a "skip to content" link
117
+
118
+ ### Landmarks
119
+ - Check each specific landmark type directly for precise verification:
120
+ - \`virtual_perform\` → moveToNextMain — MUST exist (required landmark)
121
+ - \`virtual_perform\` → moveToNextNavigation — recommended
122
+ - \`virtual_perform\` → moveToNextBanner — header region
123
+ - \`virtual_perform\` → moveToNextContentinfo — footer region
124
+ - \`virtual_perform\` → moveToNextComplementary — aside region
125
+ - \`virtual_perform\` → moveToNextSearch — search region
126
+ - \`virtual_perform\` → moveToNextRegion — named regions
127
+ - Then \`virtual_perform\` → moveToNextLandmark (repeat) to catch any additional landmarks
128
+ - \`log_finding\` for WCAG 1.3.1
129
+
130
+ ### Tab Order
131
+ - \`virtual_press\` with "Tab" through entire page
132
+ - Verify order follows visual/logical reading order
133
+ - Verify no keyboard traps (can always Tab out)
134
+ - Verify all interactive elements are reachable
135
+ - \`log_finding\` for WCAG 2.1.1, 2.1.2, 2.4.3
136
+
137
+ ### Focus Management
138
+ - Check modals: focus should be trapped inside
139
+ - Check expandable sections: focus should move appropriately
140
+ - \`log_finding\` for WCAG 2.4.3`,
141
+ links: `## Phase 2 — Link Audit
142
+
143
+ - \`virtual_perform\` → moveToNextLink (repeat until exhausted)
144
+ - For each link:
145
+ a. \`virtual_last_spoken_phrase\` — record full announcement
146
+ b. \`virtual_item_text\` — record link text
147
+ c. Verify link text is descriptive (not "click here", "read more", "here", "link")
148
+ d. Verify link purpose is clear from text alone or surrounding context
149
+ e. Check for redundant links (same destination, different text)
150
+ - \`log_finding\` for WCAG 2.4.4 (Link Purpose in Context)`,
151
+ images: `## Phase 2 — Image Audit
152
+
153
+ - \`virtual_perform\` → moveToNextFigure (repeat until exhausted) — jump directly from image to image
154
+ - For each image:
155
+ a. \`virtual_last_spoken_phrase\` — check what the screen reader announces
156
+ b. \`virtual_item_text\` — check the text content
157
+ c. Informative images: verify alt text exists and is descriptive
158
+ d. Decorative images: verify they are hidden from the screen reader (role="presentation" or alt="")
159
+ e. Complex images (charts, diagrams): verify long description is provided (check with \`virtual_perform\` → jumpToDetailsElement)
160
+ - \`log_finding\` for WCAG 1.1.1 (Non-text Content)`,
161
+ };
162
+ const testBlock = testBlocks[testType] ?? testBlocks.full;
163
+ return [
164
+ {
165
+ role: 'user',
166
+ content: {
167
+ type: 'text',
168
+ text: `Run a ${testType} accessibility audit of ${url} using the Virtual Screen Reader. Follow every step in order.
169
+
170
+ ## Phase 1 — Start
171
+ 1. \`virtual_start\` with url "${url}"
172
+ 2. \`start_audit\` with url "${url}", screenReader "virtual", wcagLevel "${wcagLevel}"
173
+
174
+ ${testBlock}
175
+
176
+ ## Handling Issues
177
+ - Inability to navigate to an element via screen reader IS a finding — log it as a violation
178
+ - Try a workaround (e.g., Tab key via \`virtual_press\`) and continue; never stop at the first failure
179
+
180
+ ## Phase 3 — Report & Shutdown
181
+ 1. \`end_audit\`
182
+ 2. \`generate_report\` with format "markdown"
183
+ 3. Present the report with critical issues first
184
+ 4. \`virtual_stop\``,
185
+ },
186
+ },
187
+ ];
188
+ },
189
+ };
190
+ const virtualFullAudit = {
191
+ prompt: {
192
+ name: 'virtual_full_audit',
193
+ description: 'Comprehensive virtual screen reader audit. Covers headings, landmarks, links, forms, images, and keyboard navigation.',
194
+ arguments: [
195
+ {
196
+ name: 'url',
197
+ description: 'URL of the page to audit',
198
+ required: true,
199
+ },
200
+ {
201
+ name: 'wcagLevel',
202
+ description: 'WCAG conformance level: A, AA, or AAA (default: AA)',
203
+ required: false,
204
+ },
205
+ ],
206
+ },
207
+ getMessage: (args) => virtualAccessibilityAudit.getMessage({
208
+ ...args,
209
+ testType: 'full',
210
+ }),
211
+ };
212
+ const virtualHeadingAudit = {
213
+ prompt: {
214
+ name: 'virtual_heading_audit',
215
+ description: 'Audit heading structure using the Virtual Screen Reader. Checks h1 uniqueness, hierarchy, and descriptive content.',
216
+ arguments: [
217
+ {
218
+ name: 'url',
219
+ description: 'URL of the page to audit',
220
+ required: true,
221
+ },
222
+ ],
223
+ },
224
+ getMessage: (args) => virtualAccessibilityAudit.getMessage({
225
+ ...args,
226
+ testType: 'headings',
227
+ }),
228
+ };
229
+ const virtualFormAudit = {
230
+ prompt: {
231
+ name: 'virtual_form_audit',
232
+ description: 'Audit form accessibility using the Virtual Screen Reader: labels, error messages, required fields, and keyboard navigation.',
233
+ arguments: [
234
+ {
235
+ name: 'url',
236
+ description: 'URL of the page with forms to audit',
237
+ required: true,
238
+ },
239
+ ],
240
+ },
241
+ getMessage: (args) => virtualAccessibilityAudit.getMessage({
242
+ ...args,
243
+ testType: 'forms',
244
+ }),
245
+ };
246
+ const virtualNavigationAudit = {
247
+ prompt: {
248
+ name: 'virtual_navigation_audit',
249
+ description: 'Audit keyboard navigation and landmarks using the Virtual Screen Reader. Checks tab order, landmarks, skip links, and focus management.',
250
+ arguments: [
251
+ {
252
+ name: 'url',
253
+ description: 'URL of the page to audit',
254
+ required: true,
255
+ },
256
+ ],
257
+ },
258
+ getMessage: (args) => virtualAccessibilityAudit.getMessage({
259
+ ...args,
260
+ testType: 'navigation',
261
+ }),
262
+ };
263
+ export const VIRTUAL_PROMPTS = new Map([
264
+ ['virtual_accessibility_audit', virtualAccessibilityAudit],
265
+ ['virtual_full_audit', virtualFullAudit],
266
+ ['virtual_heading_audit', virtualHeadingAudit],
267
+ ['virtual_form_audit', virtualFormAudit],
268
+ ['virtual_navigation_audit', virtualNavigationAudit],
269
+ ]);
270
+ export const listVirtualPrompts = () => listPrompts(VIRTUAL_PROMPTS);
271
+ export const getVirtualPromptMessages = (name, args) => getPromptMessages(name, args, VIRTUAL_PROMPTS);
272
+ //# sourceMappingURL=virtual-prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual-prompts.js","sourceRoot":"","sources":["../../src/prompts/virtual-prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ import type { ClickOptions, ScreenReaderCommandResult, ScreenReaderPort } from '@weaaare/mcp-auditor-core';
2
+ export declare class VirtualScreenReaderAdapter implements ScreenReaderPort {
3
+ private browser;
4
+ private context;
5
+ private page;
6
+ private getPage;
7
+ private ensureBrowser;
8
+ loadUrl(url: string): Promise<void>;
9
+ loadHtml(html: string): Promise<void>;
10
+ start(): Promise<ScreenReaderCommandResult>;
11
+ stop(): Promise<ScreenReaderCommandResult>;
12
+ next(): Promise<ScreenReaderCommandResult>;
13
+ previous(): Promise<ScreenReaderCommandResult>;
14
+ act(): Promise<ScreenReaderCommandResult>;
15
+ interact(): Promise<ScreenReaderCommandResult>;
16
+ stopInteracting(): Promise<ScreenReaderCommandResult>;
17
+ press(key: string): Promise<ScreenReaderCommandResult>;
18
+ type(text: string): Promise<ScreenReaderCommandResult>;
19
+ perform(command: string): Promise<ScreenReaderCommandResult>;
20
+ performCommander(_command: string): Promise<ScreenReaderCommandResult>;
21
+ getCommanderCommands(): string[];
22
+ itemText(): Promise<string>;
23
+ lastSpokenPhrase(): Promise<string>;
24
+ spokenPhraseLog(): Promise<string[]>;
25
+ itemTextLog(): Promise<string[]>;
26
+ clearSpokenPhraseLog(): Promise<void>;
27
+ clearItemTextLog(): Promise<void>;
28
+ click(options?: ClickOptions): Promise<ScreenReaderCommandResult>;
29
+ detect(): Promise<boolean>;
30
+ isDefault(): Promise<boolean>;
31
+ }
32
+ //# sourceMappingURL=virtual.adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual.adapter.d.ts","sourceRoot":"","sources":["../../../src/screen-readers/virtual/virtual.adapter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,YAAY,EACZ,yBAAyB,EACzB,gBAAgB,EACjB,MAAM,2BAA2B,CAAC;AAqBnC,qBAAa,0BAA2B,YAAW,gBAAgB;IACjE,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,IAAI,CAAqB;IAEjC,OAAO,CAAC,OAAO;YASD,aAAa;IA6BrB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKnC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKrC,KAAK,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAU3C,IAAI,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAoC1C,IAAI,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAY1C,QAAQ,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAY9C,GAAG,IAAI,OAAO,CAAC,yBAAyB,CAAC;IASzC,QAAQ,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAQ9C,eAAe,IAAI,OAAO,CAAC,yBAAyB,CAAC;IAQrD,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAStD,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAQtD,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAmBlE,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAMtE,oBAAoB,IAAI,MAAM,EAAE;IAI1B,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAO3B,gBAAgB,IAAI,OAAO,CAAC,MAAM,CAAC;IAOnC,eAAe,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAOpC,WAAW,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAOhC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOrC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAajE,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC;IAI1B,SAAS,IAAI,OAAO,CAAC,OAAO,CAAC;CAGpC"}
@@ -0,0 +1,246 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { createRequire } from 'node:module';
3
+ import { dirname, join } from 'node:path';
4
+ import { chromium } from 'playwright-core';
5
+ const _require = createRequire(import.meta.url);
6
+ const BROWSER_BUNDLE_PATH = join(dirname(_require.resolve('@guidepup/virtual-screen-reader/package.json')), 'lib', 'esm', 'index.browser.js');
7
+ const BUNDLE_INTERCEPT_URL = 'https://virtual-sr-local/bundle.js';
8
+ const ADAPT_VIRTUAL_COMMANDS = {
9
+ findNextHeading: 'moveToNextHeading',
10
+ findPreviousHeading: 'moveToPreviousHeading',
11
+ findNextLink: 'moveToNextLink',
12
+ findPreviousLink: 'moveToPreviousLink',
13
+ findNextControl: 'moveToNextForm',
14
+ findPreviousControl: 'moveToPreviousForm',
15
+ };
16
+ export class VirtualScreenReaderAdapter {
17
+ browser = null;
18
+ context = null;
19
+ page = null;
20
+ getPage() {
21
+ if (!this.page) {
22
+ throw new Error('No page loaded. Call loadUrl() or loadHtml() before using the virtual screen reader.');
23
+ }
24
+ return this.page;
25
+ }
26
+ async ensureBrowser() {
27
+ if (this.page) {
28
+ try {
29
+ await this.page.close();
30
+ }
31
+ catch {
32
+ /* ignore */
33
+ }
34
+ this.page = null;
35
+ }
36
+ if (this.context) {
37
+ try {
38
+ await this.context.close();
39
+ }
40
+ catch {
41
+ /* ignore */
42
+ }
43
+ this.context = null;
44
+ }
45
+ if (!this.browser) {
46
+ this.browser = await chromium.launch({ headless: true, channel: 'chrome' });
47
+ }
48
+ this.context = await this.browser.newContext({ bypassCSP: true });
49
+ this.page = await this.context.newPage();
50
+ const bundleSource = readFileSync(BROWSER_BUNDLE_PATH, 'utf-8');
51
+ await this.page.route(BUNDLE_INTERCEPT_URL, (route) => {
52
+ route.fulfill({ contentType: 'application/javascript', body: bundleSource });
53
+ });
54
+ return this.page;
55
+ }
56
+ async loadUrl(url) {
57
+ const page = await this.ensureBrowser();
58
+ await page.goto(url, { waitUntil: 'load' });
59
+ }
60
+ async loadHtml(html) {
61
+ const page = await this.ensureBrowser();
62
+ await page.setContent(html, { waitUntil: 'load' });
63
+ }
64
+ async start() {
65
+ const page = this.getPage();
66
+ await page.evaluate(async (bundleUrl) => {
67
+ const { virtual } = await import(bundleUrl);
68
+ globalThis.__guidepupVirtual = virtual;
69
+ await virtual.start({ container: globalThis.document.body });
70
+ }, BUNDLE_INTERCEPT_URL);
71
+ return { action: 'Virtual Screen Reader started successfully' };
72
+ }
73
+ async stop() {
74
+ if (this.page) {
75
+ try {
76
+ await this.page.evaluate(async () => {
77
+ const v = globalThis.__guidepupVirtual;
78
+ if (v)
79
+ await v.stop();
80
+ });
81
+ }
82
+ catch {
83
+ /* page may already be closed */
84
+ }
85
+ try {
86
+ await this.page.close();
87
+ }
88
+ catch {
89
+ /* ignore */
90
+ }
91
+ this.page = null;
92
+ }
93
+ if (this.context) {
94
+ try {
95
+ await this.context.close();
96
+ }
97
+ catch {
98
+ /* ignore */
99
+ }
100
+ this.context = null;
101
+ }
102
+ if (this.browser) {
103
+ try {
104
+ await this.browser.close();
105
+ }
106
+ catch {
107
+ /* ignore */
108
+ }
109
+ this.browser = null;
110
+ }
111
+ return { action: 'Virtual Screen Reader stopped successfully' };
112
+ }
113
+ async next() {
114
+ const data = await this.getPage().evaluate(async () => {
115
+ const v = globalThis.__guidepupVirtual;
116
+ await v.next();
117
+ return {
118
+ itemText: (await v.itemText()),
119
+ spokenPhrase: (await v.lastSpokenPhrase()),
120
+ };
121
+ });
122
+ return { action: 'moved to next item', ...data };
123
+ }
124
+ async previous() {
125
+ const data = await this.getPage().evaluate(async () => {
126
+ const v = globalThis.__guidepupVirtual;
127
+ await v.previous();
128
+ return {
129
+ itemText: (await v.itemText()),
130
+ spokenPhrase: (await v.lastSpokenPhrase()),
131
+ };
132
+ });
133
+ return { action: 'moved to previous item', ...data };
134
+ }
135
+ async act() {
136
+ const data = await this.getPage().evaluate(async () => {
137
+ const v = globalThis.__guidepupVirtual;
138
+ await v.act();
139
+ return { spokenPhrase: (await v.lastSpokenPhrase()) };
140
+ });
141
+ return { action: 'performed default action', ...data };
142
+ }
143
+ async interact() {
144
+ await this.getPage().evaluate(async () => {
145
+ const v = globalThis.__guidepupVirtual;
146
+ await v.interact();
147
+ });
148
+ return { action: 'interact (no-op in virtual screen reader)' };
149
+ }
150
+ async stopInteracting() {
151
+ await this.getPage().evaluate(async () => {
152
+ const v = globalThis.__guidepupVirtual;
153
+ await v.stopInteracting();
154
+ });
155
+ return { action: 'stop interacting (no-op in virtual screen reader)' };
156
+ }
157
+ async press(key) {
158
+ const data = await this.getPage().evaluate(async (k) => {
159
+ const v = globalThis.__guidepupVirtual;
160
+ await v.press(k);
161
+ return { spokenPhrase: (await v.lastSpokenPhrase()) };
162
+ }, key);
163
+ return { action: `pressed key: ${key}`, ...data };
164
+ }
165
+ async type(text) {
166
+ await this.getPage().evaluate(async (t) => {
167
+ const v = globalThis.__guidepupVirtual;
168
+ await v.type(t);
169
+ }, text);
170
+ return { action: `typed: ${text}` };
171
+ }
172
+ async perform(command) {
173
+ const virtualCommand = ADAPT_VIRTUAL_COMMANDS[command] ?? command;
174
+ const data = await this.getPage().evaluate(async (cmd) => {
175
+ const v = globalThis.__guidepupVirtual;
176
+ const cmdValue = v.commands[cmd];
177
+ if (!cmdValue) {
178
+ throw new Error(`Unknown command: ${cmd}. Available: ${Object.keys(v.commands).join(', ')}`);
179
+ }
180
+ await v.perform(cmdValue);
181
+ return {
182
+ itemText: (await v.itemText()),
183
+ spokenPhrase: (await v.lastSpokenPhrase()),
184
+ };
185
+ }, virtualCommand);
186
+ return { action: `performed command: ${command}`, ...data };
187
+ }
188
+ performCommander(_command) {
189
+ throw new Error('Commander commands are not supported in Virtual Screen Reader. Use perform() with virtual navigation commands instead (e.g., moveToNextLandmark, moveToNextHeadingLevel1).');
190
+ }
191
+ getCommanderCommands() {
192
+ return [];
193
+ }
194
+ async itemText() {
195
+ return this.getPage().evaluate(async () => {
196
+ const v = globalThis.__guidepupVirtual;
197
+ return (await v.itemText());
198
+ });
199
+ }
200
+ async lastSpokenPhrase() {
201
+ return this.getPage().evaluate(async () => {
202
+ const v = globalThis.__guidepupVirtual;
203
+ return (await v.lastSpokenPhrase());
204
+ });
205
+ }
206
+ async spokenPhraseLog() {
207
+ return this.getPage().evaluate(async () => {
208
+ const v = globalThis.__guidepupVirtual;
209
+ return (await v.spokenPhraseLog());
210
+ });
211
+ }
212
+ async itemTextLog() {
213
+ return this.getPage().evaluate(async () => {
214
+ const v = globalThis.__guidepupVirtual;
215
+ return (await v.itemTextLog());
216
+ });
217
+ }
218
+ async clearSpokenPhraseLog() {
219
+ await this.getPage().evaluate(async () => {
220
+ const v = globalThis.__guidepupVirtual;
221
+ await v.clearSpokenPhraseLog();
222
+ });
223
+ }
224
+ async clearItemTextLog() {
225
+ await this.getPage().evaluate(async () => {
226
+ const v = globalThis.__guidepupVirtual;
227
+ await v.clearItemTextLog();
228
+ });
229
+ }
230
+ async click(options) {
231
+ const button = options?.button ?? 'left';
232
+ const clickCount = options?.clickCount ?? 1;
233
+ await this.getPage().evaluate(async (opts) => {
234
+ const v = globalThis.__guidepupVirtual;
235
+ await v.click({ button: opts.button, clickCount: opts.clickCount });
236
+ }, { button, clickCount });
237
+ return { action: 'clicked mouse', spokenPhrase: `${button} click x${clickCount}` };
238
+ }
239
+ async detect() {
240
+ return true;
241
+ }
242
+ async isDefault() {
243
+ return false;
244
+ }
245
+ }
246
+ //# sourceMappingURL=virtual.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual.adapter.js","sourceRoot":"","sources":["../../../src/screen-readers/virtual/virtual.adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ToolModule } from '@weaaare/mcp-auditor-core';
2
+ import type { VirtualScreenReaderAdapter } from './virtual.adapter.js';
3
+ export declare const createVirtualTools: (adapter: VirtualScreenReaderAdapter) => ToolModule;
4
+ //# sourceMappingURL=virtual.tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual.tools.d.ts","sourceRoot":"","sources":["../../../src/screen-readers/virtual/virtual.tools.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAEzE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAqTvE,eAAO,MAAM,kBAAkB,GAAI,SAAS,0BAA0B,KAAG,UAGvE,CAAC"}
@@ -0,0 +1,297 @@
1
+ import { result } from '@weaaare/mcp-auditor-core';
2
+ const PERFORM_COMMAND_NAMES = [
3
+ 'findNextHeading',
4
+ 'findPreviousHeading',
5
+ 'findNextLink',
6
+ 'findPreviousLink',
7
+ 'findNextControl',
8
+ 'findPreviousControl',
9
+ 'moveToNextHeading',
10
+ 'moveToPreviousHeading',
11
+ 'moveToNextHeadingLevel1',
12
+ 'moveToPreviousHeadingLevel1',
13
+ 'moveToNextHeadingLevel2',
14
+ 'moveToPreviousHeadingLevel2',
15
+ 'moveToNextHeadingLevel3',
16
+ 'moveToPreviousHeadingLevel3',
17
+ 'moveToNextHeadingLevel4',
18
+ 'moveToPreviousHeadingLevel4',
19
+ 'moveToNextHeadingLevel5',
20
+ 'moveToPreviousHeadingLevel5',
21
+ 'moveToNextHeadingLevel6',
22
+ 'moveToPreviousHeadingLevel6',
23
+ 'moveToNextLink',
24
+ 'moveToPreviousLink',
25
+ 'moveToNextLandmark',
26
+ 'moveToPreviousLandmark',
27
+ 'moveToNextBanner',
28
+ 'moveToPreviousBanner',
29
+ 'moveToNextNavigation',
30
+ 'moveToPreviousNavigation',
31
+ 'moveToNextMain',
32
+ 'moveToPreviousMain',
33
+ 'moveToNextRegion',
34
+ 'moveToPreviousRegion',
35
+ 'moveToNextContentinfo',
36
+ 'moveToPreviousContentinfo',
37
+ 'moveToNextComplementary',
38
+ 'moveToPreviousComplementary',
39
+ 'moveToNextSearch',
40
+ 'moveToPreviousSearch',
41
+ 'moveToNextForm',
42
+ 'moveToPreviousForm',
43
+ 'moveToNextFigure',
44
+ 'moveToPreviousFigure',
45
+ 'jumpToControlledElement',
46
+ 'jumpToDetailsElement',
47
+ 'jumpToErrorMessageElement',
48
+ ];
49
+ const defineTools = () => [
50
+ {
51
+ name: 'virtual_start',
52
+ description: [
53
+ 'Start the Virtual Screen Reader on a live web page or provided HTML content.',
54
+ 'This launches a real browser (headless), navigates to the URL or loads the HTML,',
55
+ 'and injects a virtual screen reader that navigates the live accessibility tree.',
56
+ 'JavaScript on the page executes normally, so SPAs and dynamic content work.',
57
+ '',
58
+ "Provide either 'url' (preferred) or 'html'. If both are given, 'url' takes priority.",
59
+ '',
60
+ 'Typical workflow:',
61
+ '1. Call virtual_start with the URL to audit',
62
+ '2. Navigate with virtual_next, virtual_previous, virtual_perform, etc.',
63
+ '3. Call virtual_stop when done',
64
+ ].join('\n'),
65
+ inputSchema: {
66
+ type: 'object',
67
+ properties: {
68
+ url: {
69
+ type: 'string',
70
+ description: 'URL to audit. A real browser navigates to this URL, so JS executes and dynamic content renders.',
71
+ },
72
+ html: {
73
+ type: 'string',
74
+ description: 'Raw HTML content to audit. Used as fallback when no URL is provided.',
75
+ },
76
+ },
77
+ },
78
+ },
79
+ {
80
+ name: 'virtual_stop',
81
+ description: 'Stop the Virtual Screen Reader and release resources.',
82
+ inputSchema: { type: 'object', properties: {} },
83
+ },
84
+ {
85
+ name: 'virtual_next',
86
+ description: 'Move the Virtual Screen Reader cursor to the next item in the accessibility tree.',
87
+ inputSchema: { type: 'object', properties: {} },
88
+ },
89
+ {
90
+ name: 'virtual_previous',
91
+ description: 'Move the Virtual Screen Reader cursor to the previous item in the accessibility tree.',
92
+ inputSchema: { type: 'object', properties: {} },
93
+ },
94
+ {
95
+ name: 'virtual_act',
96
+ description: 'Perform the default action for the current item (e.g., activate a link or button).',
97
+ inputSchema: { type: 'object', properties: {} },
98
+ },
99
+ {
100
+ name: 'virtual_interact',
101
+ description: 'Interact with the current item. Note: this is a no-op in the Virtual Screen Reader.',
102
+ inputSchema: { type: 'object', properties: {} },
103
+ },
104
+ {
105
+ name: 'virtual_stop_interacting',
106
+ description: 'Stop interacting with the current item. Note: this is a no-op in the Virtual Screen Reader.',
107
+ inputSchema: { type: 'object', properties: {} },
108
+ },
109
+ {
110
+ name: 'virtual_press',
111
+ description: "Press a key on the focused item (e.g., 'Enter', 'Tab', 'ArrowDown', 'Command+f').",
112
+ inputSchema: {
113
+ type: 'object',
114
+ properties: {
115
+ key: {
116
+ type: 'string',
117
+ description: "Key to press (e.g., 'Enter', 'Tab', 'ArrowDown', 'Shift+Tab')",
118
+ },
119
+ },
120
+ required: ['key'],
121
+ },
122
+ },
123
+ {
124
+ name: 'virtual_type',
125
+ description: 'Type text into the focused item.',
126
+ inputSchema: {
127
+ type: 'object',
128
+ properties: { text: { type: 'string', description: 'Text to type' } },
129
+ required: ['text'],
130
+ },
131
+ },
132
+ {
133
+ name: 'virtual_perform',
134
+ description: [
135
+ 'Perform a navigation command in the Virtual Screen Reader.',
136
+ 'Supports semantic navigation by element type: headings (by level), links, landmarks, forms, figures, and ARIA relationships.',
137
+ '',
138
+ 'Common compatible commands: findNextHeading, findPreviousHeading, findNextLink, findPreviousLink, findNextControl, findPreviousControl.',
139
+ '',
140
+ 'Virtual-specific commands: moveToNextHeadingLevel1-6, moveToNextLandmark, moveToNextBanner, moveToNextNavigation, moveToNextMain, moveToNextRegion, etc.',
141
+ ].join('\n'),
142
+ inputSchema: {
143
+ type: 'object',
144
+ properties: {
145
+ command: {
146
+ type: 'string',
147
+ enum: [...PERFORM_COMMAND_NAMES],
148
+ description: 'Navigation command to perform',
149
+ },
150
+ },
151
+ required: ['command'],
152
+ },
153
+ },
154
+ {
155
+ name: 'virtual_item_text',
156
+ description: 'Get the text of the item currently under the Virtual Screen Reader cursor.',
157
+ inputSchema: { type: 'object', properties: {} },
158
+ },
159
+ {
160
+ name: 'virtual_last_spoken_phrase',
161
+ description: 'Get the last phrase spoken by the Virtual Screen Reader.',
162
+ inputSchema: { type: 'object', properties: {} },
163
+ },
164
+ {
165
+ name: 'virtual_spoken_phrase_log',
166
+ description: 'Get the log of all spoken phrases for this Virtual Screen Reader session.',
167
+ inputSchema: { type: 'object', properties: {} },
168
+ },
169
+ {
170
+ name: 'virtual_item_text_log',
171
+ description: 'Get the log of all visited item text for this Virtual Screen Reader session.',
172
+ inputSchema: { type: 'object', properties: {} },
173
+ },
174
+ {
175
+ name: 'virtual_clear_spoken_phrase_log',
176
+ description: 'Clear the log of all spoken phrases.',
177
+ inputSchema: { type: 'object', properties: {} },
178
+ },
179
+ {
180
+ name: 'virtual_clear_item_text_log',
181
+ description: 'Clear the log of all visited item text.',
182
+ inputSchema: { type: 'object', properties: {} },
183
+ },
184
+ {
185
+ name: 'virtual_click',
186
+ description: 'Click the mouse at the current position.',
187
+ inputSchema: {
188
+ type: 'object',
189
+ properties: {
190
+ button: {
191
+ type: 'string',
192
+ enum: ['left', 'right'],
193
+ description: 'Mouse button to click (default: left)',
194
+ },
195
+ clickCount: { type: 'number', description: 'Number of times to click (default: 1)' },
196
+ },
197
+ },
198
+ },
199
+ ];
200
+ const buildHandlers = (adapter) => {
201
+ const handlers = new Map();
202
+ handlers.set('virtual_start', async (args) => {
203
+ if (args.url) {
204
+ await adapter.loadUrl(args.url);
205
+ }
206
+ else if (args.html) {
207
+ await adapter.loadHtml(args.html);
208
+ }
209
+ else {
210
+ throw new Error("Either 'url' or 'html' parameter is required");
211
+ }
212
+ const res = await adapter.start();
213
+ return result.json(res);
214
+ });
215
+ handlers.set('virtual_stop', async () => {
216
+ const res = await adapter.stop();
217
+ return result.json(res);
218
+ });
219
+ handlers.set('virtual_next', async () => {
220
+ const res = await adapter.next();
221
+ return result.json(res);
222
+ });
223
+ handlers.set('virtual_previous', async () => {
224
+ const res = await adapter.previous();
225
+ return result.json(res);
226
+ });
227
+ handlers.set('virtual_act', async () => {
228
+ const res = await adapter.act();
229
+ return result.json(res);
230
+ });
231
+ handlers.set('virtual_interact', async () => {
232
+ const res = await adapter.interact();
233
+ return result.json(res);
234
+ });
235
+ handlers.set('virtual_stop_interacting', async () => {
236
+ const res = await adapter.stopInteracting();
237
+ return result.json(res);
238
+ });
239
+ handlers.set('virtual_press', async (args) => {
240
+ if (!args.key) {
241
+ throw new Error('key parameter is required');
242
+ }
243
+ const res = await adapter.press(args.key);
244
+ return result.json(res);
245
+ });
246
+ handlers.set('virtual_type', async (args) => {
247
+ if (!args.text) {
248
+ throw new Error('text parameter is required');
249
+ }
250
+ const res = await adapter.type(args.text);
251
+ return result.json(res);
252
+ });
253
+ handlers.set('virtual_perform', async (args) => {
254
+ if (!args.command) {
255
+ throw new Error('command parameter is required');
256
+ }
257
+ const res = await adapter.perform(args.command);
258
+ return result.json(res);
259
+ });
260
+ handlers.set('virtual_item_text', async () => {
261
+ const text = await adapter.itemText();
262
+ return result.text(text);
263
+ });
264
+ handlers.set('virtual_last_spoken_phrase', async () => {
265
+ const phrase = await adapter.lastSpokenPhrase();
266
+ return result.text(phrase);
267
+ });
268
+ handlers.set('virtual_spoken_phrase_log', async () => {
269
+ const log = await adapter.spokenPhraseLog();
270
+ return result.json(log);
271
+ });
272
+ handlers.set('virtual_item_text_log', async () => {
273
+ const log = await adapter.itemTextLog();
274
+ return result.json(log);
275
+ });
276
+ handlers.set('virtual_clear_spoken_phrase_log', async () => {
277
+ await adapter.clearSpokenPhraseLog();
278
+ return result.text('Spoken phrase log cleared');
279
+ });
280
+ handlers.set('virtual_clear_item_text_log', async () => {
281
+ await adapter.clearItemTextLog();
282
+ return result.text('Item text log cleared');
283
+ });
284
+ handlers.set('virtual_click', async (args) => {
285
+ const res = await adapter.click({
286
+ button: args.button ?? 'left',
287
+ clickCount: args.clickCount ?? 1,
288
+ });
289
+ return result.json(res);
290
+ });
291
+ return handlers;
292
+ };
293
+ export const createVirtualTools = (adapter) => ({
294
+ tools: defineTools(),
295
+ handlers: buildHandlers(adapter),
296
+ });
297
+ //# sourceMappingURL=virtual.tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"virtual.tools.js","sourceRoot":"","sources":["../../../src/screen-readers/virtual/virtual.tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ export declare const createServer: () => Server;
3
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAsBnE,eAAO,MAAM,YAAY,QAAO,MAsD/B,CAAC"}
package/dist/server.js ADDED
@@ -0,0 +1,48 @@
1
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
2
+ import { CallToolRequestSchema, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
3
+ import { AuditSession, createAuditTools, createReportTools, listResources, readResource, ToolRegistry, } from '@weaaare/mcp-auditor-core';
4
+ import packageVersion from '../package.json' with { type: 'json' };
5
+ import { getVirtualPromptMessages, listVirtualPrompts } from './prompts/virtual-prompts.js';
6
+ import { VirtualScreenReaderAdapter } from './screen-readers/virtual/virtual.adapter.js';
7
+ import { createVirtualTools } from './screen-readers/virtual/virtual.tools.js';
8
+ export const createServer = () => {
9
+ const server = new Server({
10
+ name: 'mcp-virtual-screen-reader-auditor',
11
+ version: packageVersion.version,
12
+ }, { capabilities: { tools: {}, prompts: {}, resources: {} } });
13
+ const adapter = new VirtualScreenReaderAdapter();
14
+ const session = new AuditSession();
15
+ const registry = new ToolRegistry();
16
+ registry.register(createVirtualTools(adapter));
17
+ registry.register(createAuditTools(session));
18
+ registry.register(createReportTools(session));
19
+ // --- Tools ---
20
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
21
+ tools: registry.listTools(),
22
+ }));
23
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
24
+ const { name, arguments: args } = request.params;
25
+ return registry.callTool(name, args ?? {});
26
+ });
27
+ // --- Prompts ---
28
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
29
+ prompts: listVirtualPrompts(),
30
+ }));
31
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
32
+ const { name, arguments: args } = request.params;
33
+ const messages = getVirtualPromptMessages(name, args ?? {});
34
+ return {
35
+ description: `Audit prompt: ${name}`,
36
+ messages,
37
+ };
38
+ });
39
+ // --- Resources ---
40
+ server.setRequestHandler(ListResourcesRequestSchema, async () => ({
41
+ resources: listResources(session),
42
+ }));
43
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
44
+ return readResource(request.params.uri, session);
45
+ });
46
+ return server;
47
+ };
48
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@weaaare/mcp-virtual-screen-reader-auditor",
3
+ "version": "0.0.1",
4
+ "description": "MCP server for virtual screen reader accessibility auditing — headless browser-based screen reader simulation that works on any OS",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "bin": {
8
+ "mcp-virtual-screen-reader-auditor": "dist/index.js"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "files": [
13
+ "dist"
14
+ ],
15
+ "scripts": {
16
+ "build": "tsc",
17
+ "check-types": "tsc --noEmit",
18
+ "lint": "biome check .",
19
+ "dev": "tsc --watch",
20
+ "test": "rstest --passWithNoTests"
21
+ },
22
+ "dependencies": {
23
+ "@guidepup/virtual-screen-reader": "catalog:",
24
+ "@modelcontextprotocol/sdk": "catalog:",
25
+ "@weaaare/mcp-auditor-core": "workspace:*",
26
+ "playwright-core": "catalog:"
27
+ },
28
+ "devDependencies": {
29
+ "@biomejs/biome": "catalog:",
30
+ "@rstest/core": "catalog:",
31
+ "@types/node": "catalog:",
32
+ "@weaaare/config": "workspace:*",
33
+ "typescript": "catalog:"
34
+ },
35
+ "keywords": [
36
+ "mcp",
37
+ "accessibility",
38
+ "a11y",
39
+ "virtual-screen-reader",
40
+ "screen-reader",
41
+ "wcag",
42
+ "headless"
43
+ ],
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "git+https://github.com/weAAAre/accessibility-ai.git",
47
+ "directory": "packages/mcp-virtual-screen-reader-auditor"
48
+ },
49
+ "homepage": "https://github.com/weAAAre/accessibility-ai/tree/main/packages/mcp-virtual-screen-reader-auditor#readme",
50
+ "bugs": {
51
+ "url": "https://github.com/weAAAre/accessibility-ai/issues"
52
+ },
53
+ "author": "weAAAre <hola@weAAAre.com> (https://weAAAre.com)",
54
+ "engines": {
55
+ "node": ">=24"
56
+ }
57
+ }