Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/TOOLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ searchCapability → describeCapability → invokeCapability
| Tool | What it does |
|---|---|
| `startAccessibilityScan` | Start a web accessibility scan of a page URL and retrieve a local CSV report path. Optional settings: `wcagVersion` (WCAG 2.0–2.2 at A/AA/AAA, or RGAA 4.1), `bestPractices`, `needsReview`, `advancedRules` and `experimentalRules`; the answer states the settings the scan ran with. To scan the same page again (for example after a fix), pass the earlier scan's `scanId`: that starts a new run of that scan with its saved settings, which `fetchAccessibilityIssues` can compare with `compareWith: "previous"`. Mobile apps are scanned through an App Automate run instead (`setupBrowserStackAppAutomateTests` with `accessibility: true`). |
| `accessibilityExpert` | Ask the A11y Expert (WCAG 2.0/2.1/2.2, mobile/web usability, best practices). |
| `accessibilityExpert` | **Deprecated, to be removed.** Ask the A11y Expert (WCAG 2.0/2.1/2.2, mobile/web usability, best practices). |
| `createAccessibilityAuthConfig` | Create an authentication configuration (form-based or basic) for accessibility scans behind a login. |
| `getAccessibilityAuthConfig` | Retrieve an existing accessibility authentication configuration by ID. |
| `fetchAccessibilityIssues` | Fetch accessibility issues, with pagination, from a Website Scanner run, an Automated Tests build (web) or App Accessibility build (mobile app, by the build id the SDK prints), a Workflow Analyzer report, an App Accessibility manual report (`appReportId`), or a report's dashboard link (a Website Scanner link is read by the run's build id, however old the scan; a Workflow Analyzer link by the report id it carries). Once the tests or scan have finished, a report that is still processing is not waited on: the answer says to call again in a minute or two; a run still in progress is read as it is, with a note. For an app build with no scans, lists the likely causes. |
Expand Down
25 changes: 18 additions & 7 deletions src/tools/accessibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,13 @@ async function initializeReportFetcher(
return reportFetcher;
}

/**
* accessibilityExpert is going away; until it is removed it still answers, with this note,
* which names what to use instead so an agent stops reaching for it.
*/
const ACCESSIBILITY_EXPERT_DEPRECATED =
"Note: accessibilityExpert is deprecated and will be removed in a future release. To list or filter a report's issues, for example those failing a WCAG criterion, use fetchAccessibilityIssues and answer from its result; to scan a page, use startAccessibilityScan. For advice on a report, such as how to raise its score or which issues to fix first, call askBrowserStackAI with product a11y and give the user its answer. If askBrowserStackAI says it is not enabled for this account, answer from the report's issues.";

async function executeAccessibilityRAG(
args: { query: string },
server: McpServer,
Expand All @@ -172,14 +179,18 @@ async function executeAccessibilityRAG(
);
const { query, shortened, kept } = fitExpertQuery(args.query);
const answer = await queryAccessibilityRAG(query, config);
if (!shortened) return answer;
return {
...answer,
content: [
{
type: "text",
text: `The question was ${args.query.length} characters; the knowledge base takes at most ${EXPERT_QUERY_MAX_CHARS}, so ${query.length} were sent: its ${kept ?? "opening"}. If the answer misses the point, ask again more briefly.`,
},
{ type: "text", text: ACCESSIBILITY_EXPERT_DEPRECATED },
...(shortened
? [
{
type: "text" as const,
text: `The question was ${args.query.length} characters; the knowledge base takes at most ${EXPERT_QUERY_MAX_CHARS}, so ${query.length} were sent: its ${kept ?? "opening"}. If the answer misses the point, ask again more briefly.`,
},
]
: []),
...(answer.content ?? []),
],
};
Expand Down Expand Up @@ -1983,7 +1994,7 @@ export default function addAccessibilityTools(

tools.accessibilityExpert = server.tool(
"accessibilityExpert",
"Answer accessibility, a11y, and WCAG questions using BrowserStack's accessibility knowledge base.",
"Deprecated, to be removed: answers accessibility, a11y, and WCAG questions from BrowserStack's accessibility knowledge base.",
{
query: z
.string()
Expand All @@ -1992,7 +2003,7 @@ export default function addAccessibilityTools(
),
},
{
title: "Accessibility Expert",
title: "Accessibility Expert (deprecated)",
readOnlyHint: true,
openWorldHint: false,
destructiveHint: false,
Expand Down
9 changes: 6 additions & 3 deletions tests/tools/accessibilityExpertQuery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,19 @@ describe("accessibilityExpert with a long question", () => {
const result = await ask(query);

const sent: string = rag.query.mock.calls[0][0];
expect(result.content[0].text).toBe(
expect(result.content[0].text).toMatch(/^Note: accessibilityExpert is deprecated/);
expect(result.content[1].text).toBe(
`The question was ${query.length} characters; the knowledge base takes at most ${EXPERT_QUERY_MAX_CHARS}, so ${sent.length} were sent: its ${kept}. If the answer misses the point, ask again more briefly.`,
);
expect(result.content.at(-1).text).toBe("Answer.");
});

it("adds no note to a question within the limit", async () => {
it("adds only the deprecation note to a question within the limit", async () => {
const result = await ask(QUESTION);

expect(rag.query.mock.calls[0][0]).toBe(QUESTION);
expect(result.content).toEqual([{ type: "text", text: "Answer." }]);
expect(result.content).toHaveLength(2);
expect(result.content[0].text).toMatch(/^Note: accessibilityExpert is deprecated/);
expect(result.content[1]).toEqual({ type: "text", text: "Answer." });
});
});
Loading