@czi-sds/mcp 0.2.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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +34 -0
  3. package/data/component-list.json +55 -0
  4. package/data/component-props/Accordion.json +31 -0
  5. package/data/component-props/Alert.json +52 -0
  6. package/data/component-props/Autocomplete.json +52 -0
  7. package/data/component-props/Banner.json +35 -0
  8. package/data/component-props/Button.json +109 -0
  9. package/data/component-props/ButtonIcon.json +80 -0
  10. package/data/component-props/ButtonToggle.json +91 -0
  11. package/data/component-props/Callout.json +93 -0
  12. package/data/component-props/CellBasic.json +102 -0
  13. package/data/component-props/CellComponent.json +46 -0
  14. package/data/component-props/CellHeader.json +78 -0
  15. package/data/component-props/Chip.json +73 -0
  16. package/data/component-props/ComplexFilter.json +19 -0
  17. package/data/component-props/ContentCard.json +18 -0
  18. package/data/component-props/Dropdown.json +107 -0
  19. package/data/component-props/DropdownMenu.json +86 -0
  20. package/data/component-props/HeatmapChart.json +110 -0
  21. package/data/component-props/Icon.json +27 -0
  22. package/data/component-props/InputCheckbox.json +76 -0
  23. package/data/component-props/InputDropdown.json +72 -0
  24. package/data/component-props/InputRadio.json +75 -0
  25. package/data/component-props/InputSearch.json +99 -0
  26. package/data/component-props/InputSlider.json +56 -0
  27. package/data/component-props/InputText.json +95 -0
  28. package/data/component-props/InputToggle.json +72 -0
  29. package/data/component-props/List.json +43 -0
  30. package/data/component-props/LoadingIndicator.json +11 -0
  31. package/data/component-props/Menu.json +48 -0
  32. package/data/component-props/MenuItem.json +72 -0
  33. package/data/component-props/MenuSelect.json +83 -0
  34. package/data/component-props/NavigationFooter.json +50 -0
  35. package/data/component-props/NavigationHeader.json +119 -0
  36. package/data/component-props/NavigationJumpTo.json +58 -0
  37. package/data/component-props/Notification.json +89 -0
  38. package/data/component-props/Pagination.json +51 -0
  39. package/data/component-props/Panel.json +72 -0
  40. package/data/component-props/SegmentedControl.json +65 -0
  41. package/data/component-props/Table.json +26 -0
  42. package/data/component-props/TableRow.json +70 -0
  43. package/data/component-props/Tag.json +86 -0
  44. package/data/component-props/TagFilter.json +58 -0
  45. package/data/component-props/Tooltip.json +86 -0
  46. package/data/component-props/TooltipTable.json +22 -0
  47. package/data/component-props-storybook/Accordion-storybook.json +45 -0
  48. package/data/component-props-storybook/Alert-storybook.json +30 -0
  49. package/data/component-props-storybook/Autocomplete-storybook.json +67 -0
  50. package/data/component-props-storybook/Banner-storybook.json +78 -0
  51. package/data/component-props-storybook/Button-storybook.json +115 -0
  52. package/data/component-props-storybook/ButtonDropdown-storybook.json +73 -0
  53. package/data/component-props-storybook/ButtonIcon-storybook.json +60 -0
  54. package/data/component-props-storybook/ButtonToggle-storybook.json +68 -0
  55. package/data/component-props-storybook/Callout-storybook.json +90 -0
  56. package/data/component-props-storybook/CellBasic-storybook.json +138 -0
  57. package/data/component-props-storybook/CellComponent-storybook.json +48 -0
  58. package/data/component-props-storybook/CellHeader-storybook.json +71 -0
  59. package/data/component-props-storybook/Chip-storybook.json +26 -0
  60. package/data/component-props-storybook/ComplexFilter-storybook.json +60 -0
  61. package/data/component-props-storybook/ContentCard-storybook.json +175 -0
  62. package/data/component-props-storybook/Dialog-storybook.json +56 -0
  63. package/data/component-props-storybook/Dropdown-storybook.json +93 -0
  64. package/data/component-props-storybook/DropdownMenu-storybook.json +73 -0
  65. package/data/component-props-storybook/HeatmapChart-storybook.json +55 -0
  66. package/data/component-props-storybook/Icon-storybook.json +75 -0
  67. package/data/component-props-storybook/InputCheckbox-storybook.json +57 -0
  68. package/data/component-props-storybook/InputDropdown-storybook.json +80 -0
  69. package/data/component-props-storybook/InputRadio-storybook.json +56 -0
  70. package/data/component-props-storybook/InputSearch-storybook.json +55 -0
  71. package/data/component-props-storybook/InputSlider-storybook.json +55 -0
  72. package/data/component-props-storybook/InputText-storybook.json +59 -0
  73. package/data/component-props-storybook/InputToggle-storybook.json +42 -0
  74. package/data/component-props-storybook/Link-storybook.json +50 -0
  75. package/data/component-props-storybook/List-storybook.json +26 -0
  76. package/data/component-props-storybook/LoadingIndicator-storybook.json +34 -0
  77. package/data/component-props-storybook/Menu-storybook.json +26 -0
  78. package/data/component-props-storybook/MenuItem-storybook.json +74 -0
  79. package/data/component-props-storybook/MenuSelect-storybook.json +38 -0
  80. package/data/component-props-storybook/NavigationFooter-storybook.json +67 -0
  81. package/data/component-props-storybook/NavigationHeader-storybook.json +115 -0
  82. package/data/component-props-storybook/NavigationJumpTo-storybook.json +41 -0
  83. package/data/component-props-storybook/Notification-storybook.json +89 -0
  84. package/data/component-props-storybook/Pagination-storybook.json +50 -0
  85. package/data/component-props-storybook/Panel-storybook.json +52 -0
  86. package/data/component-props-storybook/SegmentedControl-storybook.json +30 -0
  87. package/data/component-props-storybook/Table-storybook.json +26 -0
  88. package/data/component-props-storybook/TableHeader-storybook.json +26 -0
  89. package/data/component-props-storybook/TableRow-storybook.json +62 -0
  90. package/data/component-props-storybook/Tabs-storybook.json +45 -0
  91. package/data/component-props-storybook/Tag-storybook.json +78 -0
  92. package/data/component-props-storybook/TagFilter-storybook.json +30 -0
  93. package/data/component-props-storybook/Tooltip-storybook.json +85 -0
  94. package/data/component-props-storybook/TooltipCondensed-storybook.json +38 -0
  95. package/data/component-props-storybook/TooltipTable-storybook.json +47 -0
  96. package/data/tailwind.json +3009 -0
  97. package/dist/stdio.js +357 -0
  98. package/package.json +66 -0
