@triptease/design-system-mcp 1.0.0 → 1.0.2
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 +35 -41
- package/dist/package.json +3 -3
- package/dist/src/index.js +40 -14
- package/dist/src/index.js.map +1 -1
- package/dist/src/manifests/components/entries/barChart.js +3 -3
- package/dist/src/manifests/components/entries/barChart.js.map +1 -1
- package/dist/src/manifests/components/entries/card.d.ts +7 -2
- package/dist/src/manifests/components/entries/card.js +10 -2
- package/dist/src/manifests/components/entries/card.js.map +1 -1
- package/dist/src/manifests/components/entries/combobox.js +1 -1
- package/dist/src/manifests/components/entries/combobox.js.map +1 -1
- package/dist/src/manifests/components/entries/datePicker.js +1 -1
- package/dist/src/manifests/components/entries/datePicker.js.map +1 -1
- package/dist/src/manifests/components/entries/dateRangePicker.js +1 -1
- package/dist/src/manifests/components/entries/dateRangePicker.js.map +1 -1
- package/dist/src/manifests/components/entries/dialog.js +1 -1
- package/dist/src/manifests/components/entries/dialog.js.map +1 -1
- package/dist/src/manifests/components/entries/lineChart.js +1 -1
- package/dist/src/manifests/components/entries/lineChart.js.map +1 -1
- package/dist/src/resources/components/get.d.ts +7 -0
- package/dist/src/resources/components/get.js +29 -0
- package/dist/src/resources/components/get.js.map +1 -0
- package/dist/src/resources/components/index.d.ts +2 -0
- package/dist/src/resources/components/index.js +3 -0
- package/dist/src/resources/components/index.js.map +1 -0
- package/dist/src/resources/components/list.d.ts +7 -0
- package/dist/src/resources/components/list.js +19 -0
- package/dist/src/resources/components/list.js.map +1 -0
- package/dist/src/resources/guides/index.d.ts +2 -0
- package/dist/src/resources/guides/index.js +3 -0
- package/dist/src/resources/guides/index.js.map +1 -0
- package/dist/src/resources/guides/principles.d.ts +60 -0
- package/dist/src/resources/guides/principles.js +158 -0
- package/dist/src/resources/guides/principles.js.map +1 -0
- package/dist/src/resources/guides/setup.d.ts +7 -0
- package/dist/src/resources/guides/setup.js +54 -0
- package/dist/src/resources/guides/setup.js.map +1 -0
- package/dist/src/resources/index.d.ts +3 -0
- package/dist/src/resources/index.js +4 -0
- package/dist/src/resources/index.js.map +1 -0
- package/dist/src/resources/tokens/get.d.ts +7 -0
- package/dist/src/resources/tokens/get.js +30 -0
- package/dist/src/resources/tokens/get.js.map +1 -0
- package/dist/src/resources/tokens/index.d.ts +2 -0
- package/dist/src/resources/tokens/index.js +3 -0
- package/dist/src/resources/tokens/index.js.map +1 -0
- package/dist/src/resources/tokens/list.d.ts +7 -0
- package/dist/src/resources/tokens/list.js +21 -0
- package/dist/src/resources/tokens/list.js.map +1 -0
- package/dist/src/utils/buildCDNUrls.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +94 -14
- package/src/manifests/components/entries/barChart.ts +3 -3
- package/src/manifests/components/entries/card.ts +10 -2
- package/src/manifests/components/entries/combobox.ts +1 -1
- package/src/manifests/components/entries/datePicker.ts +1 -1
- package/src/manifests/components/entries/dateRangePicker.ts +1 -1
- package/src/manifests/components/entries/dialog.ts +1 -1
- package/src/manifests/components/entries/lineChart.ts +1 -1
- package/src/resources/components/get.test.ts +39 -0
- package/src/resources/components/get.ts +35 -0
- package/src/resources/components/index.ts +2 -0
- package/src/resources/components/list.test.ts +40 -0
- package/src/resources/components/list.ts +20 -0
- package/src/resources/guides/index.ts +2 -0
- package/src/resources/guides/principles.ts +160 -0
- package/src/resources/guides/setup.test.ts +72 -0
- package/src/resources/guides/setup.ts +66 -0
- package/src/resources/index.ts +3 -0
- package/src/resources/tokens/get.test.ts +41 -0
- package/src/resources/tokens/get.ts +36 -0
- package/src/resources/tokens/index.ts +2 -0
- package/src/resources/tokens/list.test.ts +42 -0
- package/src/resources/tokens/list.ts +31 -0
- package/src/utils/buildCDNUrls.ts +1 -1
- package/dist/src/tools/searchComponents/handler.d.ts +0 -6
- package/dist/src/tools/searchComponents/handler.js +0 -29
- package/dist/src/tools/searchComponents/handler.js.map +0 -1
- package/dist/src/tools/searchComponents/index.d.ts +0 -12
- package/dist/src/tools/searchComponents/index.js +0 -14
- package/dist/src/tools/searchComponents/index.js.map +0 -1
- package/src/tools/searchComponents/__snapshots__/handler.test.ts.snap +0 -23
- package/src/tools/searchComponents/handler.test.ts +0 -14
- package/src/tools/searchComponents/handler.ts +0 -36
- package/src/tools/searchComponents/index.ts +0 -15
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { setupGuides } from '@/tools/getSetupGuide/setupGuides.js';
|
|
2
|
+
|
|
3
|
+
export const getSetupGuide = async (type?: string) => {
|
|
4
|
+
// Return both guides if no type specified
|
|
5
|
+
if (!type) {
|
|
6
|
+
const allGuides = Object.entries(setupGuides).map(([key, guide]) => ({
|
|
7
|
+
type: key,
|
|
8
|
+
name: guide.name,
|
|
9
|
+
description: guide.description,
|
|
10
|
+
guide,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
contents: [
|
|
15
|
+
{
|
|
16
|
+
uri: 'designsystem://guides/setup',
|
|
17
|
+
mimeType: 'application/json',
|
|
18
|
+
text: JSON.stringify(
|
|
19
|
+
{
|
|
20
|
+
message: 'Multiple setup options available. Choose based on user preference or project requirements.',
|
|
21
|
+
options: allGuides,
|
|
22
|
+
},
|
|
23
|
+
null,
|
|
24
|
+
2
|
|
25
|
+
),
|
|
26
|
+
},
|
|
27
|
+
],
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const guideType = type.toLowerCase();
|
|
32
|
+
const guide = setupGuides[guideType];
|
|
33
|
+
|
|
34
|
+
if (!guide) {
|
|
35
|
+
return {
|
|
36
|
+
contents: [
|
|
37
|
+
{
|
|
38
|
+
uri: `designsystem://guides/setup/${type}`,
|
|
39
|
+
mimeType: 'application/json',
|
|
40
|
+
text: JSON.stringify(
|
|
41
|
+
{
|
|
42
|
+
error: `Setup guide '${guideType}' not found`,
|
|
43
|
+
available: Object.keys(setupGuides).map((key) => ({
|
|
44
|
+
key,
|
|
45
|
+
name: setupGuides[key].name,
|
|
46
|
+
description: setupGuides[key].description,
|
|
47
|
+
})),
|
|
48
|
+
},
|
|
49
|
+
null,
|
|
50
|
+
2
|
|
51
|
+
),
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
contents: [
|
|
59
|
+
{
|
|
60
|
+
uri: `designsystem://guides/setup/${type}`,
|
|
61
|
+
mimeType: 'application/json',
|
|
62
|
+
text: JSON.stringify(guide, null, 2),
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { getCSSTokens } from './get.js';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
describe('getCSSTokens resource', () => {
|
|
5
|
+
it('should return error for invalid category', async () => {
|
|
6
|
+
const result = await getCSSTokens('invalid');
|
|
7
|
+
const data = JSON.parse(result.contents[0].text);
|
|
8
|
+
|
|
9
|
+
expect(data.error).toBe("Invalid category 'invalid'");
|
|
10
|
+
expect(data.available).toBeDefined();
|
|
11
|
+
expect(Array.isArray(data.available)).toBe(true);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should return tokens array for valid category', async () => {
|
|
15
|
+
const result = await getCSSTokens('color');
|
|
16
|
+
const data = JSON.parse(result.contents[0].text);
|
|
17
|
+
|
|
18
|
+
expect(Array.isArray(data)).toBe(true);
|
|
19
|
+
expect(data.length).toBeGreaterThan(0);
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should return tokens with token and value properties', async () => {
|
|
23
|
+
const result = await getCSSTokens('color');
|
|
24
|
+
const data = JSON.parse(result.contents[0].text);
|
|
25
|
+
const firstToken = data[0];
|
|
26
|
+
|
|
27
|
+
expect(firstToken).toHaveProperty('token');
|
|
28
|
+
expect(firstToken).toHaveProperty('value');
|
|
29
|
+
expect(typeof firstToken.token).toBe('string');
|
|
30
|
+
expect(typeof firstToken.value).toBe('string');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it('should return contents with correct URI and mimeType', async () => {
|
|
34
|
+
const result = await getCSSTokens('color');
|
|
35
|
+
|
|
36
|
+
expect(result.contents).toBeDefined();
|
|
37
|
+
expect(result.contents).toHaveLength(1);
|
|
38
|
+
expect(result.contents[0].uri).toBe('designsystem://tokens/color');
|
|
39
|
+
expect(result.contents[0].mimeType).toBe('application/json');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import designTokens from '@triptease/stylesheet/tokens' with { type: 'json' };
|
|
2
|
+
import { buildTokens } from '@/tools/getCSSTokens/utils.js';
|
|
3
|
+
|
|
4
|
+
export const getCSSTokens = async (category: string) => {
|
|
5
|
+
const tokens = buildTokens(designTokens);
|
|
6
|
+
const categories = Object.keys(tokens);
|
|
7
|
+
|
|
8
|
+
if (!categories.includes(category)) {
|
|
9
|
+
return {
|
|
10
|
+
contents: [
|
|
11
|
+
{
|
|
12
|
+
uri: `designsystem://tokens/${category}`,
|
|
13
|
+
mimeType: 'application/json',
|
|
14
|
+
text: JSON.stringify(
|
|
15
|
+
{
|
|
16
|
+
error: `Invalid category '${category}'`,
|
|
17
|
+
available: categories,
|
|
18
|
+
},
|
|
19
|
+
null,
|
|
20
|
+
2
|
|
21
|
+
),
|
|
22
|
+
},
|
|
23
|
+
],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
contents: [
|
|
29
|
+
{
|
|
30
|
+
uri: `designsystem://tokens/${category}`,
|
|
31
|
+
mimeType: 'application/json',
|
|
32
|
+
text: JSON.stringify(tokens[category], null, 2),
|
|
33
|
+
},
|
|
34
|
+
],
|
|
35
|
+
};
|
|
36
|
+
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { listCSSTokens } from './list.js';
|
|
2
|
+
import { describe, expect, it } from 'vitest';
|
|
3
|
+
|
|
4
|
+
describe('listCSSTokens resource', () => {
|
|
5
|
+
it('should return contents with correct URI and mimeType', async () => {
|
|
6
|
+
const result = await listCSSTokens();
|
|
7
|
+
|
|
8
|
+
expect(result.contents).toBeDefined();
|
|
9
|
+
expect(result.contents).toHaveLength(1);
|
|
10
|
+
expect(result.contents[0].uri).toBe('designsystem://tokens');
|
|
11
|
+
expect(result.contents[0].mimeType).toBe('application/json');
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it('should return token categories as an object', async () => {
|
|
15
|
+
const result = await listCSSTokens();
|
|
16
|
+
const data = JSON.parse(result.contents[0].text);
|
|
17
|
+
|
|
18
|
+
expect(typeof data).toBe('object');
|
|
19
|
+
expect(data).not.toBeNull();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('should include count property for each category', async () => {
|
|
23
|
+
const result = await listCSSTokens();
|
|
24
|
+
const data = JSON.parse(result.contents[0].text);
|
|
25
|
+
const categories = Object.keys(data);
|
|
26
|
+
|
|
27
|
+
expect(categories.length).toBeGreaterThan(0);
|
|
28
|
+
categories.forEach((category) => {
|
|
29
|
+
expect(data[category]).toHaveProperty('count');
|
|
30
|
+
expect(typeof data[category].count).toBe('number');
|
|
31
|
+
expect(data[category].count).toBeGreaterThan(0);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('should include color category', async () => {
|
|
36
|
+
const result = await listCSSTokens();
|
|
37
|
+
const data = JSON.parse(result.contents[0].text);
|
|
38
|
+
|
|
39
|
+
expect(data).toHaveProperty('color');
|
|
40
|
+
expect(data.color.count).toBeGreaterThan(0);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import designTokens from '@triptease/stylesheet/tokens' with { type: 'json' };
|
|
2
|
+
import { buildTokens } from '@/tools/getCSSTokens/utils.js';
|
|
3
|
+
|
|
4
|
+
interface Summary {
|
|
5
|
+
count: number;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface SummaryMap {
|
|
9
|
+
[category: string]: Summary;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const listCSSTokens = async () => {
|
|
13
|
+
const tokens = buildTokens(designTokens);
|
|
14
|
+
const categories = Object.keys(tokens);
|
|
15
|
+
const result: SummaryMap = {};
|
|
16
|
+
|
|
17
|
+
for (const category of categories) {
|
|
18
|
+
const tokenCount = tokens[category].length;
|
|
19
|
+
result[category] = { count: tokenCount };
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
contents: [
|
|
24
|
+
{
|
|
25
|
+
uri: 'designsystem://tokens',
|
|
26
|
+
mimeType: 'application/json',
|
|
27
|
+
text: JSON.stringify(result, null, 2),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
};
|
|
31
|
+
};
|
|
@@ -2,6 +2,6 @@ const buildCDNUrl = (componentName: string, version: string) => {
|
|
|
2
2
|
return `https://cdn.design-system.triptease.io/${componentName}/${version}/${componentName}.js`;
|
|
3
3
|
};
|
|
4
4
|
|
|
5
|
-
const buildMajorVersion = (version: string) => `${version.split('.')[0]}.x.x
|
|
5
|
+
const buildMajorVersion = (version: string) => `${version.split('.')[0]}.x.x`;
|
|
6
6
|
|
|
7
7
|
export { buildCDNUrl, buildMajorVersion };
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { componentManifest } from '../../manifests/components/index.js';
|
|
2
|
-
export default (args) => {
|
|
3
|
-
const query = args.query.toLowerCase();
|
|
4
|
-
const results = [];
|
|
5
|
-
for (const [key, comp] of Object.entries(componentManifest)) {
|
|
6
|
-
const searchText = `${key} ${comp.name} ${comp.description}`.toLowerCase();
|
|
7
|
-
if (searchText.includes(query)) {
|
|
8
|
-
results.push({
|
|
9
|
-
key,
|
|
10
|
-
name: comp.name,
|
|
11
|
-
description: comp.description,
|
|
12
|
-
element: comp.element,
|
|
13
|
-
});
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return {
|
|
17
|
-
content: [
|
|
18
|
-
{
|
|
19
|
-
type: 'text',
|
|
20
|
-
text: JSON.stringify({
|
|
21
|
-
query,
|
|
22
|
-
count: results.length,
|
|
23
|
-
results,
|
|
24
|
-
}),
|
|
25
|
-
},
|
|
26
|
-
],
|
|
27
|
-
};
|
|
28
|
-
};
|
|
29
|
-
//# sourceMappingURL=handler.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../../../src/tools/searchComponents/handler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AAMpE,eAAe,CAAC,IAA0B,EAAkB,EAAE;IAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;IACvC,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,iBAAiB,CAAC,EAAE,CAAC;QAC5D,MAAM,UAAU,GAAG,GAAG,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;QAC3E,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC;gBACX,GAAG;gBACH,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,WAAW,EAAE,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;aACtB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE;YACP;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK;oBACL,KAAK,EAAE,OAAO,CAAC,MAAM;oBACrB,OAAO;iBACR,CAAC;aACH;SACF;KACF,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport { componentManifest } from '@/manifests/components/index.js';\n\nexport interface SearchComponentsArgs {\n query: string;\n}\n\nexport default (args: SearchComponentsArgs): CallToolResult => {\n const query = args.query.toLowerCase();\n const results = [];\n\n for (const [key, comp] of Object.entries(componentManifest)) {\n const searchText = `${key} ${comp.name} ${comp.description}`.toLowerCase();\n if (searchText.includes(query)) {\n results.push({\n key,\n name: comp.name,\n description: comp.description,\n element: comp.element,\n });\n }\n }\n\n return {\n content: [\n {\n type: 'text',\n text: JSON.stringify({\n query,\n count: results.length,\n results,\n }),\n },\n ],\n };\n};\n"]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
declare const toolDefinition: {
|
|
3
|
-
name: string;
|
|
4
|
-
config: {
|
|
5
|
-
description: string;
|
|
6
|
-
inputSchema: {
|
|
7
|
-
query: z.ZodString;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
handler: (args: import("./handler.js").SearchComponentsArgs) => import("@modelcontextprotocol/sdk/types.js").CallToolResult;
|
|
11
|
-
};
|
|
12
|
-
export default toolDefinition;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import handler from './handler.js';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
const toolDefinition = {
|
|
4
|
-
name: 'search_components',
|
|
5
|
-
config: {
|
|
6
|
-
description: 'Search for componentManifest by keyword or usage',
|
|
7
|
-
inputSchema: {
|
|
8
|
-
query: z.string().describe('Search query'),
|
|
9
|
-
},
|
|
10
|
-
},
|
|
11
|
-
handler,
|
|
12
|
-
};
|
|
13
|
-
export default toolDefinition;
|
|
14
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/tools/searchComponents/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,cAAc,GAAG;IACrB,IAAI,EAAE,mBAAmB;IACzB,MAAM,EAAE;QACN,WAAW,EAAE,kDAAkD;QAC/D,WAAW,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,cAAc,CAAC;SAC3C;KACF;IACD,OAAO;CACR,CAAC;AAEF,eAAe,cAAc,CAAC","sourcesContent":["import handler from './handler.js';\nimport { z } from 'zod';\n\nconst toolDefinition = {\n name: 'search_components',\n config: {\n description: 'Search for componentManifest by keyword or usage',\n inputSchema: {\n query: z.string().describe('Search query'),\n },\n },\n handler,\n};\n\nexport default toolDefinition;\n"]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
-
|
|
3
|
-
exports[`searchComponents tool > should return an empty response if no components match the query 1`] = `
|
|
4
|
-
{
|
|
5
|
-
"content": [
|
|
6
|
-
{
|
|
7
|
-
"text": "{"query":"doctorwhoisthebestshowintheworld","count":0,"results":[]}",
|
|
8
|
-
"type": "text",
|
|
9
|
-
},
|
|
10
|
-
],
|
|
11
|
-
}
|
|
12
|
-
`;
|
|
13
|
-
|
|
14
|
-
exports[`searchComponents tool > should search for components by keyword 1`] = `
|
|
15
|
-
{
|
|
16
|
-
"content": [
|
|
17
|
-
{
|
|
18
|
-
"text": "{"query":"button","count":2,"results":[{"key":"button","name":"Button","description":"Interactive button component with multiple themes and states","element":"button"},{"key":"radio","name":"Radio","description":"Radio button for selecting exactly one option from mutually exclusive choices","element":"input[type='radio']"}]}",
|
|
19
|
-
"type": "text",
|
|
20
|
-
},
|
|
21
|
-
],
|
|
22
|
-
}
|
|
23
|
-
`;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import handler from './handler.js';
|
|
2
|
-
import { describe, expect, it } from 'vitest';
|
|
3
|
-
|
|
4
|
-
describe('searchComponents tool', () => {
|
|
5
|
-
it('should search for components by keyword', () => {
|
|
6
|
-
const result = handler({ query: 'button' });
|
|
7
|
-
expect(result).toMatchSnapshot();
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it('should return an empty response if no components match the query', () => {
|
|
11
|
-
const result = handler({ query: 'DoctorWhoIsTheBestShowInTheWorld' });
|
|
12
|
-
expect(result).toMatchSnapshot();
|
|
13
|
-
});
|
|
14
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { CallToolResult } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
-
import { componentManifest } from '@/manifests/components/index.js';
|
|
3
|
-
|
|
4
|
-
export interface SearchComponentsArgs {
|
|
5
|
-
query: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export default (args: SearchComponentsArgs): CallToolResult => {
|
|
9
|
-
const query = args.query.toLowerCase();
|
|
10
|
-
const results = [];
|
|
11
|
-
|
|
12
|
-
for (const [key, comp] of Object.entries(componentManifest)) {
|
|
13
|
-
const searchText = `${key} ${comp.name} ${comp.description}`.toLowerCase();
|
|
14
|
-
if (searchText.includes(query)) {
|
|
15
|
-
results.push({
|
|
16
|
-
key,
|
|
17
|
-
name: comp.name,
|
|
18
|
-
description: comp.description,
|
|
19
|
-
element: comp.element,
|
|
20
|
-
});
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
content: [
|
|
26
|
-
{
|
|
27
|
-
type: 'text',
|
|
28
|
-
text: JSON.stringify({
|
|
29
|
-
query,
|
|
30
|
-
count: results.length,
|
|
31
|
-
results,
|
|
32
|
-
}),
|
|
33
|
-
},
|
|
34
|
-
],
|
|
35
|
-
};
|
|
36
|
-
};
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import handler from './handler.js';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
|
|
4
|
-
const toolDefinition = {
|
|
5
|
-
name: 'search_components',
|
|
6
|
-
config: {
|
|
7
|
-
description: 'Search for componentManifest by keyword or usage',
|
|
8
|
-
inputSchema: {
|
|
9
|
-
query: z.string().describe('Search query'),
|
|
10
|
-
},
|
|
11
|
-
},
|
|
12
|
-
handler,
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
export default toolDefinition;
|