@atlaskit/ads-mcp 0.18.1 → 0.19.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/CHANGELOG.md +9 -0
- package/README.md +2 -2
- package/dist/cjs/helpers/fuse-multi-term.js +130 -0
- package/dist/cjs/helpers/index.js +15 -1
- package/dist/cjs/index.js +28 -14
- package/dist/cjs/instructions.js +1 -1
- package/dist/cjs/tools/analyze-a11y/index.js +12 -12
- package/dist/cjs/tools/get-a11y-guidelines/index.js +3 -3
- package/dist/cjs/tools/{get-components → get-all-components}/index.js +6 -6
- package/dist/cjs/tools/get-all-icons/index.js +1 -1
- package/dist/cjs/tools/get-all-tokens/index.js +1 -1
- package/dist/cjs/tools/get-guidelines/index.js +4 -4
- package/dist/cjs/tools/get-lint-rules/index.js +5 -5
- package/dist/cjs/tools/i18n-conversion/index.js +3 -3
- package/dist/cjs/tools/migration-guides/index.js +3 -3
- package/dist/cjs/tools/plan/index.js +13 -17
- package/dist/cjs/tools/search-components/index.js +44 -65
- package/dist/cjs/tools/search-icons/index.js +42 -68
- package/dist/cjs/tools/search-tokens/index.js +56 -43
- package/dist/cjs/tools/suggest-a11y-fixes/index.js +7 -7
- package/dist/es2019/helpers/fuse-multi-term.js +98 -0
- package/dist/es2019/helpers/index.js +1 -0
- package/dist/es2019/index.js +81 -83
- package/dist/es2019/instructions.js +2 -1
- package/dist/es2019/tools/analyze-a11y/index.js +28 -12
- package/dist/es2019/tools/get-a11y-guidelines/index.js +10 -3
- package/dist/es2019/tools/{get-components → get-all-components}/index.js +9 -4
- package/dist/es2019/tools/get-all-icons/index.js +6 -1
- package/dist/es2019/tools/get-all-tokens/index.js +6 -1
- package/dist/es2019/tools/get-guidelines/index.js +20 -7
- package/dist/es2019/tools/get-lint-rules/index.js +12 -8
- package/dist/es2019/tools/i18n-conversion/index.js +10 -13
- package/dist/es2019/tools/migration-guides/index.js +10 -4
- package/dist/es2019/tools/plan/index.js +25 -25
- package/dist/es2019/tools/search-components/index.js +42 -56
- package/dist/es2019/tools/search-icons/index.js +37 -62
- package/dist/es2019/tools/search-tokens/index.js +54 -45
- package/dist/es2019/tools/suggest-a11y-fixes/index.js +16 -7
- package/dist/esm/helpers/fuse-multi-term.js +122 -0
- package/dist/esm/helpers/index.js +1 -0
- package/dist/esm/index.js +28 -14
- package/dist/esm/instructions.js +1 -1
- package/dist/esm/tools/analyze-a11y/index.js +12 -12
- package/dist/esm/tools/get-a11y-guidelines/index.js +3 -3
- package/dist/esm/tools/{get-components → get-all-components}/index.js +5 -5
- package/dist/esm/tools/get-all-icons/index.js +1 -1
- package/dist/esm/tools/get-all-tokens/index.js +1 -1
- package/dist/esm/tools/get-guidelines/index.js +4 -4
- package/dist/esm/tools/get-lint-rules/index.js +5 -5
- package/dist/esm/tools/i18n-conversion/index.js +3 -3
- package/dist/esm/tools/migration-guides/index.js +3 -3
- package/dist/esm/tools/plan/index.js +13 -17
- package/dist/esm/tools/search-components/index.js +45 -66
- package/dist/esm/tools/search-icons/index.js +43 -69
- package/dist/esm/tools/search-tokens/index.js +57 -44
- package/dist/esm/tools/suggest-a11y-fixes/index.js +7 -7
- package/dist/types/helpers/fuse-multi-term.d.ts +45 -0
- package/dist/types/helpers/index.d.ts +1 -0
- package/dist/types/instructions.d.ts +1 -1
- package/dist/types/tools/{get-components → get-all-components}/index.d.ts +2 -2
- package/dist/types/tools/plan/index.d.ts +1 -4
- package/dist/types/tools/search-components/index.d.ts +1 -4
- package/dist/types/tools/search-icons/index.d.ts +1 -4
- package/dist/types/tools/search-tokens/index.d.ts +1 -4
- package/dist/types-ts4.5/helpers/fuse-multi-term.d.ts +45 -0
- package/dist/types-ts4.5/helpers/index.d.ts +1 -0
- package/dist/types-ts4.5/instructions.d.ts +1 -1
- package/dist/types-ts4.5/tools/{get-components → get-all-components}/index.d.ts +2 -2
- package/dist/types-ts4.5/tools/plan/index.d.ts +1 -4
- package/dist/types-ts4.5/tools/search-components/index.d.ts +1 -4
- package/dist/types-ts4.5/tools/search-icons/index.d.ts +1 -4
- package/dist/types-ts4.5/tools/search-tokens/index.d.ts +1 -4
- package/package.json +5 -5
- /package/dist/cjs/tools/{get-components → get-all-components}/components.codegen.js +0 -0
- /package/dist/cjs/tools/{get-components → get-all-components}/components.js +0 -0
- /package/dist/cjs/tools/{get-components → get-all-components}/load-all-components.js +0 -0
- /package/dist/cjs/tools/{get-components → get-all-components}/types.js +0 -0
- /package/dist/es2019/tools/{get-components → get-all-components}/components.codegen.js +0 -0
- /package/dist/es2019/tools/{get-components → get-all-components}/components.js +0 -0
- /package/dist/es2019/tools/{get-components → get-all-components}/load-all-components.js +0 -0
- /package/dist/es2019/tools/{get-components → get-all-components}/types.js +0 -0
- /package/dist/esm/tools/{get-components → get-all-components}/components.codegen.js +0 -0
- /package/dist/esm/tools/{get-components → get-all-components}/components.js +0 -0
- /package/dist/esm/tools/{get-components → get-all-components}/load-all-components.js +0 -0
- /package/dist/esm/tools/{get-components → get-all-components}/types.js +0 -0
- /package/dist/types/tools/{get-components → get-all-components}/components.codegen.d.ts +0 -0
- /package/dist/types/tools/{get-components → get-all-components}/components.d.ts +0 -0
- /package/dist/types/tools/{get-components → get-all-components}/load-all-components.d.ts +0 -0
- /package/dist/types/tools/{get-components → get-all-components}/types.d.ts +0 -0
- /package/dist/types-ts4.5/tools/{get-components → get-all-components}/components.codegen.d.ts +0 -0
- /package/dist/types-ts4.5/tools/{get-components → get-all-components}/components.d.ts +0 -0
- /package/dist/types-ts4.5/tools/{get-components → get-all-components}/load-all-components.d.ts +0 -0
- /package/dist/types-ts4.5/tools/{get-components → get-all-components}/types.d.ts +0 -0
|
@@ -19,16 +19,16 @@ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol
|
|
|
19
19
|
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
20
20
|
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } /* eslint-disable-next-line import/extensions -- MCP SDK requires .js extensions for ESM imports */
|
|
21
21
|
var suggestA11yFixesInputSchema = exports.suggestA11yFixesInputSchema = _zod.z.object({
|
|
22
|
-
violation: _zod.z.string().describe('
|
|
23
|
-
code: _zod.z.string().describe('
|
|
24
|
-
component: _zod.z.string().optional().describe('
|
|
25
|
-
context: _zod.z.string().optional().describe('
|
|
22
|
+
violation: _zod.z.string().describe('Human-readable description of the issue (e.g. axe rule help text, "button has no accessible name", "missing alt"). Used to match curated recipes when possible; otherwise the tool falls back to generic guidance.'),
|
|
23
|
+
code: _zod.z.string().describe('Snippet of the problematic code or markup so the response can be tailored (may be shown in the output for traceability).'),
|
|
24
|
+
component: _zod.z.string().optional().describe('Optional: React component name involved (e.g. `Button`, `TextField`)—may be ADS or app-specific.'),
|
|
25
|
+
context: _zod.z.string().optional().describe('Optional: where this appears (e.g. modal, table row, page section) or constraints.')
|
|
26
26
|
});
|
|
27
27
|
var listSuggestA11yFixesTool = exports.listSuggestA11yFixesTool = {
|
|
28
28
|
name: 'ads_suggest_a11y_fixes',
|
|
29
|
-
description: "Suggests
|
|
29
|
+
description: "Suggests remediation steps for an accessibility issue described in natural language (often pasted from **axe-core**, ESLint, or review).\n\nWHAT YOU GET (varies by match):\n- **Curated hit:** ADS-biased examples and patterns from this server\u2019s recipe map (components, tokens, common fixes).\n- **No strong match:** Generic guidance (e.g. \u201Cuse ADS components\u201D, labeling, testing)\u2014still useful, but **not** guaranteed to be ADS-specific. May reference axe/atlassian.design resources.\n\nWHEN TO USE:\nAfter `ads_analyze_a11y` or `ads_analyze_localhost_a11y`, or whenever you have a violation string. For **topic-level** Atlassian Design System accessibility guidance, call `ads_get_a11y_guidelines` (this tool is fix-oriented, not a full guideline browse).\n\nDoes not replace manual testing with assistive technologies or keyboard-only navigation.",
|
|
30
30
|
annotations: {
|
|
31
|
-
title: 'Suggest
|
|
31
|
+
title: 'Suggest accessibility fixes',
|
|
32
32
|
readOnlyHint: true,
|
|
33
33
|
destructiveHint: false,
|
|
34
34
|
idempotentHint: true,
|
|
@@ -169,7 +169,7 @@ var suggestA11yFixesTool = exports.suggestA11yFixesTool = /*#__PURE__*/function
|
|
|
169
169
|
availableFixTypes: Object.keys(_fixes.accessibilityFixes),
|
|
170
170
|
suggestions: ['Try describing the issue with keywords like: button, label, missing, text, color, contrast, focus, etc.', 'Use axe-core violation IDs or descriptions directly', 'Be more specific about the element type (button, input, image, etc.)'],
|
|
171
171
|
additionalResources: ['https://atlassian.design/llms-a11y.txt - Complete ADS accessibility documentation', 'https://atlassian.design/foundations/accessibility - ADS accessibility foundation'],
|
|
172
|
-
recommendation: 'Try the
|
|
172
|
+
recommendation: 'Try the ads_get_a11y_guidelines tool for component-specific guidance'
|
|
173
173
|
}, null, 2)
|
|
174
174
|
}]
|
|
175
175
|
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Allocation for multi-query Fuse search: each term alone, plus one spaced combined query.
|
|
3
|
+
*
|
|
4
|
+
* `poolMax = limit * termCount`. From each term we take up to `perTermTake` hits; the rest of the
|
|
5
|
+
* pool is filled from the spaced combined query.
|
|
6
|
+
*/
|
|
7
|
+
export function computeMultiTermFuseAllocation(limit, termCount) {
|
|
8
|
+
if (termCount <= 1) return {
|
|
9
|
+
perTermTake: 1,
|
|
10
|
+
combinedTake: 0,
|
|
11
|
+
totalTake: 1
|
|
12
|
+
};
|
|
13
|
+
const perTermTake = Math.max(Math.round(limit / termCount), 1);
|
|
14
|
+
const combinedTake = Math.max(limit * termCount - termCount * perTermTake, 1);
|
|
15
|
+
const totalTake = Math.max(perTermTake * termCount + combinedTake, 1);
|
|
16
|
+
return {
|
|
17
|
+
perTermTake,
|
|
18
|
+
combinedTake,
|
|
19
|
+
totalTake
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Runs `search` for each term (top `perTermTake`) and for `terms.join(' ')` (top `combinedTake`),
|
|
24
|
+
* merges pools, sorts globally by Fuse score, then returns the first `limit` **distinct** keys
|
|
25
|
+
* (later duplicate keys are skipped).
|
|
26
|
+
*
|
|
27
|
+
* Default `tokenKey` uses `item.name` when present; pass an explicit `tokenKey` for types without
|
|
28
|
+
* `name` (e.g. icons keyed by `componentName`).
|
|
29
|
+
*/
|
|
30
|
+
export function mergeMultiTermFuseResults({
|
|
31
|
+
searchTerms,
|
|
32
|
+
limit,
|
|
33
|
+
search,
|
|
34
|
+
tokenKey = item => {
|
|
35
|
+
var _name;
|
|
36
|
+
return String((_name = item.name) !== null && _name !== void 0 ? _name : '');
|
|
37
|
+
},
|
|
38
|
+
searchTermsJoin = ' '
|
|
39
|
+
}) {
|
|
40
|
+
const n = searchTerms.length;
|
|
41
|
+
if (n === 0) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
if (n === 1) {
|
|
45
|
+
return takeFirstUniqueKeys(sortByScoreAsc(toScoredHits(search(searchTerms[0]), tokenKey)), limit);
|
|
46
|
+
}
|
|
47
|
+
const {
|
|
48
|
+
perTermTake,
|
|
49
|
+
combinedTake,
|
|
50
|
+
totalTake
|
|
51
|
+
} = computeMultiTermFuseAllocation(limit, n);
|
|
52
|
+
const termsCombined = searchTerms.join(searchTermsJoin);
|
|
53
|
+
const pool = [];
|
|
54
|
+
for (const term of searchTerms) {
|
|
55
|
+
pool.push(...topRankedFromQuery(search, term, tokenKey, perTermTake));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Combine the terms together and search as well.
|
|
59
|
+
pool.push(...topRankedFromQuery(search, termsCombined, tokenKey, combinedTake));
|
|
60
|
+
|
|
61
|
+
// Grab the top combinations of all queries' results.
|
|
62
|
+
return takeFirstUniqueKeys(sortByScoreAsc(pool), totalTake);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Best `take` hits for one Fuse query (ranked by score, then slice).
|
|
67
|
+
*/
|
|
68
|
+
function topRankedFromQuery(search, query, tokenKey, take) {
|
|
69
|
+
return sortByScoreAsc(toScoredHits(search(query), tokenKey)).slice(0, take);
|
|
70
|
+
}
|
|
71
|
+
function toScoredHits(fuseHits, tokenKey) {
|
|
72
|
+
return fuseHits.map(hit => {
|
|
73
|
+
var _hit$score;
|
|
74
|
+
return {
|
|
75
|
+
item: hit.item,
|
|
76
|
+
score: (_hit$score = hit.score) !== null && _hit$score !== void 0 ? _hit$score : Number.POSITIVE_INFINITY,
|
|
77
|
+
key: tokenKey(hit.item)
|
|
78
|
+
};
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
function sortByScoreAsc(hits) {
|
|
82
|
+
return [...hits].sort((a, b) => a.score - b.score);
|
|
83
|
+
}
|
|
84
|
+
function takeFirstUniqueKeys(sortedHits, limit) {
|
|
85
|
+
const seen = new Set();
|
|
86
|
+
const out = [];
|
|
87
|
+
for (const h of sortedHits) {
|
|
88
|
+
if (seen.has(h.key)) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
seen.add(h.key);
|
|
92
|
+
out.push(h.item);
|
|
93
|
+
if (out.length >= limit) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return out;
|
|
98
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/* eslint-disable-next-line import/extensions -- MCP SDK requires .js extensions for ESM imports */
|
|
2
2
|
|
|
3
3
|
import { zodToJsonSchema as zodToJsonSchemaHelper } from 'zod-to-json-schema';
|
|
4
|
+
export { computeMultiTermFuseAllocation, mergeMultiTermFuseResults } from './fuse-multi-term';
|
|
4
5
|
export const cleanQuery = query => query.trim().toLowerCase().replace(/\s+/g, '');
|
|
5
6
|
export const zodToJsonSchema = (schema, options) => {
|
|
6
7
|
return zodToJsonSchemaHelper(schema, options);
|
package/dist/es2019/index.js
CHANGED
|
@@ -7,14 +7,17 @@ import { validateToolArguments } from './helpers/validation';
|
|
|
7
7
|
import { instructions } from './instructions';
|
|
8
8
|
import { analyzeA11yInputSchema, analyzeA11yLocalhostInputSchema, analyzeA11yTool, analyzeLocalhostA11yTool, listAnalyzeA11yTool, listAnalyzeLocalhostA11yTool } from './tools/analyze-a11y';
|
|
9
9
|
import { getA11yGuidelinesInputSchema, getA11yGuidelinesTool, listGetA11yGuidelinesTool } from './tools/get-a11y-guidelines';
|
|
10
|
+
import { getAllComponentsTool, listGetAllComponentsTool } from './tools/get-all-components';
|
|
10
11
|
import { getAllIconsTool, listGetAllIconsTool } from './tools/get-all-icons';
|
|
11
12
|
import { getAllTokensTool, listGetAllTokensTool } from './tools/get-all-tokens';
|
|
12
|
-
import { getComponentsTool, listGetComponentsTool } from './tools/get-components';
|
|
13
13
|
import { getGuidelinesInputSchema, getGuidelinesTool, listGetGuidelinesTool } from './tools/get-guidelines';
|
|
14
14
|
import { getLintRulesInputSchema, getLintRulesTool, listGetLintRulesTool } from './tools/get-lint-rules';
|
|
15
15
|
import { i18nConversionInputSchema, i18nConversionTool, listI18nConversionTool } from './tools/i18n-conversion';
|
|
16
16
|
import { listMigrationGuidesTool, migrationGuidesInputSchema, migrationGuidesTool } from './tools/migration-guides';
|
|
17
17
|
import { listPlanTool, planInputSchema, planTool } from './tools/plan';
|
|
18
|
+
import { listSearchComponentsTool, searchComponentsInputSchema, searchComponentsTool } from './tools/search-components';
|
|
19
|
+
import { listSearchIconsTool, searchIconsInputSchema, searchIconsTool } from './tools/search-icons';
|
|
20
|
+
import { listSearchTokensTool, searchTokensInputSchema, searchTokensTool } from './tools/search-tokens';
|
|
18
21
|
import { listSuggestA11yFixesTool, suggestA11yFixesInputSchema, suggestA11yFixesTool } from './tools/suggest-a11y-fixes';
|
|
19
22
|
|
|
20
23
|
// 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
|
|
@@ -45,88 +48,83 @@ const generateLogger = level => (...args) => {
|
|
|
45
48
|
console.error(`[ads-mcp.custom-logging][${level}]`, ...args);
|
|
46
49
|
}
|
|
47
50
|
};
|
|
48
|
-
export const getToolRegistry = () => {
|
|
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
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
tool: listGetLintRulesTool
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
return baseTools;
|
|
129
|
-
};
|
|
51
|
+
export const getToolRegistry = () => ({
|
|
52
|
+
[listAnalyzeA11yTool.name]: {
|
|
53
|
+
handler: analyzeA11yTool,
|
|
54
|
+
inputSchema: analyzeA11yInputSchema,
|
|
55
|
+
tool: listAnalyzeA11yTool
|
|
56
|
+
},
|
|
57
|
+
[listAnalyzeLocalhostA11yTool.name]: {
|
|
58
|
+
handler: analyzeLocalhostA11yTool,
|
|
59
|
+
inputSchema: analyzeA11yLocalhostInputSchema,
|
|
60
|
+
tool: listAnalyzeLocalhostA11yTool
|
|
61
|
+
},
|
|
62
|
+
[listGetA11yGuidelinesTool.name]: {
|
|
63
|
+
handler: getA11yGuidelinesTool,
|
|
64
|
+
inputSchema: getA11yGuidelinesInputSchema,
|
|
65
|
+
tool: listGetA11yGuidelinesTool
|
|
66
|
+
},
|
|
67
|
+
[listGetAllComponentsTool.name]: {
|
|
68
|
+
handler: getAllComponentsTool,
|
|
69
|
+
inputSchema: null,
|
|
70
|
+
tool: listGetAllComponentsTool
|
|
71
|
+
},
|
|
72
|
+
[listPlanTool.name]: {
|
|
73
|
+
handler: planTool,
|
|
74
|
+
inputSchema: planInputSchema,
|
|
75
|
+
tool: listPlanTool
|
|
76
|
+
},
|
|
77
|
+
[listSearchComponentsTool.name]: {
|
|
78
|
+
handler: searchComponentsTool,
|
|
79
|
+
inputSchema: searchComponentsInputSchema,
|
|
80
|
+
tool: listSearchComponentsTool
|
|
81
|
+
},
|
|
82
|
+
[listSearchIconsTool.name]: {
|
|
83
|
+
handler: searchIconsTool,
|
|
84
|
+
inputSchema: searchIconsInputSchema,
|
|
85
|
+
tool: listSearchIconsTool
|
|
86
|
+
},
|
|
87
|
+
[listSearchTokensTool.name]: {
|
|
88
|
+
handler: searchTokensTool,
|
|
89
|
+
inputSchema: searchTokensInputSchema,
|
|
90
|
+
tool: listSearchTokensTool
|
|
91
|
+
},
|
|
92
|
+
[listSuggestA11yFixesTool.name]: {
|
|
93
|
+
handler: suggestA11yFixesTool,
|
|
94
|
+
inputSchema: suggestA11yFixesInputSchema,
|
|
95
|
+
tool: listSuggestA11yFixesTool
|
|
96
|
+
},
|
|
97
|
+
[listMigrationGuidesTool.name]: {
|
|
98
|
+
handler: migrationGuidesTool,
|
|
99
|
+
inputSchema: migrationGuidesInputSchema,
|
|
100
|
+
tool: listMigrationGuidesTool
|
|
101
|
+
},
|
|
102
|
+
[listI18nConversionTool.name]: {
|
|
103
|
+
handler: i18nConversionTool,
|
|
104
|
+
inputSchema: i18nConversionInputSchema,
|
|
105
|
+
tool: listI18nConversionTool
|
|
106
|
+
},
|
|
107
|
+
[listGetGuidelinesTool.name]: {
|
|
108
|
+
handler: getGuidelinesTool,
|
|
109
|
+
inputSchema: getGuidelinesInputSchema,
|
|
110
|
+
tool: listGetGuidelinesTool
|
|
111
|
+
},
|
|
112
|
+
[listGetAllTokensTool.name]: {
|
|
113
|
+
handler: getAllTokensTool,
|
|
114
|
+
inputSchema: null,
|
|
115
|
+
tool: listGetAllTokensTool
|
|
116
|
+
},
|
|
117
|
+
[listGetAllIconsTool.name]: {
|
|
118
|
+
handler: getAllIconsTool,
|
|
119
|
+
inputSchema: null,
|
|
120
|
+
tool: listGetAllIconsTool
|
|
121
|
+
},
|
|
122
|
+
[listGetLintRulesTool.name]: {
|
|
123
|
+
handler: getLintRulesTool,
|
|
124
|
+
inputSchema: getLintRulesInputSchema,
|
|
125
|
+
tool: listGetLintRulesTool
|
|
126
|
+
}
|
|
127
|
+
});
|
|
130
128
|
server.setRequestHandler(ListToolsRequestSchema, async (request, extra) => {
|
|
131
129
|
const toolRegistry = getToolRegistry();
|
|
132
130
|
const tools = Object.values(toolRegistry).map(toolConfig => toolConfig.tool);
|
|
@@ -3,5 +3,6 @@ You are an expert in the Atlassian Design System (ADS).
|
|
|
3
3
|
You can search for tokens, icons, and components and return guidance on how to build user interfaces.
|
|
4
4
|
You have special accessibility knowledge and can ensure interfaces built with ADS components are accessible to all users.
|
|
5
5
|
You can analyze code for accessibility violations, provide specific fix suggestions, and offer guidance on accessibility best practices.
|
|
6
|
-
|
|
6
|
+
For org-wide standards alongside ADS tools: pair Context Engine \`get_accessibility_docs\` with \`ads_get_a11y_guidelines\`, \`get_content_standards_docs\` with \`ads_get_guidelines\`, and \`get_i18n_docs\` with \`ads_i18n_conversion_guide\` (Traduki/i18n policy plus the bundled formatMessage refactor guide).
|
|
7
|
+
These tools will support you, but for deep research you may also fetch https://atlassian.design/llms.txt, https://atlassian.design/llms-a11y.txt, or https://atlassian.design/ directly.
|
|
7
8
|
`;
|
|
@@ -6,16 +6,23 @@ import puppeteer from 'puppeteer';
|
|
|
6
6
|
import { z } from 'zod';
|
|
7
7
|
import { zodToJsonSchema } from '../../helpers';
|
|
8
8
|
export const analyzeA11yInputSchema = z.object({
|
|
9
|
-
code: z.string().describe('React component
|
|
10
|
-
componentName: z.string().describe('
|
|
11
|
-
context: z.string().describe('
|
|
12
|
-
includePatternAnalysis: z.boolean().default(true).describe('
|
|
9
|
+
code: z.string().describe('Source code of a React component or JSX snippet to analyze (string content only—no file path).'),
|
|
10
|
+
componentName: z.string().optional().describe('Optional label for the component under review (for summaries and reports).'),
|
|
11
|
+
context: z.string().optional().describe('Optional: how the component is used (e.g. in a form, modal) to improve suggestions.'),
|
|
12
|
+
includePatternAnalysis: z.boolean().default(true).describe('When true (default), runs regex-based heuristics on the code string (e.g. unlabeled buttons, missing alt) in addition to other analysis.').optional()
|
|
13
13
|
});
|
|
14
14
|
export const listAnalyzeA11yTool = {
|
|
15
15
|
name: 'ads_analyze_a11y',
|
|
16
|
-
description:
|
|
16
|
+
description: `Analyzes a **string of React/JSX** code for likely accessibility issues (heuristics and/or axe-related paths) and returns hints that often **point to** \`ads_suggest_a11y_fixes\` or generic axe/WCAG-style context—not every finding maps to a specific ADS component fix.
|
|
17
|
+
|
|
18
|
+
WHEN TO USE:
|
|
19
|
+
You have component source as text and want automated checks or heuristics before or during a code review.
|
|
20
|
+
|
|
21
|
+
LIMITATIONS:
|
|
22
|
+
- Does not replace testing in a real browser with assistive technologies or full keyboard traversal.
|
|
23
|
+
- For rendered UI, \`ads_analyze_localhost_a11y\` (live URL + axe) is preferable when available—it is **only exposed when this MCP runs locally**, not in the remote MCP deployment.`,
|
|
17
24
|
annotations: {
|
|
18
|
-
title: 'Analyze
|
|
25
|
+
title: 'Analyze accessibility (code string)',
|
|
19
26
|
readOnlyHint: true,
|
|
20
27
|
destructiveHint: false,
|
|
21
28
|
idempotentHint: true,
|
|
@@ -24,16 +31,25 @@ export const listAnalyzeA11yTool = {
|
|
|
24
31
|
inputSchema: zodToJsonSchema(analyzeA11yInputSchema)
|
|
25
32
|
};
|
|
26
33
|
export const analyzeA11yLocalhostInputSchema = z.object({
|
|
27
|
-
url: z.string().describe('
|
|
28
|
-
componentName: z.string().optional().describe('
|
|
29
|
-
context: z.string().optional().describe('
|
|
30
|
-
selector: z.string().optional().describe('CSS selector to
|
|
34
|
+
url: z.string().describe('Fully qualified page URL to load (e.g. `http://localhost:9000` or a dev URL). Must be reachable from this MCP process.'),
|
|
35
|
+
componentName: z.string().optional().describe('Optional label for reporting (e.g. feature or component under test).'),
|
|
36
|
+
context: z.string().optional().describe('Optional: route, user flow, or feature context for the analyzed page.'),
|
|
37
|
+
selector: z.string().optional().describe('Optional CSS selector to scope axe analysis to a subtree (e.g. `#my-form`, `[data-testid="panel"]`). Omit to analyze the whole document.')
|
|
31
38
|
});
|
|
32
39
|
export const listAnalyzeLocalhostA11yTool = {
|
|
33
40
|
name: 'ads_analyze_localhost_a11y',
|
|
34
|
-
description: `
|
|
41
|
+
description: `Loads a **live URL** in a headless browser, runs **axe-core**, and returns violations with follow-up hints (often suggesting \`ads_suggest_a11y_fixes\`). Output is anchored in **axe** rule text; remediation may be generic or ADS-biased depending on the violation.
|
|
42
|
+
|
|
43
|
+
**Availability:** This tool is only registered when the ADS MCP runs **on your machine** (local MCP). It is **not** available in the **remote** MCP offering—use \`ads_analyze_a11y\` on source text there instead.
|
|
44
|
+
|
|
45
|
+
WHEN TO USE:
|
|
46
|
+
You have a running app or storybook page and need automated accessibility results on **rendered** UI—especially local or staging URLs.
|
|
47
|
+
|
|
48
|
+
LIMITATIONS:
|
|
49
|
+
- Does not replace manual testing with assistive technologies or keyboard-only navigation.
|
|
50
|
+
- Requires network access to the URL from the environment running the MCP.`,
|
|
35
51
|
annotations: {
|
|
36
|
-
title: 'Analyze
|
|
52
|
+
title: 'Analyze accessibility (live URL)',
|
|
37
53
|
readOnlyHint: true,
|
|
38
54
|
destructiveHint: false,
|
|
39
55
|
idempotentHint: true,
|
|
@@ -5,13 +5,20 @@ import { zodToJsonSchema } from '../../helpers';
|
|
|
5
5
|
import { accessibilityGuidelines } from './guidelines';
|
|
6
6
|
const topics = Object.keys(accessibilityGuidelines);
|
|
7
7
|
export const getA11yGuidelinesInputSchema = z.object({
|
|
8
|
-
topic: z.string().optional().describe('
|
|
8
|
+
topic: z.string().optional().describe('ADS accessibility topic key. Omit to receive all topics and the full guideline bundle. Pass a valid key (see response \`availableTopics\`) or \`general\` for a focused overview when supported. Known topics: ' + topics.join(', ') + '.')
|
|
9
9
|
});
|
|
10
10
|
export const listGetA11yGuidelinesTool = {
|
|
11
11
|
name: 'ads_get_a11y_guidelines',
|
|
12
|
-
description:
|
|
12
|
+
description: `Returns Atlassian Design System (ADS) accessibility guidance: best practices and patterns for buttons, interactions, color contrast, forms, and other design-system topics shipped in this tool.
|
|
13
|
+
|
|
14
|
+
Use this alongside the Context Engine MCP tool \`get_accessibility_docs\` for Atlassian-wide accessibility standards (e.g. A11YKB); this tool supplies ADS-specific component and pattern guidance.
|
|
15
|
+
|
|
16
|
+
WHEN TO USE:
|
|
17
|
+
You MUST call this when generating or substantially changing a new interactive or visual user interface built with ADS, or when you need topic-specific ADS guidance (e.g. focus, forms, motion).
|
|
18
|
+
|
|
19
|
+
DO NOT rely on generic web accessibility advice alone—ADS conventions may differ. Use \`get_accessibility_docs\` for org-wide standards and this tool for ADS-topic guidance.`,
|
|
13
20
|
annotations: {
|
|
14
|
-
title: 'Get
|
|
21
|
+
title: 'Get ADS accessibility guidelines',
|
|
15
22
|
readOnlyHint: true,
|
|
16
23
|
destructiveHint: false,
|
|
17
24
|
idempotentHint: true,
|
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { zodToJsonSchema } from '../../helpers';
|
|
5
5
|
import { loadAllComponents } from './load-all-components';
|
|
6
|
-
export const
|
|
7
|
-
name: '
|
|
8
|
-
description: `
|
|
6
|
+
export const listGetAllComponentsTool = {
|
|
7
|
+
name: 'ads_get_all_components',
|
|
8
|
+
description: `Returns **every** Atlassian Design System component record as separate JSON text chunks (full catalog; large payload).
|
|
9
|
+
|
|
10
|
+
WHEN TO USE:
|
|
11
|
+
Last resort when \`ads_plan\` / \`ads_search_components\` is insufficient and you must enumerate all components. Prefer search for normal component picking.
|
|
12
|
+
|
|
13
|
+
No parameters.`,
|
|
9
14
|
annotations: {
|
|
10
15
|
title: 'Get all ADS components',
|
|
11
16
|
readOnlyHint: true,
|
|
@@ -15,7 +20,7 @@ export const listGetComponentsTool = {
|
|
|
15
20
|
},
|
|
16
21
|
inputSchema: zodToJsonSchema(z.object({}))
|
|
17
22
|
};
|
|
18
|
-
export const
|
|
23
|
+
export const getAllComponentsTool = async () => {
|
|
19
24
|
return {
|
|
20
25
|
content: loadAllComponents().map(component => ({
|
|
21
26
|
// NOTE: Ideally one day the MCP would support structured content…
|
|
@@ -5,7 +5,12 @@ import { zodToJsonSchema } from '../../helpers';
|
|
|
5
5
|
import { icons } from './icons';
|
|
6
6
|
export const listGetAllIconsTool = {
|
|
7
7
|
name: 'ads_get_all_icons',
|
|
8
|
-
description:
|
|
8
|
+
description: `Returns **every** ADS icon record as separate JSON text chunks (full catalog; large payload).
|
|
9
|
+
|
|
10
|
+
WHEN TO USE:
|
|
11
|
+
Last resort when \`ads_plan\` / \`ads_search_icons\` is insufficient and you must enumerate all icons. Prefer search for normal icon picking.
|
|
12
|
+
|
|
13
|
+
No parameters.`,
|
|
9
14
|
annotations: {
|
|
10
15
|
title: 'Get all ADS icons',
|
|
11
16
|
readOnlyHint: true,
|
|
@@ -6,7 +6,12 @@ import { zodToJsonSchema } from '../../helpers';
|
|
|
6
6
|
const inputSchema = z.object({});
|
|
7
7
|
export const listGetAllTokensTool = {
|
|
8
8
|
name: 'ads_get_all_tokens',
|
|
9
|
-
description:
|
|
9
|
+
description: `Returns **every** ADS design token from bundled metadata (name, example value, usage guidelines)—one JSON object per token, **very large** output.
|
|
10
|
+
|
|
11
|
+
WHEN TO USE:
|
|
12
|
+
Last resort when \`ads_plan\` / \`ads_search_tokens\` cannot answer the question and you need the full list (e.g. exhaustive audit). Prefer targeted search for normal development.
|
|
13
|
+
|
|
14
|
+
No parameters.`,
|
|
10
15
|
annotations: {
|
|
11
16
|
title: 'Get all ADS tokens',
|
|
12
17
|
readOnlyHint: true,
|
|
@@ -5,19 +5,32 @@ import { z } from 'zod';
|
|
|
5
5
|
import { cleanQuery, zodToJsonSchema } from '../../helpers';
|
|
6
6
|
import { guidelinesStructuredContent } from './guidelines-structured-content.codegen';
|
|
7
7
|
export const getGuidelinesInputSchema = z.object({
|
|
8
|
-
terms: z.array(z.string()).default([]).describe('
|
|
9
|
-
limit: z.number().default(1).describe('
|
|
8
|
+
terms: z.array(z.string()).default([]).describe('Search terms matched against guideline keywords and body (fuzzy). Examples: `["empty state", "voice tone"]`, `["color tokens", "spacing"]`, `["elevation", "grid"]`. Omit or use an empty array to return **all** guidelines as Markdown.').optional(),
|
|
9
|
+
limit: z.number().default(1).describe('Max matches **per term** when `terms` is non-empty (default 1). Ignored when returning all guidelines.').optional()
|
|
10
10
|
});
|
|
11
11
|
export const listGetGuidelinesTool = {
|
|
12
12
|
name: 'ads_get_guidelines',
|
|
13
|
-
description: `
|
|
13
|
+
description: `Returns Atlassian Design System (ADS) **foundations** guidelines as Markdown: the bundled design-system-docs foundations set (not component API docs).
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
-
|
|
15
|
+
TOPIC COVERAGE:
|
|
16
|
+
- **Content & UX writing**: messaging types (empty state, error, success, warning, info, feature discovery), voice and tone, inclusive language, grammar and style, date/time copy handoff, vocabulary pointers.
|
|
17
|
+
- **Visual foundations**: color (roles, accents, palette, charts, pickers), borders and radius, elevation and z-index, spacing and layout primitives (box/inline/stack), grid, iconography, logos.
|
|
18
|
+
- **Design tokens**: concepts, themes, migration, using tokens in code and in Figma.
|
|
19
|
+
- **Typography**: typefaces, scale, applying text styles and tokens.
|
|
20
|
+
- **Accessibility overview**: building accessible apps and related foundations pages bundled here.
|
|
17
21
|
|
|
18
|
-
|
|
22
|
+
When working with content, use this tool alongside the Context Engine MCP tool \`get_content_standards_docs\` for Atlassian-wide content standards (CDSTD/BAIT-style org guidance); this tool supplies ADS-specific foundations.
|
|
23
|
+
|
|
24
|
+
WHAT YOU GET:
|
|
25
|
+
- With \`terms\`: fuzzy search over keywords and content; concatenated Markdown for matches.
|
|
26
|
+
- Without \`terms\` (or empty): the full guideline set as Markdown.
|
|
27
|
+
|
|
28
|
+
WHEN TO USE:
|
|
29
|
+
Use this when you are **building or updating a visual interface**, **writing or reviewing user-facing copy**, or need to **answer foundations questions** about ADS: content patterns, visual appearance, design tokens, typography, spacing, color, grid, motion, and related topics shipped in this bundle.
|
|
30
|
+
|
|
31
|
+
It is **not** for picking a component’s props or package (use \`ads_plan\` / \`ads_search_components\`) or for interactive accessibility rules and patterns (use \`ads_get_a11y_guidelines\`, with Context Engine \`get_accessibility_docs\` for org-wide a11y standards).`,
|
|
19
32
|
annotations: {
|
|
20
|
-
title: 'Get ADS guidelines',
|
|
33
|
+
title: 'Get ADS guidelines (content, a11y, visual design, design tokens, typography)',
|
|
21
34
|
readOnlyHint: true,
|
|
22
35
|
destructiveHint: false,
|
|
23
36
|
idempotentHint: true,
|
|
@@ -5,20 +5,24 @@ import { z } from 'zod';
|
|
|
5
5
|
import { cleanQuery, zodToJsonSchema } from '../../helpers';
|
|
6
6
|
import { lintRulesMcpStructuredContent } from './lint-rules-structured-content.codegen';
|
|
7
7
|
export const getLintRulesInputSchema = z.object({
|
|
8
|
-
terms: z.array(z.string()).default([]).describe('
|
|
9
|
-
limit: z.number().default(1).describe('
|
|
10
|
-
exactName: z.boolean().default(false).describe('
|
|
8
|
+
terms: z.array(z.string()).default([]).describe('Search terms matched against rule name, description, and docs body (fuzzy unless \`exactName\` is true). Example: `["icon-label", "xcss", "design token"]`. Omit or empty: return **all** rules as JSON.').optional(),
|
|
9
|
+
limit: z.number().default(1).describe('Max matches **per term** when searching (default 1). Not used when returning all rules.').optional(),
|
|
10
|
+
exactName: z.boolean().default(false).describe('If true, resolve each term by **exact** ESLint rule name (case-insensitive). If false, fuzzy search across name, description, and content.').optional()
|
|
11
11
|
});
|
|
12
12
|
export const listGetLintRulesTool = {
|
|
13
13
|
name: 'ads_get_lint_rules',
|
|
14
|
-
description: `
|
|
14
|
+
description: `Returns documentation for **Constellation** (Atlassian Design System) ESLint rules shipped with this MCP—rule purpose, examples, and fixes where available.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
-
|
|
16
|
+
WHAT YOU GET:
|
|
17
|
+
- No \`terms\`: JSON array of all rule payloads.
|
|
18
|
+
- With \`terms\`: fuzzy search (or exact rule name when \`exactName\` is true); JSON for one or more matching rules.
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
WHEN TO USE:
|
|
21
|
+
Explaining or fixing an ESLint message from ADS rules (e.g. \`icon-label\`, \`ensure-proper-xcss-usage\`, \`no-deprecated-apis\`), or browsing rule docs without opening the repo. Prefer this over guessing from rule id alone.
|
|
22
|
+
|
|
23
|
+
This tool does not run ESLint; it only returns bundled documentation.`,
|
|
20
24
|
annotations: {
|
|
21
|
-
title: 'Get ADS
|
|
25
|
+
title: 'Get ADS ESLint rule docs',
|
|
22
26
|
readOnlyHint: true,
|
|
23
27
|
destructiveHint: false,
|
|
24
28
|
idempotentHint: true,
|
|
@@ -4,25 +4,22 @@ import { z } from 'zod';
|
|
|
4
4
|
import { zodToJsonSchema } from '../../helpers';
|
|
5
5
|
import { i18nConversionGuide } from './guide';
|
|
6
6
|
export const i18nConversionInputSchema = z.object({
|
|
7
|
-
guide: z.enum(['hardcoded-string-to-formatmessage']).describe('
|
|
7
|
+
guide: z.enum(['hardcoded-string-to-formatmessage']).describe('Which bundled guide to return. Currently only `hardcoded-string-to-formatmessage` (JSX literals → `formatMessage` / intl patterns).')
|
|
8
8
|
});
|
|
9
9
|
export const listI18nConversionTool = {
|
|
10
10
|
name: 'ads_i18n_conversion_guide',
|
|
11
|
-
description: `
|
|
11
|
+
description: `Returns a **bundled** step-by-step guide for replacing hardcoded UI strings with \`formatMessage\` (and related patterns) using @atlassian/jira-intl or react-intl-next: message constants, placeholders, descriptions, and scope/limitations for systematic refactors.
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
- "fix hardcoded string" / "fix hardcoded strings" / "fix hardcoded string in [file]"
|
|
15
|
-
- "convert hardcoded string" / "convert to i18n" / "convert to formatMessage"
|
|
16
|
-
- "translate string" / "internationalize string" / "i18n this string"
|
|
17
|
-
- "use formatMessage" / "use FormattedMessage" / "wrap in formatMessage"
|
|
18
|
-
- "literal string" / "fix literal string" / "convert literal string"
|
|
19
|
-
- ESLint errors: "Literal string in JSX content should be internationalized. Use FormattedMessage or intl.formatMessage()"
|
|
20
|
-
- ESLint errors: "@atlassian/i18n/no-literal-string-in-jsx"
|
|
21
|
-
- Requests to convert hardcoded strings to i18n messages
|
|
13
|
+
When working with i18n or hardcoded UI strings, use this tool alongside the Context Engine MCP tool \`get_i18n_docs\` for Atlassian-wide Traduki / i18n standards (message definition, extraction, pluralisation, formatting, workflow); this tool supplies the concrete hardcoded-string → \`formatMessage\` playbook bundled in ADS MCP.
|
|
22
14
|
|
|
23
|
-
|
|
15
|
+
WHEN TO USE / TYPICAL TRIGGERS:
|
|
16
|
+
- Refactoring JSX or TS literals to i18n; "fix hardcoded string(s)", "convert hardcoded string in [file]", "literal string in JSX".
|
|
17
|
+
- "Convert to i18n", "convert to formatMessage", "translate this string", "internationalize this string", "i18n this string".
|
|
18
|
+
- "Use formatMessage", "use FormattedMessage", "wrap in formatMessage", "fix literal string".
|
|
19
|
+
- ESLint: \`Literal string in JSX content should be internationalized. Use FormattedMessage or intl.formatMessage()\`.
|
|
20
|
+
- ESLint: \`@atlassian/i18n/no-literal-string-in-jsx\`.`,
|
|
24
21
|
annotations: {
|
|
25
|
-
title: 'i18n
|
|
22
|
+
title: 'i18n conversion guide',
|
|
26
23
|
readOnlyHint: true,
|
|
27
24
|
destructiveHint: false,
|
|
28
25
|
idempotentHint: true,
|