package/dist/stdio.js ADDED
@@ -0,0 +1,357 @@
1
+ #!/usr/bin/env node
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 from 'fs';
6
+ import path, { join } from 'path';
7
+ import { fileURLToPath } from 'url';
8
+ import { readFile } from 'fs/promises';
9
+
10
+ var server = new McpServer({
11
+ name: "sds-mcp",
12
+ version: "0.1.0",
13
+ capabilities: {
14
+ prompts: {},
15
+ resources: {},
16
+ tools: {}
17
+ }
18
+ });
19
+ var filename = fileURLToPath(import.meta.url);
20
+ var dirname = path.dirname(filename);
21
+ async function getAllComponentNames() {
22
+ try {
23
+ const possiblePaths = [
24
+ path.join(dirname, "../../data/component-list.json"),
25
+ // From src/lib in dev
26
+ path.join(dirname, "../data/component-list.json"),
27
+ // From dist in prod
28
+ path.join(process.cwd(), "data/component-list.json")
29
+ // From current working directory
30
+ ];
31
+ let dataPath = "";
32
+ for (const p of possiblePaths) {
33
+ if (fs.existsSync(p)) {
34
+ dataPath = p;
35
+ break;
36
+ }
37
+ }
38
+ if (!dataPath) {
39
+ throw new Error(
40
+ "Component list not found in any expected location. Please run 'yarn generate:components-list' first."
41
+ );
42
+ }
43
+ const fileContent = fs.readFileSync(dataPath, "utf-8");
44
+ const componentList = JSON.parse(fileContent);
45
+ return componentList;
46
+ } catch (error) {
47
+ throw new Error(
48
+ `Failed to load component list: ${error instanceof Error ? error.message : `Unknown error ${error}`}`
49
+ );
50
+ }
51
+ }
52
+ async function fetchComponentProps(component) {
53
+ try {
54
+ const propsPaths = [
55
+ path.join(dirname, `../../data/component-props/${component}.json`),
56
+ // From src/lib in dev
57
+ path.join(dirname, `../data/component-props/${component}.json`),
58
+ // From dist in prod
59
+ path.join(process.cwd(), `data/component-props/${component}.json`)
60
+ // From current working directory
61
+ ];
62
+ let propsPath = "";
63
+ for (const p of propsPaths) {
64
+ if (fs.existsSync(p)) {
65
+ propsPath = p;
66
+ break;
67
+ }
68
+ }
69
+ if (!propsPath) {
70
+ return {
71
+ [component]: {
72
+ message: "Props information not available for this component. Run 'yarn generate:component-props' to generate props data.",
73
+ props: {}
74
+ }
75
+ };
76
+ }
77
+ const fileContent = fs.readFileSync(propsPath, "utf-8");
78
+ return JSON.parse(fileContent);
79
+ } catch (error) {
80
+ throw new Error(
81
+ `Failed to load props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
82
+ );
83
+ }
84
+ }
85
+ async function fetchComponentPropsStorybook(component) {
86
+ try {
87
+ const propsPaths = [
88
+ path.join(
89
+ dirname,
90
+ `../../data/component-props-storybook/${component}-storybook.json`
91
+ ),
92
+ // From src/lib in dev
93
+ path.join(
94
+ dirname,
95
+ `../data/component-props-storybook/${component}-storybook.json`
96
+ ),
97
+ // From dist in prod
98
+ path.join(
99
+ process.cwd(),
100
+ `data/component-props-storybook/${component}-storybook.json`
101
+ )
102
+ // From current working directory
103
+ ];
104
+ let propsPath = "";
105
+ for (const p of propsPaths) {
106
+ if (fs.existsSync(p)) {
107
+ propsPath = p;
108
+ break;
109
+ }
110
+ }
111
+ if (!propsPath) {
112
+ return {
113
+ [component]: {
114
+ message: "Props information not available for this component. Run 'yarn generate:component-props' to generate props data.",
115
+ props: {}
116
+ }
117
+ };
118
+ }
119
+ const fileContent = fs.readFileSync(propsPath, "utf-8");
120
+ return JSON.parse(fileContent);
121
+ } catch (error) {
122
+ throw new Error(
123
+ `Failed to load props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
124
+ );
125
+ }
126
+ }
127
+
128
+ // src/tools/get-component-props.ts
129
+ var getComponentPropsTool = {
130
+ name: "get_component_props",
131
+ 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.",
132
+ async ctx() {
133
+ try {
134
+ const componentList = await getAllComponentNames();
135
+ return {
136
+ componentList: [
137
+ ...componentList.components,
138
+ ...componentList["data-viz"]
139
+ ]
140
+ };
141
+ } catch (error) {
142
+ throw new Error(
143
+ `Failed to initialize component props tool: ${error instanceof Error ? error.message : "Unknown error"}`
144
+ );
145
+ }
146
+ },
147
+ exec(server2, { ctx, name, description }) {
148
+ server2.tool(
149
+ name,
150
+ description,
151
+ {
152
+ component: z.enum(ctx.componentList).describe("The name of the SDS component to get properties for")
153
+ },
154
+ async ({ component }) => {
155
+ try {
156
+ const json = await fetchComponentProps(component);
157
+ return {
158
+ content: [
159
+ {
160
+ type: "text",
161
+ text: JSON.stringify(json)
162
+ }
163
+ ]
164
+ };
165
+ } catch (error) {
166
+ return {
167
+ content: [
168
+ {
169
+ type: "text",
170
+ text: `Failed to get component props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
171
+ }
172
+ ]
173
+ };
174
+ }
175
+ }
176
+ );
177
+ }
178
+ };
179
+
180
+ // src/tools/list-components.ts
181
+ var listComponentsTool = {
182
+ name: "list_components",
183
+ 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.",
184
+ async ctx() {
185
+ try {
186
+ const componentList = await getAllComponentNames();
187
+ return { componentList };
188
+ } catch (error) {
189
+ throw new Error(
190
+ `Failed to initialize list components tool: ${error instanceof Error ? error.message : "Unknown error"}`
191
+ );
192
+ }
193
+ },
194
+ exec(server2, { ctx, name, description }) {
195
+ server2.tool(name, description, {}, async () => {
196
+ return {
197
+ content: [
198
+ {
199
+ type: "text",
200
+ text: JSON.stringify(ctx.componentList, null, 2)
201
+ }
202
+ ]
203
+ };
204
+ });
205
+ }
206
+ };
207
+ var getComponentPropsStorybookTool = {
208
+ name: "get_component_props_storybook",
209
+ description: "Get detailed properties of a specific SDS component using Storybook analysis. Unlike the regular get-component-props tool, which uses TypeScript analysis, 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 from Storybook.",
210
+ async ctx() {
211
+ try {
212
+ const componentList = await getAllComponentNames();
213
+ return {
214
+ componentList: [
215
+ ...componentList.components,
216
+ ...componentList["data-viz"]
217
+ ]
218
+ };
219
+ } catch (error) {
220
+ throw new Error(
221
+ `Failed to initialize component props tool: ${error instanceof Error ? error.message : "Unknown error"}`
222
+ );
223
+ }
224
+ },
225
+ exec(server2, { ctx, name, description }) {
226
+ server2.tool(
227
+ name,
228
+ description,
229
+ {
230
+ component: z.enum(ctx.componentList).describe("The name of the SDS component to get properties for")
231
+ },
232
+ async ({ component }) => {
233
+ try {
234
+ const json = await fetchComponentPropsStorybook(component);
235
+ return {
236
+ content: [
237
+ {
238
+ type: "text",
239
+ text: JSON.stringify(json)
240
+ }
241
+ ]
242
+ };
243
+ } catch (error) {
244
+ return {
245
+ content: [
246
+ {
247
+ type: "text",
248
+ text: `Failed to get component props for ${component}: ${error instanceof Error ? error.message : "Unknown error"}`
249
+ }
250
+ ]
251
+ };
252
+ }
253
+ }
254
+ );
255
+ }
256
+ };
257
+ var getTailwindTokensTool = {
258
+ name: "get_tailwind_tokens",
259
+ description: "Get all available Tailwind tokens from the SDS design system. Returns design tokens including colors, typography, spacing, borders, shadows, and other design system values formatted for Tailwind CSS.",
260
+ async ctx() {
261
+ return {};
262
+ },
263
+ exec(server2, { name, description }) {
264
+ server2.tool(
265
+ name,
266
+ description,
267
+ {
268
+ category: z.enum([
269
+ "all",
270
+ "fontFamily",
271
+ "fontSize",
272
+ "fontVariantNumeric",
273
+ "letterSpacing",
274
+ "lineHeight",
275
+ "textDecoration",
276
+ "textTransform",
277
+ "typography",
278
+ "height",
279
+ "width",
280
+ "borderRadius",
281
+ "boxShadow",
282
+ "breakpoints",
283
+ "colors",
284
+ "spacing"
285
+ ]).optional().describe(
286
+ "Optional category of tokens to retrieve. If not specified, returns all tokens."
287
+ )
288
+ },
289
+ async ({ category }) => {
290
+ try {
291
+ const dataPath = join(process.cwd(), "data", "tailwind.json");
292
+ const fileContent = await readFile(dataPath, "utf-8");
293
+ const tokens = JSON.parse(fileContent);
294
+ let result = tokens;
295
+ if (category && category !== "all") {
296
+ result = tokens[category] || {};
297
+ }
298
+ return {
299
+ content: [
300
+ {
301
+ type: "text",
302
+ text: JSON.stringify(result, null, 2)
303
+ }
304
+ ]
305
+ };
306
+ } catch (error) {
307
+ return {
308
+ content: [
309
+ {
310
+ type: "text",
311
+ text: `Failed to get Tailwind tokens: ${error instanceof Error ? error.message : "Unknown error"}`
312
+ }
313
+ ]
314
+ };
315
+ }
316
+ }
317
+ );
318
+ }
319
+ };
320
+
321
+ // src/tools/index.ts
322
+ var tools = [
323
+ getComponentPropsTool,
324
+ getComponentPropsStorybookTool,
325
+ listComponentsTool,
326
+ getTailwindTokensTool
327
+ ];
328
+ var registeredToolCache = /* @__PURE__ */ new Map();
329
+ var initializeTools = async (server2, config) => {
330
+ const enabledTools = tools.filter((tool) => !tool.disabled?.(config));
331
+ await Promise.all(
332
+ enabledTools.map(async (tool) => {
333
+ const toolCtx = await tool.ctx?.();
334
+ if (registeredToolCache.has(tool.name)) {
335
+ return;
336
+ }
337
+ registeredToolCache.set(tool.name, tool);
338
+ tool.exec(server2, {
339
+ config,
340
+ ctx: toolCtx,
341
+ description: tool.description,
342
+ name: tool.name
343
+ });
344
+ })
345
+ );
346
+ };
347
+
348
+ // src/stdio.ts
349
+ async function main() {
350
+ await initializeTools(server, {});
351
+ const transport = new StdioServerTransport();
352
+ await server.connect(transport);
353
+ }
354
+ main().catch((error) => {
355
+ console.error("Fatal error in main():", error);
356
+ process.exit(1);
357
+ });
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@czi-sds/mcp",
3
+ "description": "The official MCP server for SDS",
4
+ "version": "0.2.0",
5
+ "main": "dist/stdio.js",
6
+ "files": [
7
+ "dist",
8
+ "data"
9
+ ],
10
+ "sideEffects": false,
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "author": "",
15
+ "homepage": "https://sds.czi.design",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/chanzuckerberg/sci-components",
19
+ "directory": "packages/mcp"
20
+ },
21
+ "scripts": {
22
+ "generate:tailwind-tokens": "mkdir -p data && cp ../components/src/common/styles-dictionary/json/tailwind.json data/tailwind.json && echo '✓ Copied tailwind.json to data folder'",
23
+ "generate:components-list": "tsx scripts/generate-component-list.ts",
24
+ "generate:component-props": "tsx scripts/generate-component-props.ts",
25
+ "generate:component-props-storybook": "tsx scripts/generate-component-props-from-storybook.ts",
26
+ "generate:all": "yarn generate:tailwind-tokens && yarn generate:components-list && yarn generate:component-props && yarn generate:component-props-storybook",
27
+ "prebuild": "yarn generate:all",
28
+ "build": "yarn prebuild && tsup && chmod 755 dist/stdio.js",
29
+ "dev": "tsup --watch",
30
+ "inspect": "node scripts/inspect.js",
31
+ "inspect:dev": "npx @modelcontextprotocol/inspector npx tsx src/stdio.ts",
32
+ "serve": "tsx --watch src/http.ts"
33
+ },
34
+ "bin": {
35
+ "sds-mcp": "./dist/stdio.js"
36
+ },
37
+ "keywords": [
38
+ "sds",
39
+ "mcp-server",
40
+ "chat",
41
+ "chatgpt",
42
+ "mcp"
43
+ ],
44
+ "type": "module",
45
+ "license": "MIT",
46
+ "config": {
47
+ "commitizen": {
48
+ "path": "./node_modules/cz-conventional-changelog"
49
+ }
50
+ },
51
+ "dependencies": {
52
+ "@modelcontextprotocol/sdk": "^1.15.0",
53
+ "express": "^5.1.0",
54
+ "zod": "^3.24.4"
55
+ },
56
+ "devDependencies": {
57
+ "@tsconfig/node22": "^22.0.1",
58
+ "@types/express": "^5.0.3",
59
+ "@types/fs-extra": "^11.0.4",
60
+ "react-docgen-typescript": "^2.4.0",
61
+ "tsup": "^8.5.0",
62
+ "tsx": "^4.20.3",
63
+ "typescript": "^5.9.2"
64
+ },
65
+ "gitHead": "f4621fab06e1ddad620b4952aefd5675318d4318"
66
+ }