@czi-sds/mcp 0.15.0 → 0.17.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/README.md +2 -1
- package/data/component-docs/Accordion.md +291 -0
- package/data/component-docs/Autocomplete.md +525 -0
- package/data/component-docs/Banner.md +231 -0
- package/data/component-docs/Button.md +224 -0
- package/data/component-docs/ButtonDropdown.md +256 -0
- package/data/component-docs/ButtonGroup.md +320 -0
- package/data/component-docs/ButtonToggle.md +397 -0
- package/data/component-docs/Callout.md +268 -0
- package/data/component-docs/CellBasic.md +122 -0
- package/data/component-docs/CellComponent.md +63 -0
- package/data/component-docs/CellHeader.md +128 -0
- package/data/component-docs/ComplexFilter.md +294 -0
- package/data/component-docs/ContentCard.md +406 -0
- package/data/component-docs/Dialog.md +651 -0
- package/data/component-docs/Dropdown.md +155 -0
- package/data/component-docs/DropdownMenu.md +949 -0
- package/data/component-docs/HeatmapChart.md +782 -0
- package/data/component-docs/Hero.md +363 -0
- package/data/component-docs/Icon.md +283 -0
- package/data/component-docs/InputCheckbox.md +205 -0
- package/data/component-docs/InputDropdown.md +482 -0
- package/data/component-docs/InputRadio.md +173 -0
- package/data/component-docs/InputSearch.md +81 -0
- package/data/component-docs/InputSlider.md +189 -0
- package/data/component-docs/InputText.md +110 -0
- package/data/component-docs/InputToggle.md +141 -0
- package/data/component-docs/IntentMessage.md +293 -0
- package/data/component-docs/Legend.md +442 -0
- package/data/component-docs/Link.md +23 -0
- package/data/component-docs/List.md +300 -0
- package/data/component-docs/LoadingIndicator.md +198 -0
- package/data/component-docs/Menu.md +298 -0
- package/data/component-docs/MenuItem.md +100 -0
- package/data/component-docs/NavigationFooter.md +165 -0
- package/data/component-docs/NavigationHeader.md +500 -0
- package/data/component-docs/NavigationJumpTo.md +414 -0
- package/data/component-docs/Notification.md +288 -0
- package/data/component-docs/Pagination.md +67 -0
- package/data/component-docs/Panel.md +636 -0
- package/data/component-docs/Popover.md +448 -0
- package/data/component-docs/PreComposedTable.md +2947 -0
- package/data/component-docs/SegmentedControl.md +396 -0
- package/data/component-docs/StackedBarChart.md +475 -0
- package/data/component-docs/Table.md +2000 -0
- package/data/component-docs/TableHeader.md +53 -0
- package/data/component-docs/TableRow.md +74 -0
- package/data/component-docs/Tabs.md +455 -0
- package/data/component-docs/Tag.md +647 -0
- package/data/component-docs/TagFilter.md +131 -0
- package/data/component-docs/Tooltip.md +561 -0
- package/data/component-docs/TooltipCondensed.md +203 -0
- package/data/component-docs/TooltipTable.md +145 -0
- package/data/component-docs/index.json +262 -0
- package/data/component-list.json +2 -5
- package/data/component-props/Accordion.json +31 -11
- package/data/component-props/Alert.json +3 -3
- package/data/component-props/Autocomplete.json +150 -15
- package/data/component-props/Banner.json +31 -17
- package/data/component-props/Button.json +45 -20
- package/data/component-props/ButtonDropdown.json +36 -17
- package/data/component-props/ButtonDropdownLegacy.json +11 -11
- package/data/component-props/ButtonGroup.json +32 -11
- package/data/component-props/ButtonIcon.json +10 -10
- package/data/component-props/ButtonLegacy.json +19 -19
- package/data/component-props/ButtonToggle.json +32 -19
- package/data/component-props/ButtonToggleLegacy.json +11 -11
- package/data/component-props/Callout.json +58 -17
- package/data/component-props/CellBasic.json +94 -41
- package/data/component-props/CellComponent.json +23 -7
- package/data/component-props/CellHeader.json +62 -19
- package/data/component-props/ComplexFilter.json +52 -21
- package/data/component-props/ContentCard.json +70 -47
- package/data/component-props/Dialog.json +47 -14
- package/data/component-props/Dropdown.json +67 -31
- package/data/component-props/DropdownMenu.json +128 -23
- package/data/component-props/HeatmapChart.json +88 -12
- package/data/component-props/Hero.json +80 -39
- package/data/component-props/Icon.json +20 -9
- package/data/component-props/InputCheckbox.json +36 -14
- package/data/component-props/InputDropdown.json +75 -27
- package/data/component-props/InputRadio.json +31 -13
- package/data/component-props/InputSearch.json +41 -18
- package/data/component-props/InputSlider.json +46 -19
- package/data/component-props/InputText.json +26 -19
- package/data/component-props/InputToggle.json +26 -9
- package/data/component-props/IntentMessage.json +38 -9
- package/data/component-props/Link.json +13 -7
- package/data/component-props/LoadingIndicator.json +11 -3
- package/data/component-props/MenuItem.json +38 -19
- package/data/component-props/MenuSelect.json +8 -8
- package/data/component-props/NavigationFooter.json +49 -19
- package/data/component-props/NavigationHeader.json +150 -37
- package/data/component-props/NavigationJumpTo.json +33 -7
- package/data/component-props/Notification.json +39 -21
- package/data/component-props/Pagination.json +39 -11
- package/data/component-props/Panel.json +62 -9
- package/data/component-props/Popover.json +80 -7
- package/data/component-props/PreComposedTable.json +99 -27
- package/data/component-props/SegmentedControl.json +42 -3
- package/data/component-props/StackedBarChart.json +116 -42
- package/data/component-props/TableRow.json +38 -19
- package/data/component-props/Tabs.json +66 -9
- package/data/component-props/Tag.json +34 -17
- package/data/component-props/TagFilter.json +10 -3
- package/data/component-props/Tooltip.json +49 -18
- package/data/component-props/TooltipCondensed.json +18 -9
- package/data/component-props/TooltipTable.json +17 -7
- package/data/resources/{zeroheight-rules.md → documentation-rules.md} +43 -30
- package/data/resources/figma-rules.md +2 -2
- package/dist/stdio.js +483 -780
- package/package.json +12 -8
- package/data/component-props/ButtonDropdownV2.json +0 -34
- package/data/component-props/ButtonNew.json +0 -47
- package/data/component-props/ButtonToggleV2.json +0 -44
- package/data/component-props/ButtonV2.json +0 -43
- package/data/zeroheight-cache.json +0 -10259
- package/data/zeroheight-exports/Accordion.md +0 -774
- package/data/zeroheight-exports/Banner.md +0 -691
- package/data/zeroheight-exports/Borders.md +0 -117
- package/data/zeroheight-exports/Buttons.md +0 -1854
- package/data/zeroheight-exports/Callout.md +0 -931
- package/data/zeroheight-exports/Colors.md +0 -1755
- package/data/zeroheight-exports/Content-Card.md +0 -309
- package/data/zeroheight-exports/Contributing-to-SDS.md +0 -98
- package/data/zeroheight-exports/Control-Inputs.md +0 -2818
- package/data/zeroheight-exports/Corners.md +0 -104
- package/data/zeroheight-exports/Cover-page.md +0 -3
- package/data/zeroheight-exports/Dialog.md +0 -1367
- package/data/zeroheight-exports/Downloads.md +0 -236
- package/data/zeroheight-exports/Drop-Shadows.md +0 -79
- package/data/zeroheight-exports/Dropdown-Input.md +0 -1776
- package/data/zeroheight-exports/Dropdown-Menus.md +0 -913
- package/data/zeroheight-exports/Element-Status-Tracker.md +0 -267
- package/data/zeroheight-exports/Field-Inputs.md +0 -1405
- package/data/zeroheight-exports/Filters.md +0 -1111
- package/data/zeroheight-exports/Getting-Started.md +0 -1157
- package/data/zeroheight-exports/Hero.md +0 -414
- package/data/zeroheight-exports/Icons.md +0 -2067
- package/data/zeroheight-exports/Intent.md +0 -86
- package/data/zeroheight-exports/Introduction-to-Bases.md +0 -35
- package/data/zeroheight-exports/Introduction-to-Cells.md +0 -35
- package/data/zeroheight-exports/Introduction-to-DNA.md +0 -35
- package/data/zeroheight-exports/Introduction-to-Genes.md +0 -35
- package/data/zeroheight-exports/Introduction.md +0 -115
- package/data/zeroheight-exports/Link.md +0 -432
- package/data/zeroheight-exports/Lists.md +0 -986
- package/data/zeroheight-exports/Loading-Indicator.md +0 -41
- package/data/zeroheight-exports/Navigation.md +0 -1190
- package/data/zeroheight-exports/Notification.md +0 -1038
- package/data/zeroheight-exports/Panel.md +0 -1030
- package/data/zeroheight-exports/README.md +0 -122
- package/data/zeroheight-exports/Responsive-Design.md +0 -330
- package/data/zeroheight-exports/Search-Input.md +0 -91
- package/data/zeroheight-exports/Search.md +0 -822
- package/data/zeroheight-exports/Segmented-Control.md +0 -609
- package/data/zeroheight-exports/Spacing.md +0 -297
- package/data/zeroheight-exports/Table.md +0 -5345
- package/data/zeroheight-exports/Tabs.md +0 -1324
- package/data/zeroheight-exports/Tags.md +0 -1545
- package/data/zeroheight-exports/Text-Link.md +0 -268
- package/data/zeroheight-exports/Theming.md +0 -362
- package/data/zeroheight-exports/Tooltips.md +0 -2015
- package/data/zeroheight-exports/Typography.md +0 -800
package/dist/stdio.js
CHANGED
|
@@ -1,242 +1,189 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { StdioServerTransport } from
|
|
3
|
-
import { McpServer } from
|
|
4
|
-
import { z } from
|
|
5
|
-
import fs, {
|
|
6
|
-
import path, { dirname
|
|
7
|
-
import { fileURLToPath } from
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import fs, { existsSync, readFileSync } from "fs";
|
|
6
|
+
import path, { dirname, join } from "path";
|
|
7
|
+
import { fileURLToPath } from "url";
|
|
8
|
+
//#region src/server.ts
|
|
9
|
+
const server = new McpServer({
|
|
10
|
+
name: "sds-mcp",
|
|
11
|
+
version: "0.1.0",
|
|
12
|
+
capabilities: {
|
|
13
|
+
prompts: {},
|
|
14
|
+
resources: {
|
|
15
|
+
subscribe: true,
|
|
16
|
+
listChanged: true
|
|
17
|
+
},
|
|
18
|
+
tools: {}
|
|
19
|
+
}
|
|
20
20
|
});
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
//#endregion
|
|
22
|
+
//#region src/lib/fetch.ts
|
|
23
|
+
const filename = fileURLToPath(import.meta.url);
|
|
24
|
+
const dirname$1 = path.dirname(filename);
|
|
25
|
+
/**
|
|
26
|
+
* Locates a file under `data/`. The server runs both from source via tsx and
|
|
27
|
+
* from the bundle in `dist/`, which sit at different depths, and may also be
|
|
28
|
+
* started from the package root.
|
|
29
|
+
*/
|
|
30
|
+
function resolveDataPath(relativePath) {
|
|
31
|
+
return [
|
|
32
|
+
path.join(dirname$1, "../../data", relativePath),
|
|
33
|
+
path.join(dirname$1, "../data", relativePath),
|
|
34
|
+
path.join(process.cwd(), "data", relativePath)
|
|
35
|
+
].find((candidate) => fs.existsSync(candidate)) ?? null;
|
|
36
|
+
}
|
|
37
|
+
function readDataFile(relativePath, missingHint) {
|
|
38
|
+
const dataPath = resolveDataPath(relativePath);
|
|
39
|
+
if (!dataPath) throw new Error(`${relativePath} not found in any expected location. ${missingHint}`);
|
|
40
|
+
return fs.readFileSync(dataPath, "utf-8");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Gets all component names from both packages
|
|
44
|
+
*/
|
|
23
45
|
async function getAllComponentNames() {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
// From dist in prod
|
|
30
|
-
path.join(process.cwd(), "data/component-list.json")
|
|
31
|
-
// From current working directory
|
|
32
|
-
];
|
|
33
|
-
let dataPath = "";
|
|
34
|
-
for (const p of possiblePaths) {
|
|
35
|
-
if (fs.existsSync(p)) {
|
|
36
|
-
dataPath = p;
|
|
37
|
-
break;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
if (!dataPath) {
|
|
41
|
-
throw new Error(
|
|
42
|
-
"Component list not found in any expected location. Please run 'yarn generate:components-list' first."
|
|
43
|
-
);
|
|
44
|
-
}
|
|
45
|
-
const fileContent = fs.readFileSync(dataPath, "utf-8");
|
|
46
|
-
const componentList = JSON.parse(fileContent);
|
|
47
|
-
return componentList;
|
|
48
|
-
} catch (error) {
|
|
49
|
-
throw new Error(
|
|
50
|
-
`Failed to load component list: ${error instanceof Error ? error.message : `Unknown error ${error}`}`
|
|
51
|
-
);
|
|
52
|
-
}
|
|
46
|
+
try {
|
|
47
|
+
return JSON.parse(readDataFile("component-list.json", "Please run 'yarn generate:components-list' first."));
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw new Error(`Failed to load component list: ${error instanceof Error ? error.message : `Unknown error ${error}`}`);
|
|
50
|
+
}
|
|
53
51
|
}
|
|
54
52
|
async function fetchComponentProps(component) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
for (const p of propsPaths) {
|
|
66
|
-
if (fs.existsSync(p)) {
|
|
67
|
-
propsPath = p;
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
if (!propsPath) {
|
|
72
|
-
return {
|
|
73
|
-
[component]: {
|
|
74
|
-
message: "Props information not available for this component. Run 'yarn generate:component-props' to generate props data.",
|
|
75
|
-
props: {}
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
const fileContent = fs.readFileSync(propsPath, "utf-8");
|
|
80
|
-
return JSON.parse(fileContent);
|
|
81
|
-
} catch (error) {
|
|
82
|
-
throw new Error(
|
|
83
|
-
`Failed to load props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
84
|
-
);
|
|
85
|
-
}
|
|
53
|
+
try {
|
|
54
|
+
const propsPath = resolveDataPath(`component-props/${component}.json`);
|
|
55
|
+
if (!propsPath) return { [component]: {
|
|
56
|
+
message: "Props information not available for this component. Run 'yarn generate:component-props' to generate props data.",
|
|
57
|
+
props: {}
|
|
58
|
+
} };
|
|
59
|
+
return JSON.parse(fs.readFileSync(propsPath, "utf-8"));
|
|
60
|
+
} catch (error) {
|
|
61
|
+
throw new Error(`Failed to load props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
62
|
+
}
|
|
86
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Gets the index of components that have generated documentation
|
|
66
|
+
*/
|
|
67
|
+
async function getComponentDocsIndex() {
|
|
68
|
+
try {
|
|
69
|
+
return JSON.parse(readDataFile("component-docs/index.json", "Please run 'yarn generate:component-docs' first."));
|
|
70
|
+
} catch (error) {
|
|
71
|
+
throw new Error(`Failed to load component docs index: ${error instanceof Error ? error.message : `Unknown error ${error}`}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Fetches the generated documentation markdown for a specific component
|
|
76
|
+
*/
|
|
77
|
+
async function fetchComponentDocs(file) {
|
|
78
|
+
try {
|
|
79
|
+
return readDataFile(`component-docs/${file}`, "Please run 'yarn generate:component-docs' first.");
|
|
80
|
+
} catch (error) {
|
|
81
|
+
throw new Error(`Failed to load documentation from ${file}: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Gets all component names from both packages
|
|
86
|
+
*/
|
|
87
87
|
async function fetchTailwindTokens() {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
// From dist in prod
|
|
94
|
-
path.join(process.cwd(), "data/tailwind.json")
|
|
95
|
-
// From current working directory
|
|
96
|
-
];
|
|
97
|
-
let dataPath = "";
|
|
98
|
-
for (const p of possiblePaths) {
|
|
99
|
-
if (fs.existsSync(p)) {
|
|
100
|
-
dataPath = p;
|
|
101
|
-
break;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (!dataPath) {
|
|
105
|
-
throw new Error(
|
|
106
|
-
"Component list not found in any expected location. Please run 'yarn generate:tailwind-tokens' first."
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
const fileContent = fs.readFileSync(dataPath, "utf-8");
|
|
110
|
-
const tailwindTokens = JSON.parse(fileContent);
|
|
111
|
-
return tailwindTokens;
|
|
112
|
-
} catch (error) {
|
|
113
|
-
throw new Error(
|
|
114
|
-
`Failed to load tailwind tokens: ${error instanceof Error ? error.message : `Unknown error ${error}`}`
|
|
115
|
-
);
|
|
116
|
-
}
|
|
88
|
+
try {
|
|
89
|
+
return JSON.parse(readDataFile("tailwind.json", "Please run 'yarn generate:tailwind-tokens' first."));
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new Error(`Failed to load tailwind tokens: ${error instanceof Error ? error.message : `Unknown error ${error}`}`);
|
|
92
|
+
}
|
|
117
93
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
const json = await fetchComponentProps(component);
|
|
148
|
-
return {
|
|
149
|
-
content: [
|
|
150
|
-
{
|
|
151
|
-
type: "text",
|
|
152
|
-
text: JSON.stringify(json)
|
|
153
|
-
}
|
|
154
|
-
]
|
|
155
|
-
};
|
|
156
|
-
} catch (error) {
|
|
157
|
-
return {
|
|
158
|
-
content: [
|
|
159
|
-
{
|
|
160
|
-
type: "text",
|
|
161
|
-
text: `Failed to get component props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
162
|
-
}
|
|
163
|
-
]
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
);
|
|
168
|
-
}
|
|
94
|
+
//#endregion
|
|
95
|
+
//#region src/tools/get-component-props.ts
|
|
96
|
+
const getComponentPropsTool = {
|
|
97
|
+
name: "get_component_props",
|
|
98
|
+
description: "Get detailed properties of a specific SDS component. This tool retrieves the properties, attributes, design related props for a component, like sdsStyle, sdsType, sdsSize, etc. and configuration options available for a given SDS component.",
|
|
99
|
+
async ctx() {
|
|
100
|
+
try {
|
|
101
|
+
const componentList = await getAllComponentNames();
|
|
102
|
+
return { componentList: [...componentList.components, ...componentList["data-viz"]] };
|
|
103
|
+
} catch (error) {
|
|
104
|
+
throw new Error(`Failed to initialize component props tool: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
exec(server, { ctx, name, description }) {
|
|
108
|
+
server.tool(name, description, { component: z.enum(ctx.componentList).describe("The name of the SDS component to get properties for") }, async ({ component }) => {
|
|
109
|
+
try {
|
|
110
|
+
const json = await fetchComponentProps(component);
|
|
111
|
+
return { content: [{
|
|
112
|
+
type: "text",
|
|
113
|
+
text: JSON.stringify(json)
|
|
114
|
+
}] };
|
|
115
|
+
} catch (error) {
|
|
116
|
+
return { content: [{
|
|
117
|
+
type: "text",
|
|
118
|
+
text: `Failed to get component props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
119
|
+
}] };
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
169
123
|
};
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
type: "text",
|
|
191
|
-
text: JSON.stringify(ctx.componentList, null, 2)
|
|
192
|
-
}
|
|
193
|
-
]
|
|
194
|
-
};
|
|
195
|
-
});
|
|
196
|
-
}
|
|
124
|
+
//#endregion
|
|
125
|
+
//#region src/tools/list-components.ts
|
|
126
|
+
const listComponentsTool = {
|
|
127
|
+
name: "list_components",
|
|
128
|
+
description: "List all available components in SDS. This tool retrieves the names of all SDS components from both the @czi-sds/components package and the @czi-sds/data-viz package.",
|
|
129
|
+
async ctx() {
|
|
130
|
+
try {
|
|
131
|
+
return { componentList: await getAllComponentNames() };
|
|
132
|
+
} catch (error) {
|
|
133
|
+
throw new Error(`Failed to initialize list components tool: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
exec(server, { ctx, name, description }) {
|
|
137
|
+
server.tool(name, description, {}, async () => {
|
|
138
|
+
return { content: [{
|
|
139
|
+
type: "text",
|
|
140
|
+
text: JSON.stringify(ctx.componentList, null, 2)
|
|
141
|
+
}] };
|
|
142
|
+
});
|
|
143
|
+
}
|
|
197
144
|
};
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
145
|
+
//#endregion
|
|
146
|
+
//#region src/lib/tailwind-guidance.ts
|
|
147
|
+
const TAILWIND_TOKEN_GUIDANCE = {
|
|
148
|
+
colors: {
|
|
149
|
+
category: "Colors",
|
|
150
|
+
description: "Theme-aware color tokens support both light and dark modes. Both modes follow the same token name structure: use light-token-name for light mode colors and dark:dark-token-name for dark mode colors.",
|
|
151
|
+
prefixes: [
|
|
152
|
+
"bg-",
|
|
153
|
+
"border-",
|
|
154
|
+
"divide-",
|
|
155
|
+
"outline-",
|
|
156
|
+
"ring-",
|
|
157
|
+
"ring-offset-",
|
|
158
|
+
"text-",
|
|
159
|
+
"placeholder-",
|
|
160
|
+
"caret-",
|
|
161
|
+
"decoration-",
|
|
162
|
+
"accent-",
|
|
163
|
+
"shadow-",
|
|
164
|
+
"fill-",
|
|
165
|
+
"stroke-",
|
|
166
|
+
"from-",
|
|
167
|
+
"via-",
|
|
168
|
+
"to-"
|
|
169
|
+
],
|
|
170
|
+
examples: [
|
|
171
|
+
{
|
|
172
|
+
description: "Basic text and background colors",
|
|
173
|
+
code: `<div className="bg-light-sds-color-semantic-base-background-primary dark:bg-dark-sds-color-semantic-base-background-primary text-light-sds-color-semantic-base-text-primary dark:text-dark-sds-color-semantic-base-text-primary">
|
|
227
174
|
Content with semantic colors
|
|
228
175
|
</div>`
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
description: "Dark mode with hover states",
|
|
179
|
+
code: `<button className="bg-light-sds-color-semantic-accent-fill-primary dark:bg-dark-sds-color-semantic-accent-fill-primary
|
|
233
180
|
hover:bg-light-sds-color-semantic-accent-fill-hover dark:hover:bg-dark-sds-color-semantic-accent-fill-hover">
|
|
234
181
|
Click me
|
|
235
182
|
</button>`
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
description: "Border and focus states",
|
|
186
|
+
code: `<input className="
|
|
240
187
|
border-light-sds-color-semantic-base-border-primary
|
|
241
188
|
hover:border-light-sds-color-semantic-base-border-primary-hover
|
|
242
189
|
focus:border-light-sds-color-semantic-base-border-primary-pressed
|
|
@@ -244,21 +191,22 @@ var TAILWIND_TOKEN_GUIDANCE = {
|
|
|
244
191
|
dark:hover:border-dark-sds-color-semantic-base-border-primary-hover
|
|
245
192
|
dark:focus:border-dark-sds-color-semantic-base-border-primary-pressed
|
|
246
193
|
"/>`
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
194
|
+
}
|
|
195
|
+
],
|
|
196
|
+
tips: ["Always use semantic colors (e.g., 'bg-light-sds-color-semantic-base-background-primary dark:bg-dark-sds-color-semantic-base-background-primary') over primitive colors when possible", "Include both light and dark variants for proper theme support"]
|
|
197
|
+
},
|
|
198
|
+
typography: {
|
|
199
|
+
category: "Typography",
|
|
200
|
+
description: "Complete text styling presets including font, size, weight, and spacing",
|
|
201
|
+
prefixes: [
|
|
202
|
+
"font-",
|
|
203
|
+
"text-",
|
|
204
|
+
"leading-",
|
|
205
|
+
"tracking-"
|
|
206
|
+
],
|
|
207
|
+
examples: [{
|
|
208
|
+
description: "Typography presets (recommended). SDS typography tokens come in narrow and wide variants: use token-narrow on screens smaller than md, and token-wide on md and up.",
|
|
209
|
+
code: `<!-- Use typography tokens for complete text styling -->
|
|
262
210
|
<h1 className="prose-sds-title-l-700-wide">Title</h1>
|
|
263
211
|
<h1 className="prose-sds-header-xl-600-wide">Heading</h1>
|
|
264
212
|
<p className="prose-sds-body-m-500-wide">Body text</p>
|
|
@@ -266,10 +214,9 @@ var TAILWIND_TOKEN_GUIDANCE = {
|
|
|
266
214
|
<span className="prose-sds-tabular-xxs-600-wide">Tabular Numbers</span>
|
|
267
215
|
<span className="prose-sds-code-s-500-wide">Code</span>
|
|
268
216
|
<span className="prose-sds-link-l-500-wide">Link style</span>`
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
code: `<!-- Or use individual properties when needed -->
|
|
217
|
+
}, {
|
|
218
|
+
description: "Individual typography properties",
|
|
219
|
+
code: `<!-- Or use individual properties when needed -->
|
|
273
220
|
<p className="
|
|
274
221
|
font-sds-body
|
|
275
222
|
text-sds-body-m-400-wide
|
|
@@ -278,48 +225,47 @@ var TAILWIND_TOKEN_GUIDANCE = {
|
|
|
278
225
|
">
|
|
279
226
|
Custom styled text
|
|
280
227
|
</p>`
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
code: `<div className="p-sds-m mx-sds-l my-sds-s">
|
|
228
|
+
}],
|
|
229
|
+
tips: [
|
|
230
|
+
"Use 'narrow' variants for mobile/compact layouts",
|
|
231
|
+
"Use 'wide' variants for desktop/spacious layouts",
|
|
232
|
+
"Font weights: 400 (regular), 500 (medium), 600 (semibold), 700 (bold)"
|
|
233
|
+
]
|
|
234
|
+
},
|
|
235
|
+
spacing: {
|
|
236
|
+
category: "Spacing",
|
|
237
|
+
description: "Consistent spacing scale for padding, margin, and gaps",
|
|
238
|
+
prefixes: [
|
|
239
|
+
"p-",
|
|
240
|
+
"px-",
|
|
241
|
+
"py-",
|
|
242
|
+
"pt-",
|
|
243
|
+
"pr-",
|
|
244
|
+
"pb-",
|
|
245
|
+
"pl-",
|
|
246
|
+
"m-",
|
|
247
|
+
"mx-",
|
|
248
|
+
"my-",
|
|
249
|
+
"mt-",
|
|
250
|
+
"mr-",
|
|
251
|
+
"mb-",
|
|
252
|
+
"ml-",
|
|
253
|
+
"gap-",
|
|
254
|
+
"gap-x-",
|
|
255
|
+
"gap-y-",
|
|
256
|
+
"space-x-",
|
|
257
|
+
"space-y-"
|
|
258
|
+
],
|
|
259
|
+
examples: [
|
|
260
|
+
{
|
|
261
|
+
description: "Padding and margin",
|
|
262
|
+
code: `<div className="p-sds-m mx-sds-l my-sds-s">
|
|
317
263
|
Content with medium padding and different margins
|
|
318
264
|
</div>`
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
description: "Flexbox and grid gaps",
|
|
268
|
+
code: `<div className="flex gap-sds-m">
|
|
323
269
|
<div>Item 1</div>
|
|
324
270
|
<div>Item 2</div>
|
|
325
271
|
</div>
|
|
@@ -327,72 +273,71 @@ var TAILWIND_TOKEN_GUIDANCE = {
|
|
|
327
273
|
<div className="grid grid-cols-3 gap-sds-l">
|
|
328
274
|
<div>Grid item</div>
|
|
329
275
|
</div>`
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
description: "Negative margins for overlapping",
|
|
279
|
+
code: `<div className="-mt-sds-s">
|
|
334
280
|
Overlapping element
|
|
335
281
|
</div>`
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
code: `<div className="rounded-sds-default">
|
|
282
|
+
}
|
|
283
|
+
],
|
|
284
|
+
tips: [
|
|
285
|
+
"Scale: sds-s (small), sds-default (default), sds-m (medium), sds-l (large), sds-xl (extra large)",
|
|
286
|
+
"Use consistent spacing throughout your component",
|
|
287
|
+
"Combine with responsive prefixes: sm:p-sds-m lg:p-sds-l"
|
|
288
|
+
]
|
|
289
|
+
},
|
|
290
|
+
borderRadius: {
|
|
291
|
+
category: "Border Radius",
|
|
292
|
+
description: "Corner radius values for rounded elements",
|
|
293
|
+
prefixes: [
|
|
294
|
+
"rounded-",
|
|
295
|
+
"rounded-t-",
|
|
296
|
+
"rounded-r-",
|
|
297
|
+
"rounded-b-",
|
|
298
|
+
"rounded-l-"
|
|
299
|
+
],
|
|
300
|
+
examples: [{
|
|
301
|
+
description: "Basic rounded corners",
|
|
302
|
+
code: `<div className="rounded-sds-default">
|
|
358
303
|
Standard rounded corners
|
|
359
304
|
</div>
|
|
360
305
|
|
|
361
306
|
<button className="rounded-sds-m">
|
|
362
307
|
More rounded button
|
|
363
308
|
</button>`
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
code: `<div className="rounded-t-sds-l rounded-b-none">
|
|
309
|
+
}, {
|
|
310
|
+
description: "Directional radius",
|
|
311
|
+
code: `<div className="rounded-t-sds-l rounded-b-none">
|
|
368
312
|
Only top corners rounded
|
|
369
313
|
</div>`
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
314
|
+
}],
|
|
315
|
+
tips: [
|
|
316
|
+
"Use sds-default for most UI elements",
|
|
317
|
+
"Larger values (sds-l, sds-xl) for prominent elements",
|
|
318
|
+
"Combine with borders: border rounded-sds-m"
|
|
319
|
+
]
|
|
320
|
+
},
|
|
321
|
+
boxShadow: {
|
|
322
|
+
category: "Box Shadow",
|
|
323
|
+
description: "Elevation shadows for depth and hierarchy",
|
|
324
|
+
prefixes: [
|
|
325
|
+
"shadow-",
|
|
326
|
+
"hover:shadow-",
|
|
327
|
+
"focus:shadow-"
|
|
328
|
+
],
|
|
329
|
+
examples: [{
|
|
330
|
+
description: "Basic shadows",
|
|
331
|
+
code: `<div className="shadow-sds-s">
|
|
386
332
|
Subtle shadow
|
|
387
333
|
</div>
|
|
388
334
|
|
|
389
335
|
<div className="shadow-sds-m">
|
|
390
336
|
Medium elevation
|
|
391
337
|
</div>`
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
code: `<button className="
|
|
338
|
+
}, {
|
|
339
|
+
description: "Interactive shadows",
|
|
340
|
+
code: `<button className="
|
|
396
341
|
shadow-sds-s
|
|
397
342
|
hover:shadow-sds-m
|
|
398
343
|
active:shadow-sds-xs
|
|
@@ -400,18 +345,16 @@ var TAILWIND_TOKEN_GUIDANCE = {
|
|
|
400
345
|
">
|
|
401
346
|
Interactive element
|
|
402
347
|
</button>`
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
348
|
+
}],
|
|
349
|
+
tips: [
|
|
350
|
+
"Use smaller shadows (sds-xs, sds-s) for subtle depth",
|
|
351
|
+
"Use larger shadows (sds-l, sds-xl) for modals and popovers",
|
|
352
|
+
"Combine with hover states for interactive feedback"
|
|
353
|
+
]
|
|
354
|
+
}
|
|
411
355
|
};
|
|
412
356
|
function getTokenGuidance(category) {
|
|
413
|
-
|
|
414
|
-
return `SDS Design System Tokens for Tailwind CSS
|
|
357
|
+
if (!category || category === "all") return `SDS Design System Tokens for Tailwind CSS
|
|
415
358
|
|
|
416
359
|
The Science Design System provides a comprehensive set of design tokens that map directly to Tailwind utilities.
|
|
417
360
|
|
|
@@ -438,450 +381,210 @@ typography: This category can be used for formatting typography in the tailwind.
|
|
|
438
381
|
height, width, borderRadius, boxShadow, breakpoints: These categories can be used for formatting height, width, border radius, box shadow, and breakpoints in the tailwind.config.js file
|
|
439
382
|
spacing: This category can be used for formatting spacing in the tailwind.config.js file
|
|
440
383
|
colors: This category can be used for formatting colors in the tailwind.config.js file`;
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
`;
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
output += `### Examples:
|
|
458
|
-
|
|
459
|
-
`;
|
|
460
|
-
guidance.examples.forEach((example, index) => {
|
|
461
|
-
output += `${index + 1}. **${example.description}**
|
|
462
|
-
\`\`\`jsx
|
|
463
|
-
${example.code}
|
|
464
|
-
\`\`\`
|
|
465
|
-
|
|
466
|
-
`;
|
|
467
|
-
});
|
|
468
|
-
if (guidance.tips && guidance.tips.length > 0) {
|
|
469
|
-
output += `### Tips:
|
|
470
|
-
`;
|
|
471
|
-
guidance.tips.forEach((tip) => {
|
|
472
|
-
output += `- ${tip}
|
|
473
|
-
`;
|
|
474
|
-
});
|
|
475
|
-
}
|
|
476
|
-
return output;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
// src/tools/get-tailwind-tokens.ts
|
|
480
|
-
var getTailwindTokensTool = {
|
|
481
|
-
name: "get_tailwind_tokens",
|
|
482
|
-
description: "Get all available Tailwind tokens from the SDS design system. Available design tokens include fontFamily, fontSize, fontVariantNumeric, letterSpacing, lineHeight, textDecoration, textTransform, typography, height, width, borderRadius, boxShadow, breakpoints, colors, spacing, and more.",
|
|
483
|
-
async ctx() {
|
|
484
|
-
try {
|
|
485
|
-
const tailwindTokens = await fetchTailwindTokens();
|
|
486
|
-
return { tailwindTokens };
|
|
487
|
-
} catch (error) {
|
|
488
|
-
throw new Error(
|
|
489
|
-
`Failed to initialize tailwind tokens tool: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
|
-
},
|
|
493
|
-
exec(server2, { ctx, name, description }) {
|
|
494
|
-
server2.tool(
|
|
495
|
-
name,
|
|
496
|
-
description,
|
|
497
|
-
{
|
|
498
|
-
category: z.enum([
|
|
499
|
-
"all",
|
|
500
|
-
"fontFamily",
|
|
501
|
-
"fontSize",
|
|
502
|
-
"fontVariantNumeric",
|
|
503
|
-
"letterSpacing",
|
|
504
|
-
"lineHeight",
|
|
505
|
-
"textDecoration",
|
|
506
|
-
"textTransform",
|
|
507
|
-
"typography",
|
|
508
|
-
"height",
|
|
509
|
-
"width",
|
|
510
|
-
"borderRadius",
|
|
511
|
-
"boxShadow",
|
|
512
|
-
"breakpoints",
|
|
513
|
-
"colors",
|
|
514
|
-
"spacing"
|
|
515
|
-
]).optional().describe(
|
|
516
|
-
"Optional category of tokens to retrieve. If not specified, returns all tokens."
|
|
517
|
-
)
|
|
518
|
-
},
|
|
519
|
-
async ({ category }) => {
|
|
520
|
-
try {
|
|
521
|
-
const tokens = ctx.tailwindTokens;
|
|
522
|
-
let result;
|
|
523
|
-
if (!category || category === "all") {
|
|
524
|
-
result = tokens;
|
|
525
|
-
} else {
|
|
526
|
-
result = tokens[category] || {};
|
|
527
|
-
}
|
|
528
|
-
const responseContent = [];
|
|
529
|
-
const guidance = getTokenGuidance(category);
|
|
530
|
-
responseContent.push({
|
|
531
|
-
type: "text",
|
|
532
|
-
text: guidance
|
|
533
|
-
});
|
|
534
|
-
responseContent.push({
|
|
535
|
-
type: "text",
|
|
536
|
-
text: JSON.stringify(result, null, 2)
|
|
537
|
-
});
|
|
538
|
-
return {
|
|
539
|
-
content: responseContent
|
|
540
|
-
};
|
|
541
|
-
} catch (error) {
|
|
542
|
-
return {
|
|
543
|
-
content: [
|
|
544
|
-
{
|
|
545
|
-
type: "text",
|
|
546
|
-
text: `Failed to get Tailwind tokens: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
547
|
-
}
|
|
548
|
-
]
|
|
549
|
-
};
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
);
|
|
553
|
-
}
|
|
554
|
-
};
|
|
555
|
-
var filename2 = fileURLToPath(import.meta.url);
|
|
556
|
-
var dirname2 = path.dirname(filename2);
|
|
557
|
-
function mapComponentToFile(componentName, exportedFiles) {
|
|
558
|
-
const componentToFileMap = {
|
|
559
|
-
// Button components
|
|
560
|
-
Button: "Buttons",
|
|
561
|
-
ButtonDropdown: "Buttons",
|
|
562
|
-
ButtonIcon: "Buttons",
|
|
563
|
-
ButtonToggle: "Buttons",
|
|
564
|
-
// Table components
|
|
565
|
-
TableHeader: "Table",
|
|
566
|
-
TableRow: "Table",
|
|
567
|
-
// Input components
|
|
568
|
-
InputCheckbox: "Control-Inputs",
|
|
569
|
-
InputRadio: "Control-Inputs",
|
|
570
|
-
InputToggle: "Control-Inputs",
|
|
571
|
-
InputText: "Field-Inputs",
|
|
572
|
-
InputDropdown: "Dropdown-Input",
|
|
573
|
-
InputSearch: "Search-Input",
|
|
574
|
-
InputSlider: "Control-Inputs",
|
|
575
|
-
// Dropdown components
|
|
576
|
-
Dropdown: "Dropdown-Menu",
|
|
577
|
-
DropdownMenu: "Dropdown-Menu",
|
|
578
|
-
// Content components
|
|
579
|
-
ContentCard: "Content-Card",
|
|
580
|
-
LoadingIndicator: "Loading-Indicator",
|
|
581
|
-
// Navigation components
|
|
582
|
-
NavigationFooter: "Navigation",
|
|
583
|
-
NavigationHeader: "Navigation",
|
|
584
|
-
NavigationJumpTo: "Navigation",
|
|
585
|
-
// Control components
|
|
586
|
-
SegmentedControl: "Segmented-Control",
|
|
587
|
-
// List and menu components
|
|
588
|
-
List: "Lists",
|
|
589
|
-
Menu: "Dropdown-Menu",
|
|
590
|
-
MenuItem: "Dropdown-Menu",
|
|
591
|
-
MenuSelect: "Dropdown-Menu",
|
|
592
|
-
// Tag components
|
|
593
|
-
Tag: "Tags",
|
|
594
|
-
TagFilter: "Tags",
|
|
595
|
-
// Tooltip components
|
|
596
|
-
Tooltip: "Tooltips",
|
|
597
|
-
TooltipCondensed: "Tooltips",
|
|
598
|
-
TooltipTable: "Tooltips",
|
|
599
|
-
// Table Cell components
|
|
600
|
-
CellBasic: "Table",
|
|
601
|
-
CellComponent: "Table",
|
|
602
|
-
CellHeader: "Table",
|
|
603
|
-
// Filter components
|
|
604
|
-
ComplexFilter: "Filters",
|
|
605
|
-
// Other components
|
|
606
|
-
Icon: "Icons",
|
|
607
|
-
Chip: "Tags",
|
|
608
|
-
// Chips are often similar to tags
|
|
609
|
-
Pagination: "Navigation"
|
|
610
|
-
// Pagination is often part of navigation
|
|
611
|
-
};
|
|
612
|
-
const mappedFile = componentToFileMap[componentName];
|
|
613
|
-
if (mappedFile && exportedFiles.includes(mappedFile)) {
|
|
614
|
-
return `${mappedFile}.md`;
|
|
615
|
-
}
|
|
616
|
-
if (exportedFiles.includes(componentName)) {
|
|
617
|
-
return `${componentName}.md`;
|
|
618
|
-
}
|
|
619
|
-
return null;
|
|
620
|
-
}
|
|
621
|
-
function getExportedFiles() {
|
|
622
|
-
try {
|
|
623
|
-
const possiblePaths = [
|
|
624
|
-
path.join(dirname2, "../../data/zeroheight-exports"),
|
|
625
|
-
// From src/lib in dev
|
|
626
|
-
path.join(dirname2, "../data/zeroheight-exports"),
|
|
627
|
-
// From dist in prod
|
|
628
|
-
path.join(process.cwd(), "data/zeroheight-exports")
|
|
629
|
-
// From current working directory
|
|
630
|
-
];
|
|
631
|
-
let exportDir = "";
|
|
632
|
-
for (const p of possiblePaths) {
|
|
633
|
-
if (fs.existsSync(p)) {
|
|
634
|
-
exportDir = p;
|
|
635
|
-
break;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
if (!exportDir) {
|
|
639
|
-
console.warn(
|
|
640
|
-
"Export directory not found in any expected location. Please run Zeroheight export first."
|
|
641
|
-
);
|
|
642
|
-
return [];
|
|
643
|
-
}
|
|
644
|
-
const files = fs.readdirSync(exportDir).filter((file) => file.endsWith(".md") && file !== "README.md").map((file) => file.replace(".md", ""));
|
|
645
|
-
return files;
|
|
646
|
-
} catch (error) {
|
|
647
|
-
console.warn("Could not read exported files:", error);
|
|
648
|
-
return [];
|
|
649
|
-
}
|
|
650
|
-
}
|
|
651
|
-
function getComponentsWithDocs(allComponents, exportedFiles) {
|
|
652
|
-
return allComponents.filter((component) => {
|
|
653
|
-
const mappedFile = mapComponentToFile(component, exportedFiles);
|
|
654
|
-
return mappedFile !== null;
|
|
655
|
-
});
|
|
384
|
+
const guidance = TAILWIND_TOKEN_GUIDANCE[category];
|
|
385
|
+
if (!guidance) return `Category "${category}" not found. Available categories: ${Object.keys(TAILWIND_TOKEN_GUIDANCE).join(", ")}`;
|
|
386
|
+
let output = `## ${guidance.category} Tokens\n\n`;
|
|
387
|
+
output += `${guidance.description}\n\n`;
|
|
388
|
+
output += `**Tailwind Prefixes:** ${guidance.prefixes.join(", ")}\n\n`;
|
|
389
|
+
output += `### Examples:\n\n`;
|
|
390
|
+
guidance.examples.forEach((example, index) => {
|
|
391
|
+
output += `${index + 1}. **${example.description}**\n\`\`\`jsx\n${example.code}\n\`\`\`\n\n`;
|
|
392
|
+
});
|
|
393
|
+
if (guidance.tips && guidance.tips.length > 0) {
|
|
394
|
+
output += `### Tips:\n`;
|
|
395
|
+
guidance.tips.forEach((tip) => {
|
|
396
|
+
output += `- ${tip}\n`;
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
return output;
|
|
656
400
|
}
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
}
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
listComponentsTool,
|
|
753
|
-
getTailwindTokensTool
|
|
401
|
+
//#endregion
|
|
402
|
+
//#region src/tools/index.ts
|
|
403
|
+
const tools = [
|
|
404
|
+
getComponentPropsTool,
|
|
405
|
+
{
|
|
406
|
+
name: "get_component_docs",
|
|
407
|
+
description: "Get design system documentation for a specific SDS component. Returns the component's full documentation, including how it differs from the underlying MUI component, its props, and runnable code examples for each supported variation.",
|
|
408
|
+
async ctx() {
|
|
409
|
+
try {
|
|
410
|
+
const index = await getComponentDocsIndex();
|
|
411
|
+
return {
|
|
412
|
+
index,
|
|
413
|
+
documented: Object.keys(index)
|
|
414
|
+
};
|
|
415
|
+
} catch (error) {
|
|
416
|
+
throw new Error(`Failed to initialize get component docs tool: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
417
|
+
}
|
|
418
|
+
},
|
|
419
|
+
exec(server, { ctx, name, description }) {
|
|
420
|
+
server.tool(name, description, { component: z.enum(ctx.documented).describe("The name of the SDS component to get documentation for") }, async ({ component }) => {
|
|
421
|
+
try {
|
|
422
|
+
const entry = ctx.index[component];
|
|
423
|
+
if (!entry) return { content: [{
|
|
424
|
+
type: "text",
|
|
425
|
+
text: `No documentation found for component '${component}'. This component may not have design system documentation available.`
|
|
426
|
+
}] };
|
|
427
|
+
const documentation = await fetchComponentDocs(entry.file);
|
|
428
|
+
return { content: [{
|
|
429
|
+
type: "text",
|
|
430
|
+
text: `Package: ${entry.package}\nSource: ${entry.source}\n\n${documentation}`
|
|
431
|
+
}] };
|
|
432
|
+
} catch (error) {
|
|
433
|
+
return { content: [{
|
|
434
|
+
type: "text",
|
|
435
|
+
text: `Error reading documentation for '${component}': ${error instanceof Error ? error.message : "Unknown error"}`
|
|
436
|
+
}] };
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
},
|
|
441
|
+
listComponentsTool,
|
|
442
|
+
{
|
|
443
|
+
name: "get_tailwind_tokens",
|
|
444
|
+
description: "Get all available Tailwind tokens from the SDS design system. Available design tokens include fontFamily, fontSize, fontVariantNumeric, letterSpacing, lineHeight, textDecoration, textTransform, typography, height, width, borderRadius, boxShadow, breakpoints, colors, spacing, and more.",
|
|
445
|
+
async ctx() {
|
|
446
|
+
try {
|
|
447
|
+
return { tailwindTokens: await fetchTailwindTokens() };
|
|
448
|
+
} catch (error) {
|
|
449
|
+
throw new Error(`Failed to initialize tailwind tokens tool: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
450
|
+
}
|
|
451
|
+
},
|
|
452
|
+
exec(server, { ctx, name, description }) {
|
|
453
|
+
server.tool(name, description, { category: z.enum([
|
|
454
|
+
"all",
|
|
455
|
+
"fontFamily",
|
|
456
|
+
"fontSize",
|
|
457
|
+
"fontVariantNumeric",
|
|
458
|
+
"letterSpacing",
|
|
459
|
+
"lineHeight",
|
|
460
|
+
"textDecoration",
|
|
461
|
+
"textTransform",
|
|
462
|
+
"typography",
|
|
463
|
+
"height",
|
|
464
|
+
"width",
|
|
465
|
+
"borderRadius",
|
|
466
|
+
"boxShadow",
|
|
467
|
+
"breakpoints",
|
|
468
|
+
"colors",
|
|
469
|
+
"spacing"
|
|
470
|
+
]).optional().describe("Optional category of tokens to retrieve. If not specified, returns all tokens.") }, async ({ category }) => {
|
|
471
|
+
try {
|
|
472
|
+
const tokens = ctx.tailwindTokens;
|
|
473
|
+
let result;
|
|
474
|
+
if (!category || category === "all") result = tokens;
|
|
475
|
+
else result = tokens[category] || {};
|
|
476
|
+
const responseContent = [];
|
|
477
|
+
const guidance = getTokenGuidance(category);
|
|
478
|
+
responseContent.push({
|
|
479
|
+
type: "text",
|
|
480
|
+
text: guidance
|
|
481
|
+
});
|
|
482
|
+
responseContent.push({
|
|
483
|
+
type: "text",
|
|
484
|
+
text: JSON.stringify(result, null, 2)
|
|
485
|
+
});
|
|
486
|
+
return { content: responseContent };
|
|
487
|
+
} catch (error) {
|
|
488
|
+
return { content: [{
|
|
489
|
+
type: "text",
|
|
490
|
+
text: `Failed to get Tailwind tokens: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
491
|
+
}] };
|
|
492
|
+
}
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
754
496
|
];
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
name: tool.name
|
|
770
|
-
});
|
|
771
|
-
})
|
|
772
|
-
);
|
|
497
|
+
const registeredToolCache = /* @__PURE__ */ new Map();
|
|
498
|
+
const initializeTools = async (server, config) => {
|
|
499
|
+
const enabledTools = tools.filter((tool) => !tool.disabled?.(config));
|
|
500
|
+
await Promise.all(enabledTools.map(async (tool) => {
|
|
501
|
+
const toolCtx = await tool.ctx?.();
|
|
502
|
+
if (registeredToolCache.has(tool.name)) return;
|
|
503
|
+
registeredToolCache.set(tool.name, tool);
|
|
504
|
+
tool.exec(server, {
|
|
505
|
+
config,
|
|
506
|
+
ctx: toolCtx,
|
|
507
|
+
description: tool.description,
|
|
508
|
+
name: tool.name
|
|
509
|
+
});
|
|
510
|
+
}));
|
|
773
511
|
};
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
512
|
+
//#endregion
|
|
513
|
+
//#region src/resources/index.ts
|
|
514
|
+
const DIRNAME = dirname(fileURLToPath(import.meta.url));
|
|
515
|
+
const MIME_TYPE_MARKDOWN = "text/markdown";
|
|
516
|
+
const UNKNOWN_ERROR = "Unknown error";
|
|
517
|
+
/**
|
|
518
|
+
* Finds the resource file by trying multiple paths
|
|
519
|
+
* to support both dev and production environments
|
|
520
|
+
*/
|
|
778
521
|
function findResourceFile(fileName) {
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
];
|
|
787
|
-
for (const p of possiblePaths) {
|
|
788
|
-
if (existsSync(p)) {
|
|
789
|
-
return p;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
throw new Error(
|
|
793
|
-
`Resource file '${fileName}' not found in any expected location`
|
|
794
|
-
);
|
|
522
|
+
const possiblePaths = [
|
|
523
|
+
join(DIRNAME, "../../data/resources", fileName),
|
|
524
|
+
join(DIRNAME, "../data/resources", fileName),
|
|
525
|
+
join(process.cwd(), "data/resources", fileName)
|
|
526
|
+
];
|
|
527
|
+
for (const p of possiblePaths) if (existsSync(p)) return p;
|
|
528
|
+
throw new Error(`Resource file '${fileName}' not found in any expected location`);
|
|
795
529
|
}
|
|
796
|
-
function initializeResources(
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
};
|
|
843
|
-
} catch (err) {
|
|
844
|
-
const message = err instanceof Error ? err.message : UNKNOWN_ERROR;
|
|
845
|
-
throw new Error("Failed to read component rules: " + message);
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
);
|
|
849
|
-
server2.resource(
|
|
850
|
-
"Zeroheight Documentation Rules",
|
|
851
|
-
"sds://rules/zeroheight",
|
|
852
|
-
{
|
|
853
|
-
mimeType: MIME_TYPE_MARKDOWN,
|
|
854
|
-
description: "Rules for following Zeroheight documentation"
|
|
855
|
-
},
|
|
856
|
-
async () => {
|
|
857
|
-
try {
|
|
858
|
-
const filePath = findResourceFile("zeroheight-rules.md");
|
|
859
|
-
const content = readFileSync(filePath, "utf-8");
|
|
860
|
-
return {
|
|
861
|
-
contents: [
|
|
862
|
-
{
|
|
863
|
-
uri: "sds://rules/zeroheight",
|
|
864
|
-
mimeType: MIME_TYPE_MARKDOWN,
|
|
865
|
-
text: content
|
|
866
|
-
}
|
|
867
|
-
]
|
|
868
|
-
};
|
|
869
|
-
} catch (err) {
|
|
870
|
-
const message = err instanceof Error ? err.message : UNKNOWN_ERROR;
|
|
871
|
-
throw new Error("Failed to read Zeroheight rules: " + message);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
);
|
|
530
|
+
function initializeResources(server) {
|
|
531
|
+
server.resource("Figma to Code Translation Rules", "sds://rules/figma", {
|
|
532
|
+
mimeType: MIME_TYPE_MARKDOWN,
|
|
533
|
+
description: "Rules for translating Figma designs to SDS code"
|
|
534
|
+
}, async () => {
|
|
535
|
+
try {
|
|
536
|
+
return { contents: [{
|
|
537
|
+
uri: "sds://rules/figma",
|
|
538
|
+
mimeType: MIME_TYPE_MARKDOWN,
|
|
539
|
+
text: readFileSync(findResourceFile("figma-rules.md"), "utf-8")
|
|
540
|
+
}] };
|
|
541
|
+
} catch (err) {
|
|
542
|
+
const message = err instanceof Error ? err.message : UNKNOWN_ERROR;
|
|
543
|
+
throw new Error("Failed to read Figma rules: " + message);
|
|
544
|
+
}
|
|
545
|
+
});
|
|
546
|
+
server.resource("SDS Component Usage Rules", "sds://rules/components", {
|
|
547
|
+
mimeType: MIME_TYPE_MARKDOWN,
|
|
548
|
+
description: "Guidelines for using SDS components correctly"
|
|
549
|
+
}, async () => {
|
|
550
|
+
try {
|
|
551
|
+
return { contents: [{
|
|
552
|
+
uri: "sds://rules/components",
|
|
553
|
+
mimeType: MIME_TYPE_MARKDOWN,
|
|
554
|
+
text: readFileSync(findResourceFile("sds-component-rules.md"), "utf-8")
|
|
555
|
+
}] };
|
|
556
|
+
} catch (err) {
|
|
557
|
+
const message = err instanceof Error ? err.message : UNKNOWN_ERROR;
|
|
558
|
+
throw new Error("Failed to read component rules: " + message);
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
server.resource("SDS Documentation Rules", "sds://rules/documentation", {
|
|
562
|
+
mimeType: MIME_TYPE_MARKDOWN,
|
|
563
|
+
description: "Rules for following the SDS component documentation"
|
|
564
|
+
}, async () => {
|
|
565
|
+
try {
|
|
566
|
+
return { contents: [{
|
|
567
|
+
uri: "sds://rules/documentation",
|
|
568
|
+
mimeType: MIME_TYPE_MARKDOWN,
|
|
569
|
+
text: readFileSync(findResourceFile("documentation-rules.md"), "utf-8")
|
|
570
|
+
}] };
|
|
571
|
+
} catch (err) {
|
|
572
|
+
const message = err instanceof Error ? err.message : UNKNOWN_ERROR;
|
|
573
|
+
throw new Error("Failed to read documentation rules: " + message);
|
|
574
|
+
}
|
|
575
|
+
});
|
|
875
576
|
}
|
|
876
|
-
|
|
877
|
-
|
|
577
|
+
//#endregion
|
|
578
|
+
//#region src/stdio.ts
|
|
878
579
|
async function main() {
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
580
|
+
await initializeTools(server, {});
|
|
581
|
+
initializeResources(server);
|
|
582
|
+
const transport = new StdioServerTransport();
|
|
583
|
+
await server.connect(transport);
|
|
883
584
|
}
|
|
884
585
|
main().catch((error) => {
|
|
885
|
-
|
|
886
|
-
|
|
586
|
+
console.error("Fatal error in main():", error);
|
|
587
|
+
process.exit(1);
|
|
887
588
|
});
|
|
589
|
+
//#endregion
|
|
590
|
+
export {};
|