@atlaskit/ads-mcp 0.18.0 → 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 +16 -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-components/load-all-components.js +10 -0
- 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-components/load-all-components.js +4 -0
- 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-components/load-all-components.js +4 -0
- 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/load-all-components.js +0 -16
- package/dist/es2019/tools/get-components/load-all-components.js +0 -10
- package/dist/esm/tools/get-components/load-all-components.js +0 -10
- /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}/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}/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}/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
|
@@ -8,14 +8,20 @@ import { getAvailableMigrationIds, getAvailableMigrationsDescription, migrationR
|
|
|
8
8
|
const migrationIds = getAvailableMigrationIds();
|
|
9
9
|
const migrationDescriptions = getAvailableMigrationsDescription();
|
|
10
10
|
export const migrationGuidesInputSchema = z.object({
|
|
11
|
-
migration: z.enum(migrationIds).describe(
|
|
12
|
-
description: z.enum(migrationDescriptions).describe(`
|
|
11
|
+
migration: z.enum(migrationIds).describe('Migration id from the registry. Must match the guide you want (see tool description list).'),
|
|
12
|
+
description: z.enum(migrationDescriptions).describe('Human-readable migration label that pairs with `migration` in the schema—choose the entry that matches the selected id.')
|
|
13
13
|
});
|
|
14
14
|
export const listMigrationGuidesTool = {
|
|
15
15
|
name: 'ads_migration_guides',
|
|
16
|
-
description: `
|
|
16
|
+
description: `Returns a structured Atlassian Design System (ADS) **migration guide** for a known package or API migration (before/after examples, best practices, links).
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
WHEN TO USE:
|
|
19
|
+
You are upgrading or refactoring code between ADS packages or APIs and need the official migration pattern for a specific id listed below.
|
|
20
|
+
|
|
21
|
+
Pass **both** \`migration\` and \`description\` using a **matching pair** from the enum (schema enforces valid combinations).
|
|
22
|
+
|
|
23
|
+
Available migrations:
|
|
24
|
+
${getAvailableMigrationsDescription()}`,
|
|
19
25
|
annotations: {
|
|
20
26
|
title: 'ADS Migration Guides',
|
|
21
27
|
readOnlyHint: true,
|
|
@@ -6,17 +6,25 @@ import { searchComponentsTool } from '../search-components';
|
|
|
6
6
|
import { searchIconsTool } from '../search-icons';
|
|
7
7
|
import { searchTokensTool } from '../search-tokens';
|
|
8
8
|
export const planInputSchema = z.object({
|
|
9
|
-
tokens: z.array(z.string()).describe('
|
|
10
|
-
icons: z.array(z.string()).describe('
|
|
11
|
-
components: z.array(z.string()).describe('
|
|
12
|
-
limit: z.number().default(
|
|
13
|
-
exactName: z.boolean().default(false).describe('Search tokens, icons, and components by their exact name match (use when you explicitly know the name and need more details)').optional()
|
|
9
|
+
tokens: z.array(z.string()).describe('Search terms for ADS design tokens (fuzzy by default). Use `[]` if you only need icons or components. Prefer **at least two** terms per non-empty list when you know what you need.'),
|
|
10
|
+
icons: z.array(z.string()).describe('Search terms for ADS icons. Use `[]` if you only need tokens or components. Prefer **at least two** terms per non-empty list when known.'),
|
|
11
|
+
components: z.array(z.string()).describe('Search terms for ADS components. Use `[]` if you only need tokens or icons. Prefer **at least two** terms per non-empty list when known.'),
|
|
12
|
+
limit: z.number().default(2).describe('Max matches **per term** for each non-empty list (default 2). Same limit applies to tokens, icons, and components searches.').optional()
|
|
14
13
|
});
|
|
15
14
|
export const listPlanTool = {
|
|
16
15
|
name: 'ads_plan',
|
|
17
|
-
description: `
|
|
16
|
+
description: `Runs **ads_search_tokens**, **ads_search_icons**, and **ads_search_components** in one call and returns a single JSON payload (each section only if that list was non-empty). Use this as the default way to discover ADS **tokens**, **icons**, and **components** for a UI task.
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
WHEN TO USE:
|
|
19
|
+
**Implementing or iterating on a UI**—new screen, feature, or polish—and you need candidate **token** names, **icon** imports, and **component** packages/props in one pass. Also use when exploring ADS building blocks before you write code.
|
|
20
|
+
|
|
21
|
+
At least one of \`tokens\`, \`icons\`, or \`components\` must contain search terms (use \`[]\` for lists you do not need).
|
|
22
|
+
|
|
23
|
+
Prefer supplying **multiple** terms per non-empty array when you know them—broader queries improve recall. Some queries return no rows where metadata is thin; try alternate wording.
|
|
24
|
+
|
|
25
|
+
This is equivalent to calling the individual search tools; there are no extra merge semantics beyond concatenating results.
|
|
26
|
+
|
|
27
|
+
Example request:
|
|
20
28
|
\`\`\`json
|
|
21
29
|
{
|
|
22
30
|
"tokens": ["spacing", "inverted text", "background primary", "animation"],
|
|
@@ -25,8 +33,6 @@ YOU MUST ALWAYS call this tool with known parameters and include a minimum of 2
|
|
|
25
33
|
}
|
|
26
34
|
\`\`\`
|
|
27
35
|
|
|
28
|
-
Please note, there may not be results for everything as there are minor gaps in offerings or how we describe them.
|
|
29
|
-
|
|
30
36
|
Example token usage:
|
|
31
37
|
\`\`\`tsx
|
|
32
38
|
import { token } from '@atlaskit/tokens';
|
|
@@ -39,7 +45,7 @@ import AddIcon from '@atlaskit/icon/core/add';
|
|
|
39
45
|
<AddIcon label="Add work item" size="small" />
|
|
40
46
|
\`\`\``,
|
|
41
47
|
annotations: {
|
|
42
|
-
title: '
|
|
48
|
+
title: 'Search ADS tokens, icons, and components to plan what to build',
|
|
43
49
|
readOnlyHint: true,
|
|
44
50
|
destructiveHint: false,
|
|
45
51
|
idempotentHint: true,
|
|
@@ -47,15 +53,12 @@ import AddIcon from '@atlaskit/icon/core/add';
|
|
|
47
53
|
},
|
|
48
54
|
inputSchema: zodToJsonSchema(planInputSchema)
|
|
49
55
|
};
|
|
50
|
-
export const planTool = async
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
exactName = false
|
|
57
|
-
} = params;
|
|
58
|
-
|
|
56
|
+
export const planTool = async ({
|
|
57
|
+
tokens: tokens_search,
|
|
58
|
+
icons: icons_search,
|
|
59
|
+
components: components_search,
|
|
60
|
+
limit
|
|
61
|
+
}) => {
|
|
59
62
|
// Validate that at least one search type is provided
|
|
60
63
|
if (!(tokens_search !== null && tokens_search !== void 0 && tokens_search.length) && !(icons_search !== null && icons_search !== void 0 && icons_search.length) && !(components_search !== null && components_search !== void 0 && components_search.length)) {
|
|
61
64
|
return {
|
|
@@ -73,8 +76,7 @@ export const planTool = async params => {
|
|
|
73
76
|
if (tokens_search !== null && tokens_search !== void 0 && tokens_search.length) {
|
|
74
77
|
searchPromises.push(searchTokensTool({
|
|
75
78
|
terms: tokens_search,
|
|
76
|
-
limit
|
|
77
|
-
exactName
|
|
79
|
+
limit
|
|
78
80
|
}).then(result => {
|
|
79
81
|
results.tokens = result;
|
|
80
82
|
}));
|
|
@@ -82,8 +84,7 @@ export const planTool = async params => {
|
|
|
82
84
|
if (icons_search !== null && icons_search !== void 0 && icons_search.length) {
|
|
83
85
|
searchPromises.push(searchIconsTool({
|
|
84
86
|
terms: icons_search,
|
|
85
|
-
limit
|
|
86
|
-
exactName
|
|
87
|
+
limit
|
|
87
88
|
}).then(result => {
|
|
88
89
|
results.icons = result;
|
|
89
90
|
}));
|
|
@@ -91,8 +92,7 @@ export const planTool = async params => {
|
|
|
91
92
|
if (components_search !== null && components_search !== void 0 && components_search.length) {
|
|
92
93
|
searchPromises.push(searchComponentsTool({
|
|
93
94
|
terms: components_search,
|
|
94
|
-
limit
|
|
95
|
-
exactName
|
|
95
|
+
limit
|
|
96
96
|
}).then(result => {
|
|
97
97
|
results.components = result;
|
|
98
98
|
}));
|
|
@@ -2,16 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import Fuse from 'fuse.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { cleanQuery, zodToJsonSchema } from '../../helpers';
|
|
6
|
-
import { loadAllComponents } from '../get-components/load-all-components';
|
|
5
|
+
import { cleanQuery, mergeMultiTermFuseResults, zodToJsonSchema } from '../../helpers';
|
|
6
|
+
import { loadAllComponents } from '../get-all-components/load-all-components';
|
|
7
7
|
export const searchComponentsInputSchema = z.object({
|
|
8
|
-
terms: z.array(z.string()).describe('
|
|
9
|
-
limit: z.number().default(
|
|
10
|
-
exactName: z.boolean().default(false).describe('Enable to explicitly search components by the exact name match (when you know the name, but need more details)').optional()
|
|
8
|
+
terms: z.array(z.string()).describe('Required: one or more search terms (fuzzy over name, package, category, description, keywords, examples). Example: `["button", "modal", "select"]`.'),
|
|
9
|
+
limit: z.number().default(2).describe('Max matches **per term** (default 2).').optional()
|
|
11
10
|
});
|
|
12
11
|
export const listSearchComponentsTool = {
|
|
13
12
|
name: 'ads_search_components',
|
|
14
|
-
description:
|
|
13
|
+
description: `Searches the bundled Atlassian Design System (ADS) component catalog. Returns JSON objects with **name**, **package**, **examples**, and **props** for each match (trimmed payload).
|
|
14
|
+
|
|
15
|
+
WHEN TO USE:
|
|
16
|
+
**Selecting which ADS component to use**—package name, examples, and props—before implementation. Use when composing a new view or swapping a primitive. Prefer \`ads_plan\` when you also need token and icon discovery in one shot.`,
|
|
15
17
|
annotations: {
|
|
16
18
|
title: 'Search ADS components',
|
|
17
19
|
readOnlyHint: true,
|
|
@@ -21,9 +23,7 @@ export const listSearchComponentsTool = {
|
|
|
21
23
|
},
|
|
22
24
|
inputSchema: zodToJsonSchema(searchComponentsInputSchema)
|
|
23
25
|
};
|
|
24
|
-
|
|
25
|
-
// Clean component result to only return name, package name, example, and props
|
|
26
|
-
const cleanComponentResult = result => {
|
|
26
|
+
const buildComponentResult = result => {
|
|
27
27
|
return {
|
|
28
28
|
name: result.name,
|
|
29
29
|
package: result.package,
|
|
@@ -31,43 +31,24 @@ const cleanComponentResult = result => {
|
|
|
31
31
|
props: result.props
|
|
32
32
|
};
|
|
33
33
|
};
|
|
34
|
-
export const searchComponentsTool = async
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
} = params;
|
|
40
|
-
const searchTerms = terms.filter(Boolean).map(cleanQuery);
|
|
34
|
+
export const searchComponentsTool = async ({
|
|
35
|
+
terms,
|
|
36
|
+
limit = 2
|
|
37
|
+
}) => {
|
|
38
|
+
const searchTerms = [...new Set(terms.filter(Boolean).map(cleanQuery))];
|
|
41
39
|
if (!searchTerms.length) {
|
|
42
40
|
return {
|
|
43
|
-
isError: true,
|
|
44
41
|
content: [{
|
|
45
42
|
type: 'text',
|
|
46
|
-
text:
|
|
43
|
+
text: '[]'
|
|
47
44
|
}]
|
|
48
45
|
};
|
|
49
46
|
}
|
|
50
47
|
const components = loadAllComponents();
|
|
51
|
-
if (exactName) {
|
|
52
|
-
// for each search term, search for the exact match
|
|
53
|
-
const exactNameMatches = searchTerms.map(term => {
|
|
54
|
-
return components.find(component => component.name.toLowerCase() === term.toLowerCase());
|
|
55
|
-
}).filter(Boolean);
|
|
56
|
-
if (exactNameMatches.length > 0) {
|
|
57
|
-
return {
|
|
58
|
-
content: [{
|
|
59
|
-
type: 'text',
|
|
60
|
-
text: JSON.stringify(exactNameMatches.map(cleanComponentResult))
|
|
61
|
-
}]
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// use Fuse.js to fuzzy-search through the components
|
|
67
48
|
const fuse = new Fuse(components, {
|
|
68
49
|
keys: [{
|
|
69
50
|
name: 'name',
|
|
70
|
-
weight:
|
|
51
|
+
weight: 5
|
|
71
52
|
}, {
|
|
72
53
|
name: 'package',
|
|
73
54
|
weight: 3
|
|
@@ -77,42 +58,47 @@ export const searchComponentsTool = async params => {
|
|
|
77
58
|
}, {
|
|
78
59
|
name: 'description',
|
|
79
60
|
weight: 2
|
|
61
|
+
}, {
|
|
62
|
+
name: 'keywords',
|
|
63
|
+
weight: 2
|
|
64
|
+
}, {
|
|
65
|
+
name: 'usageGuidelines',
|
|
66
|
+
weight: 2
|
|
67
|
+
}, {
|
|
68
|
+
name: 'contentGuidelines',
|
|
69
|
+
weight: 1
|
|
70
|
+
}, {
|
|
71
|
+
name: 'accessibilityGuidelines',
|
|
72
|
+
weight: 1
|
|
80
73
|
}, {
|
|
81
74
|
name: 'examples',
|
|
82
75
|
weight: 1
|
|
83
76
|
}],
|
|
84
|
-
threshold: 0.4
|
|
77
|
+
threshold: 0.4,
|
|
78
|
+
distance: 80,
|
|
79
|
+
minMatchCharLength: 3,
|
|
80
|
+
ignoreFieldNorm: true,
|
|
81
|
+
includeScore: true
|
|
85
82
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}];
|
|
95
|
-
}
|
|
96
|
-
return fuse.search(term).slice(0, limit);
|
|
97
|
-
}).flat();
|
|
98
|
-
if (!results.length) {
|
|
83
|
+
const matchedItems = mergeMultiTermFuseResults({
|
|
84
|
+
searchTerms,
|
|
85
|
+
limit,
|
|
86
|
+
search: query => fuse.search(query, {
|
|
87
|
+
limit: limit * searchTerms.length
|
|
88
|
+
})
|
|
89
|
+
});
|
|
90
|
+
if (!matchedItems.length) {
|
|
99
91
|
return {
|
|
100
|
-
isError: true,
|
|
101
92
|
content: [{
|
|
102
93
|
type: 'text',
|
|
103
94
|
text: `Error: No components found for '${terms.join(', ')}'. Available components: ${components.map(c => c.name).join(', ')}`
|
|
104
95
|
}]
|
|
105
96
|
};
|
|
106
97
|
}
|
|
107
|
-
|
|
108
|
-
// Remove duplicates based on component name
|
|
109
|
-
const uniqueResults = results.filter((result, index, arr) => {
|
|
110
|
-
return arr.findIndex(r => r.item.name === result.item.name) === index;
|
|
111
|
-
});
|
|
112
98
|
return {
|
|
113
99
|
content: [{
|
|
114
100
|
type: 'text',
|
|
115
|
-
text: JSON.stringify(
|
|
101
|
+
text: JSON.stringify(matchedItems.map(buildComponentResult))
|
|
116
102
|
}]
|
|
117
103
|
};
|
|
118
104
|
};
|
|
@@ -2,18 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
import Fuse from 'fuse.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
-
import { cleanQuery, zodToJsonSchema } from '../../helpers';
|
|
5
|
+
import { cleanQuery, mergeMultiTermFuseResults, zodToJsonSchema } from '../../helpers';
|
|
6
6
|
import { icons } from '../get-all-icons/icons';
|
|
7
7
|
export const searchIconsInputSchema = z.object({
|
|
8
|
-
terms: z.array(z.string()).describe('
|
|
9
|
-
limit: z.number().default(
|
|
10
|
-
|
|
8
|
+
terms: z.array(z.string()).describe('Required: one or more terms; fuzzy match on icon **componentName**, **iconName**, **keywords**, **categorization**, **type**, and **usage**. Example: `["search", "folder", "user"]`.'),
|
|
9
|
+
limit: z.number().default(2).describe('Max matches **per term** (default 2).').optional()
|
|
10
|
+
});
|
|
11
|
+
const buildIconResult = icon => ({
|
|
12
|
+
componentName: icon.componentName,
|
|
13
|
+
package: icon.package,
|
|
14
|
+
usage: icon.usage
|
|
11
15
|
});
|
|
12
16
|
export const listSearchIconsTool = {
|
|
13
17
|
name: 'ads_search_icons',
|
|
14
|
-
description: `
|
|
18
|
+
description: `Searches the bundled Atlassian Design System **icon** catalog. Returns JSON with **componentName**, **package**, and **usage** for each match.
|
|
19
|
+
|
|
20
|
+
WHEN TO USE:
|
|
21
|
+
**Choosing an icon** for a control, nav item, empty state, or illustration—find \`@atlaskit/icon\` import paths and usage notes. Prefer \`ads_plan\` when you also need tokens and components together.
|
|
15
22
|
|
|
16
|
-
Example
|
|
23
|
+
Example:
|
|
17
24
|
\`\`\`tsx
|
|
18
25
|
import AddIcon from '@atlaskit/icon/core/add';
|
|
19
26
|
<AddIcon label="Add work item" size="small" />
|
|
@@ -27,42 +34,23 @@ import AddIcon from '@atlaskit/icon/core/add';
|
|
|
27
34
|
},
|
|
28
35
|
inputSchema: zodToJsonSchema(searchIconsInputSchema)
|
|
29
36
|
};
|
|
30
|
-
export const searchIconsTool = async
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
} = params;
|
|
36
|
-
const searchTerms = terms.filter(Boolean).map(cleanQuery);
|
|
37
|
+
export const searchIconsTool = async ({
|
|
38
|
+
terms,
|
|
39
|
+
limit = 2
|
|
40
|
+
}) => {
|
|
41
|
+
const searchTerms = [...new Set(terms.filter(Boolean).map(cleanQuery))];
|
|
37
42
|
if (!searchTerms.length) {
|
|
38
43
|
return {
|
|
39
|
-
isError: true,
|
|
40
44
|
content: [{
|
|
41
45
|
type: 'text',
|
|
42
|
-
text:
|
|
46
|
+
text: '[]'
|
|
43
47
|
}]
|
|
44
48
|
};
|
|
45
49
|
}
|
|
46
|
-
if (exactName) {
|
|
47
|
-
// for each search term, search for the exact match
|
|
48
|
-
const exactNameMatches = searchTerms.map(term => {
|
|
49
|
-
return icons.find(icon => icon.componentName.toLowerCase() === term.toLowerCase());
|
|
50
|
-
}).filter(Boolean);
|
|
51
|
-
if (exactNameMatches.length > 0) {
|
|
52
|
-
return {
|
|
53
|
-
content: [{
|
|
54
|
-
type: 'text',
|
|
55
|
-
text: JSON.stringify(exactNameMatches)
|
|
56
|
-
}]
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// use Fuse.js to fuzzy-search through the icons
|
|
62
50
|
const fuse = new Fuse(icons, {
|
|
63
51
|
keys: [{
|
|
64
52
|
name: 'componentName',
|
|
65
|
-
weight:
|
|
53
|
+
weight: 5
|
|
66
54
|
}, {
|
|
67
55
|
name: 'iconName',
|
|
68
56
|
weight: 3
|
|
@@ -71,53 +59,40 @@ export const searchIconsTool = async params => {
|
|
|
71
59
|
weight: 2
|
|
72
60
|
}, {
|
|
73
61
|
name: 'categorization',
|
|
74
|
-
weight:
|
|
62
|
+
weight: 2
|
|
75
63
|
}, {
|
|
76
64
|
name: 'type',
|
|
77
65
|
weight: 1
|
|
78
66
|
}, {
|
|
79
67
|
name: 'usage',
|
|
80
|
-
weight:
|
|
68
|
+
weight: 2
|
|
81
69
|
}],
|
|
82
|
-
threshold: 0.4
|
|
70
|
+
threshold: 0.4,
|
|
71
|
+
distance: 80,
|
|
72
|
+
minMatchCharLength: 3,
|
|
73
|
+
ignoreFieldNorm: true,
|
|
74
|
+
includeScore: true
|
|
83
75
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
}
|
|
94
|
-
return fuse.search(term).slice(0, limit);
|
|
95
|
-
}).flat();
|
|
96
|
-
if (!results.length) {
|
|
76
|
+
const matchedItems = mergeMultiTermFuseResults({
|
|
77
|
+
searchTerms,
|
|
78
|
+
limit,
|
|
79
|
+
search: query => fuse.search(query, {
|
|
80
|
+
limit: limit * searchTerms.length
|
|
81
|
+
}),
|
|
82
|
+
tokenKey: icon => icon.componentName
|
|
83
|
+
});
|
|
84
|
+
if (!matchedItems.length) {
|
|
97
85
|
return {
|
|
98
|
-
isError: true,
|
|
99
86
|
content: [{
|
|
100
87
|
type: 'text',
|
|
101
88
|
text: `Error: No icons found for '${terms.join(', ')}'. Available icons: ${icons.map(i => i.componentName).join(', ')}`
|
|
102
89
|
}]
|
|
103
90
|
};
|
|
104
91
|
}
|
|
105
|
-
|
|
106
|
-
// Remove duplicates based on componentName
|
|
107
|
-
const uniqueResults = results.filter((result, index, arr) => {
|
|
108
|
-
return arr.findIndex(r => r.item.componentName === result.item.componentName) === index;
|
|
109
|
-
});
|
|
110
|
-
const matchedIcons = uniqueResults.map(result => {
|
|
111
|
-
return {
|
|
112
|
-
componentName: result.item.componentName,
|
|
113
|
-
package: result.item.package,
|
|
114
|
-
usage: result.item.usage
|
|
115
|
-
};
|
|
116
|
-
});
|
|
117
92
|
return {
|
|
118
93
|
content: [{
|
|
119
94
|
type: 'text',
|
|
120
|
-
text: JSON.stringify(
|
|
95
|
+
text: JSON.stringify(matchedItems.map(buildIconResult))
|
|
121
96
|
}]
|
|
122
97
|
};
|
|
123
98
|
};
|
|
@@ -3,17 +3,19 @@
|
|
|
3
3
|
import Fuse from 'fuse.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { tokens } from '@atlaskit/tokens/token-metadata';
|
|
6
|
-
import { cleanQuery, zodToJsonSchema } from '../../helpers';
|
|
6
|
+
import { cleanQuery, mergeMultiTermFuseResults, zodToJsonSchema } from '../../helpers';
|
|
7
7
|
export const searchTokensInputSchema = z.object({
|
|
8
|
-
terms: z.array(z.string()).describe('
|
|
9
|
-
limit: z.number().default(
|
|
10
|
-
exactName: z.boolean().default(false).describe('Enable to explicitly search tokens by the exact name match (when you know the name, but need more details)').optional()
|
|
8
|
+
terms: z.array(z.string()).describe('Required: one or more terms; fuzzy match on token **name**, **description**, **exampleValue**, **usageGuidelines.usage**, and **usageGuidelines.cssProperties**. Example: `["spacing", "color.text", "background"]`.'),
|
|
9
|
+
limit: z.number().default(2).describe('Max matches **per term** (default 2).').optional()
|
|
11
10
|
});
|
|
12
11
|
export const listSearchTokensTool = {
|
|
13
12
|
name: 'ads_search_tokens',
|
|
14
|
-
description: `
|
|
13
|
+
description: `Searches Atlassian Design System **design tokens** from bundled metadata. Returns JSON objects with **name** and **exampleValue** for each match (search also considers description, usage guidelines, and CSS property hints in metadata).
|
|
15
14
|
|
|
16
|
-
|
|
15
|
+
WHEN TO USE:
|
|
16
|
+
**Styling or theming in code**—you need the right \`token('…')\` names for colors, space, typography, etc. Use during layout and visual work when tokens must match ADS. Prefer \`ads_plan\` when you also need icons and components in the same step.
|
|
17
|
+
|
|
18
|
+
Example:
|
|
17
19
|
\`\`\`tsx
|
|
18
20
|
import { token } from '@atlaskit/tokens';
|
|
19
21
|
const styles = css({ color: token('color.text'), padding: token('space.100') });
|
|
@@ -27,59 +29,66 @@ const styles = css({ color: token('color.text'), padding: token('space.100') });
|
|
|
27
29
|
},
|
|
28
30
|
inputSchema: zodToJsonSchema(searchTokensInputSchema)
|
|
29
31
|
};
|
|
30
|
-
export const searchTokensTool = async
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
content: [{
|
|
45
|
-
type: 'text',
|
|
46
|
-
text: JSON.stringify(exactNameMatches.map(token => ({
|
|
47
|
-
name: token.name,
|
|
48
|
-
exampleValue: token.exampleValue
|
|
49
|
-
})))
|
|
50
|
-
}]
|
|
51
|
-
};
|
|
52
|
-
}
|
|
32
|
+
export const searchTokensTool = async ({
|
|
33
|
+
terms,
|
|
34
|
+
limit = 2
|
|
35
|
+
}) => {
|
|
36
|
+
// Unique cleaned terms (order preserved) so duplicates don't concatenate into a bogus query.
|
|
37
|
+
const searchTerms = [...new Set(terms.filter(Boolean).map(cleanQuery))];
|
|
38
|
+
if (!searchTerms.length) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{
|
|
41
|
+
type: 'text',
|
|
42
|
+
text: '[]'
|
|
43
|
+
}]
|
|
44
|
+
};
|
|
53
45
|
}
|
|
54
|
-
|
|
55
|
-
// use Fuse.js to fuzzy-search for the tokens
|
|
56
46
|
const fuse = new Fuse(tokens, {
|
|
57
47
|
keys: [{
|
|
58
48
|
name: 'name',
|
|
59
|
-
weight:
|
|
49
|
+
weight: 5
|
|
50
|
+
}, {
|
|
51
|
+
name: 'path',
|
|
52
|
+
weight: 2
|
|
60
53
|
}, {
|
|
61
54
|
name: 'description',
|
|
62
55
|
weight: 2
|
|
56
|
+
}, {
|
|
57
|
+
name: 'usageGuidelines.usage',
|
|
58
|
+
weight: 2
|
|
59
|
+
}, {
|
|
60
|
+
name: 'usageGuidelines.cssProperties',
|
|
61
|
+
weight: 3
|
|
63
62
|
}, {
|
|
64
63
|
name: 'exampleValue',
|
|
65
|
-
weight:
|
|
64
|
+
weight: 0.5
|
|
66
65
|
}],
|
|
67
|
-
threshold: 0.4
|
|
66
|
+
threshold: 0.4,
|
|
67
|
+
distance: 80,
|
|
68
|
+
minMatchCharLength: 3,
|
|
69
|
+
ignoreFieldNorm: true,
|
|
70
|
+
includeScore: true
|
|
68
71
|
});
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
const matchedItems = mergeMultiTermFuseResults({
|
|
73
|
+
searchTerms,
|
|
74
|
+
limit,
|
|
75
|
+
search: query => fuse.search(query, {
|
|
76
|
+
limit: limit * searchTerms.length
|
|
77
|
+
}),
|
|
78
|
+
searchTermsJoin: '.'
|
|
76
79
|
});
|
|
77
|
-
const matchedTokens =
|
|
80
|
+
const matchedTokens = matchedItems.map(item => ({
|
|
81
|
+
name: item.name,
|
|
82
|
+
exampleValue: item.exampleValue
|
|
83
|
+
}));
|
|
84
|
+
if (!matchedTokens.length) {
|
|
78
85
|
return {
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
content: [{
|
|
87
|
+
type: 'text',
|
|
88
|
+
text: `Error: No tokens found for '${terms.join(', ')}'. Available tokens: ${tokens.map(t => t.name).join(', ')}`
|
|
89
|
+
}]
|
|
81
90
|
};
|
|
82
|
-
}
|
|
91
|
+
}
|
|
83
92
|
return {
|
|
84
93
|
content: [{
|
|
85
94
|
type: 'text',
|
|
@@ -5,16 +5,25 @@ import { zodToJsonSchema } from '../../helpers';
|
|
|
5
5
|
import { accessibilityFixes } from './fixes';
|
|
6
6
|
import { violationKeywords } from './keywords';
|
|
7
7
|
export const suggestA11yFixesInputSchema = z.object({
|
|
8
|
-
violation: z.string().describe('
|
|
9
|
-
code: z.string().describe('
|
|
10
|
-
component: z.string().optional().describe('
|
|
11
|
-
context: z.string().optional().describe('
|
|
8
|
+
violation: 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.'),
|
|
9
|
+
code: z.string().describe('Snippet of the problematic code or markup so the response can be tailored (may be shown in the output for traceability).'),
|
|
10
|
+
component: z.string().optional().describe('Optional: React component name involved (e.g. `Button`, `TextField`)—may be ADS or app-specific.'),
|
|
11
|
+
context: z.string().optional().describe('Optional: where this appears (e.g. modal, table row, page section) or constraints.')
|
|
12
12
|
});
|
|
13
13
|
export const listSuggestA11yFixesTool = {
|
|
14
14
|
name: 'ads_suggest_a11y_fixes',
|
|
15
|
-
description: `Suggests
|
|
15
|
+
description: `Suggests remediation steps for an accessibility issue described in natural language (often pasted from **axe-core**, ESLint, or review).
|
|
16
|
+
|
|
17
|
+
WHAT YOU GET (varies by match):
|
|
18
|
+
- **Curated hit:** ADS-biased examples and patterns from this server’s recipe map (components, tokens, common fixes).
|
|
19
|
+
- **No strong match:** Generic guidance (e.g. “use ADS components”, labeling, testing)—still useful, but **not** guaranteed to be ADS-specific. May reference axe/atlassian.design resources.
|
|
20
|
+
|
|
21
|
+
WHEN TO USE:
|
|
22
|
+
After \`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).
|
|
23
|
+
|
|
24
|
+
Does not replace manual testing with assistive technologies or keyboard-only navigation.`,
|
|
16
25
|
annotations: {
|
|
17
|
-
title: 'Suggest
|
|
26
|
+
title: 'Suggest accessibility fixes',
|
|
18
27
|
readOnlyHint: true,
|
|
19
28
|
destructiveHint: false,
|
|
20
29
|
idempotentHint: true,
|
|
@@ -126,7 +135,7 @@ export const suggestA11yFixesTool = async params => {
|
|
|
126
135
|
availableFixTypes: Object.keys(accessibilityFixes),
|
|
127
136
|
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.)'],
|
|
128
137
|
additionalResources: ['https://atlassian.design/llms-a11y.txt - Complete ADS accessibility documentation', 'https://atlassian.design/foundations/accessibility - ADS accessibility foundation'],
|
|
129
|
-
recommendation: 'Try the
|
|
138
|
+
recommendation: 'Try the ads_get_a11y_guidelines tool for component-specific guidance'
|
|
130
139
|
}, null, 2)
|
|
131
140
|
}]
|
|
132
141
|
};
|