@czi-sds/mcp 0.2.0 → 0.2.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/README.md +420 -15
- package/dist/stdio.js +331 -16
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,34 +1,439 @@
|
|
|
1
1
|
# SDS MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
examples, design tokens and migration patterns.
|
|
3
|
+
Welcome to the Science Design System (SDS) MCP Server! This guide will help you understand the architecture, create new tools, test your changes, and publish the server.
|
|
5
4
|
|
|
6
|
-
##
|
|
5
|
+
## Table of Contents
|
|
7
6
|
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
7
|
+
- [Architecture Overview](#architecture-overview)
|
|
8
|
+
- [Setting Up Development Environment](#setting-up-development-environment)
|
|
9
|
+
- [Creating a New Tool](#creating-a-new-tool)
|
|
10
|
+
- [Testing Your Changes](#testing-your-changes)
|
|
11
|
+
- [Publishing to NPM](#publishing-to-npm)
|
|
12
|
+
- [Real-World Testing](#real-world-testing)
|
|
13
|
+
- [Best Practices](#best-practices)
|
|
13
14
|
|
|
14
|
-
##
|
|
15
|
+
## Architecture Overview
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
- `get_component_props` - Get component properties and configuration
|
|
18
|
-
- `get_component_example` - Retrieve usage examples and code patterns
|
|
19
|
-
- `get_theme` - Get theme tokens, semantic tokens, text styles and layer styles
|
|
17
|
+
### Project Structure
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
```
|
|
20
|
+
packages/mcp/
|
|
21
|
+
├── src/
|
|
22
|
+
│ ├── tools/ # Tool implementations
|
|
23
|
+
│ │ ├── index.ts # Tool registry and initialization
|
|
24
|
+
│ │ └── *.ts # Individual tool files
|
|
25
|
+
│ ├── lib/
|
|
26
|
+
│ │ ├── types.ts # TypeScript type definitions
|
|
27
|
+
│ │ └── fetch.ts # Data fetching utilities
|
|
28
|
+
│ ├── server.ts # Core MCP server setup
|
|
29
|
+
│ ├── stdio.ts # STDIO transport implementation
|
|
30
|
+
│ └── http.ts # HTTP transport implementation
|
|
31
|
+
├── data/ # Static data files
|
|
32
|
+
│ ├── component-list.json
|
|
33
|
+
│ ├── component-props/
|
|
34
|
+
│ ├── component-props-storybook/
|
|
35
|
+
│ └── tailwind.json
|
|
36
|
+
├── scripts/ # Build and generation scripts
|
|
37
|
+
│ ├── generate-*.ts # Data generation scripts
|
|
38
|
+
│ └── inspect.js # Inspector helper
|
|
39
|
+
└── dist/ # Built output
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Core Concepts
|
|
43
|
+
|
|
44
|
+
#### 1. **MCP Server**
|
|
45
|
+
|
|
46
|
+
The Model Context Protocol (MCP) server provides tools to AI assistants for interacting with the SDS component library. It supports two transport methods:
|
|
47
|
+
|
|
48
|
+
- **STDIO**: For local CLI usage (primary method)
|
|
49
|
+
- **HTTP**: For web-based integrations
|
|
50
|
+
|
|
51
|
+
#### 2. **Tools**
|
|
52
|
+
|
|
53
|
+
Tools are functions that AI assistants can call to retrieve information or perform actions. Each tool:
|
|
54
|
+
|
|
55
|
+
- Has a unique name and description
|
|
56
|
+
- Defines input parameters using Zod schemas
|
|
57
|
+
- Returns structured data to the assistant
|
|
58
|
+
- Can have initialization context (`ctx`)
|
|
59
|
+
|
|
60
|
+
#### 3. **Data Layer**
|
|
61
|
+
|
|
62
|
+
The `data/` directory contains pre-generated JSON files with component information:
|
|
63
|
+
|
|
64
|
+
- Component lists and properties
|
|
65
|
+
- Storybook metadata
|
|
66
|
+
- Design tokens (Tailwind config)
|
|
67
|
+
|
|
68
|
+
## Setting Up Development Environment
|
|
69
|
+
|
|
70
|
+
### Prerequisites
|
|
71
|
+
|
|
72
|
+
1. Clone the repository:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/chanzuckerberg/sci-components.git
|
|
76
|
+
cd sci-components
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
2. Install/Use the correct NodeJs version
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
nvm use
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
3. Install dependencies:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
yarn install
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
4. Build packages (required for data generation):
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
yarn build
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
5. Navigate to the MCP package:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd packages/mcp
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Creating a New Tool
|
|
104
|
+
|
|
105
|
+
### Step 1: Create the Tool File
|
|
106
|
+
|
|
107
|
+
Create a new file in `src/tools/` (e.g., `src/tools/my-new-tool.ts`):
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { z } from "zod";
|
|
111
|
+
import { type Tool } from "../lib/types.js";
|
|
112
|
+
|
|
113
|
+
// Define the tool's context type (optional)
|
|
114
|
+
type MyToolContext = {
|
|
115
|
+
// Any data needed during initialization
|
|
116
|
+
availableOptions?: string[];
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export const myNewTool: Tool<MyToolContext> = {
|
|
120
|
+
name: "my_new_tool",
|
|
121
|
+
description: "Brief description of what this tool does for AI assistants",
|
|
122
|
+
|
|
123
|
+
// Optional: Initialize context data
|
|
124
|
+
async ctx() {
|
|
125
|
+
// Load any necessary data at startup
|
|
126
|
+
const availableOptions = await loadOptions();
|
|
127
|
+
return { availableOptions };
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
// Optional: Conditionally disable the tool
|
|
131
|
+
disabled(config) {
|
|
132
|
+
return config.someFeatureFlag === false;
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
// Register and implement the tool
|
|
136
|
+
exec(server, { ctx, name, description }) {
|
|
137
|
+
server.tool(
|
|
138
|
+
name,
|
|
139
|
+
description,
|
|
140
|
+
{
|
|
141
|
+
// Define input parameters using Zod
|
|
142
|
+
param1: z.string().describe("Description of param1"),
|
|
143
|
+
param2: z
|
|
144
|
+
.enum(["option1", "option2"])
|
|
145
|
+
.optional()
|
|
146
|
+
.describe("Optional parameter with enum values"),
|
|
147
|
+
},
|
|
148
|
+
async ({ param1, param2 }) => {
|
|
149
|
+
try {
|
|
150
|
+
// Tool implementation
|
|
151
|
+
const result = await processData(param1, param2);
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
content: [
|
|
155
|
+
{
|
|
156
|
+
type: "text",
|
|
157
|
+
text: JSON.stringify(result, null, 2),
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
};
|
|
161
|
+
} catch (error) {
|
|
162
|
+
return {
|
|
163
|
+
content: [
|
|
164
|
+
{
|
|
165
|
+
type: "text",
|
|
166
|
+
text: `Error: ${error instanceof Error ? error.message : "Unknown error"}`,
|
|
167
|
+
},
|
|
168
|
+
],
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Step 2: Register the Tool
|
|
178
|
+
|
|
179
|
+
Add your tool to `src/tools/index.ts`:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
import { myNewTool } from "./my-new-tool.ts";
|
|
183
|
+
|
|
184
|
+
const tools: Tool[] = [
|
|
185
|
+
getComponentPropsTool,
|
|
186
|
+
getComponentPropsStorybookTool,
|
|
187
|
+
listComponentsTool,
|
|
188
|
+
getTailwindTokensTool,
|
|
189
|
+
myNewTool, // Add your tool here
|
|
190
|
+
];
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Step 3: Add TypeScript Types (if needed)
|
|
194
|
+
|
|
195
|
+
If your tool requires custom types, add them to `src/lib/types.ts`:
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
export interface MyToolData {
|
|
199
|
+
// Define your data structure
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Step 4: Add Data Generation Script (if needed)
|
|
204
|
+
|
|
205
|
+
If your tool requires pre-generated data, create a script in `scripts/`:
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
// scripts/generate-my-data.ts
|
|
209
|
+
import { writeFileSync } from "fs";
|
|
210
|
+
import { join } from "path";
|
|
211
|
+
|
|
212
|
+
async function generateMyData() {
|
|
213
|
+
const data = await collectData();
|
|
214
|
+
|
|
215
|
+
const outputPath = join(process.cwd(), "data", "my-data.json");
|
|
216
|
+
writeFileSync(outputPath, JSON.stringify(data, null, 2));
|
|
217
|
+
|
|
218
|
+
console.log("✓ Generated my-data.json");
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
generateMyData().catch(console.error);
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Add the script to `package.json`:
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"scripts": {
|
|
229
|
+
"generate:my-data": "tsx scripts/generate-my-data.ts",
|
|
230
|
+
"generate:all": "... && yarn generate:my-data"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Testing Your Changes
|
|
236
|
+
|
|
237
|
+
### Using the MCP Inspector
|
|
238
|
+
|
|
239
|
+
The MCP Inspector provides an interactive UI for testing your tools:
|
|
240
|
+
|
|
241
|
+
1. **Start the inspector from monorepo root with your local server:**
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
yarn mcp:inspect:dev
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
You can also navigate to the MCP package directory first and then run the commands directly from there:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
cd packages/mcp
|
|
251
|
+
yarn inspect:dev
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
This will open a web interface where you can:
|
|
255
|
+
|
|
256
|
+
- See all available tools
|
|
257
|
+
- Test tool invocations with different parameters
|
|
258
|
+
- View responses in real-time
|
|
259
|
+
- Debug any issues
|
|
260
|
+
|
|
261
|
+
2. **Test your specific tool:**
|
|
22
262
|
|
|
23
|
-
|
|
263
|
+
- Click "Connect" in the left sidebar to connect to the MCP server.
|
|
264
|
+
- Click "List Tools" to view all available tools.
|
|
265
|
+
- Fill in the required parameters.
|
|
266
|
+
- Click "Run Tool" to execute it and view the response.
|
|
267
|
+
- Verify both the output format and the content.
|
|
268
|
+
|
|
269
|
+
### Manual Testing with the Built Server
|
|
270
|
+
|
|
271
|
+
1. **Build the server:**
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
cd packages/mcp
|
|
275
|
+
yarn build
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
2. **Run the inspector with the built version:**
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
cd packages/mcp
|
|
282
|
+
yarn inspect
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Publishing to NPM
|
|
286
|
+
|
|
287
|
+
### Pre-publish Checklist
|
|
288
|
+
|
|
289
|
+
Navigate to the MCP package directory first and then run the following commands:
|
|
290
|
+
|
|
291
|
+
1. **Ensure all data is generated:**
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
yarn generate:all
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
2. **Build the package:**
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
yarn build
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
3. **Test the built package:**
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
yarn inspect
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Publishing Process
|
|
310
|
+
|
|
311
|
+
The SDS monorepo uses Lerna for publishing. From the repository root:
|
|
312
|
+
|
|
313
|
+
1. **Commit all changes:**
|
|
314
|
+
|
|
315
|
+
```bash
|
|
316
|
+
git add .
|
|
317
|
+
git commit
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
2. **Push to main branch** (after PR approval):
|
|
321
|
+
|
|
322
|
+
```bash
|
|
323
|
+
git push origin main
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
3. **Publish via CI/CD:**
|
|
327
|
+
The automated workflow handles publishing when changes are pushed to the `prod` branch:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
# Sync prod with main
|
|
331
|
+
git checkout prod
|
|
332
|
+
git pull origin main
|
|
333
|
+
git push origin prod
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
## Real-World Testing
|
|
337
|
+
|
|
338
|
+
### Testing in Claude Desktop
|
|
339
|
+
|
|
340
|
+
1. **Configure Claude Desktop:**
|
|
341
|
+
|
|
342
|
+
Add to your Claude Desktop configuration file:
|
|
343
|
+
|
|
344
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
345
|
+
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
346
|
+
|
|
347
|
+
For local MCP testing, make sure the path to your sci-components project matches your setup.
|
|
348
|
+
|
|
349
|
+
```json
|
|
350
|
+
{
|
|
351
|
+
"mcpServers": {
|
|
352
|
+
"sds-mcp": {
|
|
353
|
+
"command": "node",
|
|
354
|
+
"args": ["/sci-components/packages/mcp/dist/stdio.js"]
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
To test the published version simply use npx to run the mcp server package:
|
|
24
361
|
|
|
25
362
|
```json
|
|
26
363
|
{
|
|
27
364
|
"mcpServers": {
|
|
28
365
|
"sds-mcp": {
|
|
366
|
+
"type": "stdio",
|
|
29
367
|
"command": "npx",
|
|
30
368
|
"args": ["-y", "@czi-sds/mcp"]
|
|
31
369
|
}
|
|
32
370
|
}
|
|
33
371
|
}
|
|
34
372
|
```
|
|
373
|
+
|
|
374
|
+
3. **Restart Claude Desktop** and test your tool in conversations
|
|
375
|
+
|
|
376
|
+
### Testing in Other MCP Clients
|
|
377
|
+
|
|
378
|
+
The server can be integrated with any MCP-compatible client:
|
|
379
|
+
|
|
380
|
+
1. **Via NPX (without installation):**
|
|
381
|
+
|
|
382
|
+
```json
|
|
383
|
+
{
|
|
384
|
+
"mcpServers": {
|
|
385
|
+
"sds-mcp": {
|
|
386
|
+
"type": "stdio",
|
|
387
|
+
"command": "npx",
|
|
388
|
+
"args": ["-y", "@czi-sds/mcp"]
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
```
|
|
393
|
+
|
|
394
|
+
## Best Practices
|
|
395
|
+
|
|
396
|
+
### Tool Design
|
|
397
|
+
|
|
398
|
+
1. **Clear Naming**: Use descriptive, snake_case names (e.g., `get_component_props`)
|
|
399
|
+
2. **Comprehensive Descriptions**: Help AI assistants understand when to use your tool
|
|
400
|
+
3. **Error Handling**: Always wrap async operations in try-catch blocks
|
|
401
|
+
4. **Structured Output**: Return consistent JSON structures
|
|
402
|
+
5. **Parameter Validation**: Use Zod schemas to validate inputs
|
|
403
|
+
|
|
404
|
+
### Performance
|
|
405
|
+
|
|
406
|
+
1. **Lazy Loading**: Load data only when needed using the `ctx()` function
|
|
407
|
+
2. **Caching**: Cache expensive operations in the tool context
|
|
408
|
+
3. **Data Size**: Keep responses under reasonable size limits
|
|
409
|
+
4. **Async Operations**: Use async/await for all I/O operations
|
|
410
|
+
|
|
411
|
+
## Common Issues and Solutions
|
|
412
|
+
|
|
413
|
+
### Issue: Tool not appearing in inspector
|
|
414
|
+
|
|
415
|
+
**Solution**: Ensure the tool is properly registered in `src/tools/index.ts` and rebuild
|
|
416
|
+
|
|
417
|
+
### Issue: Data files not found
|
|
418
|
+
|
|
419
|
+
**Solution**: Run `yarn generate:all` before building
|
|
420
|
+
|
|
421
|
+
### Issue: Permission denied when running built script
|
|
422
|
+
|
|
423
|
+
**Solution**: Run `chmod +x dist/stdio.js` after building
|
|
424
|
+
|
|
425
|
+
## Getting Help
|
|
426
|
+
|
|
427
|
+
- **GitHub Issues**: [Report bugs or request features](https://github.com/chanzuckerberg/sci-components/issues)
|
|
428
|
+
- **Design System Docs**: [sds.czi.design](https://sds.czi.design)
|
|
429
|
+
- **MCP Documentation**: [Model Context Protocol](https://modelcontextprotocol.io)
|
|
430
|
+
|
|
431
|
+
## Contributing Guidelines
|
|
432
|
+
|
|
433
|
+
1. Fork the repository
|
|
434
|
+
2. Create a feature branch (`git checkout -b feature/new-tool`)
|
|
435
|
+
3. Make your changes
|
|
436
|
+
4. Write/update tests if applicable
|
|
437
|
+
5. Submit a pull request
|
|
438
|
+
|
|
439
|
+
Thank you for contributing to the SDS MCP Server!
|
package/dist/stdio.js
CHANGED
|
@@ -3,9 +3,8 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
3
3
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import fs from 'fs';
|
|
6
|
-
import path
|
|
6
|
+
import path from 'path';
|
|
7
7
|
import { fileURLToPath } from 'url';
|
|
8
|
-
import { readFile } from 'fs/promises';
|
|
9
8
|
|
|
10
9
|
var server = new McpServer({
|
|
11
10
|
name: "sds-mcp",
|
|
@@ -124,6 +123,37 @@ async function fetchComponentPropsStorybook(component) {
|
|
|
124
123
|
);
|
|
125
124
|
}
|
|
126
125
|
}
|
|
126
|
+
async function fetchTailwindTokens() {
|
|
127
|
+
try {
|
|
128
|
+
const possiblePaths = [
|
|
129
|
+
path.join(dirname, "../../data/tailwind.json"),
|
|
130
|
+
// From src/lib in dev
|
|
131
|
+
path.join(dirname, "../data/tailwind.json"),
|
|
132
|
+
// From dist in prod
|
|
133
|
+
path.join(process.cwd(), "data/tailwind.json")
|
|
134
|
+
// From current working directory
|
|
135
|
+
];
|
|
136
|
+
let dataPath = "";
|
|
137
|
+
for (const p of possiblePaths) {
|
|
138
|
+
if (fs.existsSync(p)) {
|
|
139
|
+
dataPath = p;
|
|
140
|
+
break;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
if (!dataPath) {
|
|
144
|
+
throw new Error(
|
|
145
|
+
"Component list not found in any expected location. Please run 'yarn generate:tailwind-tokens' first."
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
const fileContent = fs.readFileSync(dataPath, "utf-8");
|
|
149
|
+
const tailwindTokens = JSON.parse(fileContent);
|
|
150
|
+
return tailwindTokens;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
throw new Error(
|
|
153
|
+
`Failed to load tailwind tokens: ${error instanceof Error ? error.message : `Unknown error ${error}`}`
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
127
157
|
|
|
128
158
|
// src/tools/get-component-props.ts
|
|
129
159
|
var getComponentPropsTool = {
|
|
@@ -254,13 +284,293 @@ var getComponentPropsStorybookTool = {
|
|
|
254
284
|
);
|
|
255
285
|
}
|
|
256
286
|
};
|
|
287
|
+
|
|
288
|
+
// src/lib/tailwind-guidance.ts
|
|
289
|
+
var TAILWIND_TOKEN_GUIDANCE = {
|
|
290
|
+
colors: {
|
|
291
|
+
category: "Colors",
|
|
292
|
+
description: "Theme-aware color tokens with light/dark mode support. Both light and dark mode colors are using the same token name. Use the dark:color-token-name to use the dark mode color.",
|
|
293
|
+
prefixes: [
|
|
294
|
+
"bg-",
|
|
295
|
+
"border-",
|
|
296
|
+
"divide-",
|
|
297
|
+
"outline-",
|
|
298
|
+
"ring-",
|
|
299
|
+
"ring-offset-",
|
|
300
|
+
"text-",
|
|
301
|
+
"placeholder-",
|
|
302
|
+
"caret-",
|
|
303
|
+
"decoration-",
|
|
304
|
+
"accent-",
|
|
305
|
+
"shadow-",
|
|
306
|
+
"fill-",
|
|
307
|
+
"stroke-",
|
|
308
|
+
"from-",
|
|
309
|
+
"via-",
|
|
310
|
+
"to-"
|
|
311
|
+
],
|
|
312
|
+
examples: [
|
|
313
|
+
{
|
|
314
|
+
description: "Basic text and background colors",
|
|
315
|
+
code: `<div className="bg-sds-color-semantic-base-background-primary dark:bg-sds-color-semantic-base-background-primary text-sds-color-semantic-base-text-primary dark:text-sds-color-semantic-base-text-primary">
|
|
316
|
+
Content with semantic colors
|
|
317
|
+
</div>`
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
description: "Dark mode with hover states",
|
|
321
|
+
code: `<button className="bg-sds-color-semantic-accent-fill-primary dark:bg-sds-color-semantic-accent-fill-primary
|
|
322
|
+
hover:bg-sds-color-semantic-accent-fill-hover dark:hover:bg-sds-color-semantic-accent-fill-hover">
|
|
323
|
+
Click me
|
|
324
|
+
</button>`
|
|
325
|
+
},
|
|
326
|
+
{
|
|
327
|
+
description: "Border and focus states",
|
|
328
|
+
code: `<input className="
|
|
329
|
+
border-sds-color-semantic-base-border-primary
|
|
330
|
+
hover:border-sds-color-semantic-base-border-primary-hover
|
|
331
|
+
focus:border-sds-color-semantic-base-border-primary-pressed
|
|
332
|
+
"/>`
|
|
333
|
+
}
|
|
334
|
+
],
|
|
335
|
+
tips: [
|
|
336
|
+
"Always use semantic colors (e.g., 'sds-color-semantic-base-background-primary') over primitive colors when possible",
|
|
337
|
+
"Include both light and dark variants for proper theme support"
|
|
338
|
+
]
|
|
339
|
+
},
|
|
340
|
+
typography: {
|
|
341
|
+
category: "Typography",
|
|
342
|
+
description: "Complete text styling presets including font, size, weight, and spacing",
|
|
343
|
+
prefixes: ["font-", "text-", "leading-", "tracking-"],
|
|
344
|
+
examples: [
|
|
345
|
+
{
|
|
346
|
+
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.",
|
|
347
|
+
code: `<!-- Use typography tokens for complete text styling -->
|
|
348
|
+
<h1 className="prose-sds-title-l-700-wide">Title</h1>
|
|
349
|
+
<h1 className="prose-sds-header-xl-600-wide">Heading</h1>
|
|
350
|
+
<p className="prose-sds-body-m-500-wide">Body text</p>
|
|
351
|
+
<span className="prose-sds-caps-xxs-600-wide">SMALL CAPS TEXT</span>
|
|
352
|
+
<span className="prose-sds-tabular-xxs-600-wide">Tabular Numbers</span>
|
|
353
|
+
<span className="prose-sds-code-s-500-wide">Code</span>
|
|
354
|
+
<span className="prose-sds-link-l-500-wide">Link style</span>`
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
description: "Individual typography properties",
|
|
358
|
+
code: `<!-- Or use individual properties when needed -->
|
|
359
|
+
<p className="
|
|
360
|
+
font-sds-body
|
|
361
|
+
text-sds-body-m-400-wide
|
|
362
|
+
leading-sds-body-m-400-wide
|
|
363
|
+
tracking-sds-body-m-400-wide
|
|
364
|
+
">
|
|
365
|
+
Custom styled text
|
|
366
|
+
</p>`
|
|
367
|
+
}
|
|
368
|
+
],
|
|
369
|
+
tips: [
|
|
370
|
+
"Use 'narrow' variants for mobile/compact layouts",
|
|
371
|
+
"Use 'wide' variants for desktop/spacious layouts",
|
|
372
|
+
"Font weights: 400 (regular), 500 (medium), 600 (semibold), 700 (bold)"
|
|
373
|
+
]
|
|
374
|
+
},
|
|
375
|
+
spacing: {
|
|
376
|
+
category: "Spacing",
|
|
377
|
+
description: "Consistent spacing scale for padding, margin, and gaps",
|
|
378
|
+
prefixes: [
|
|
379
|
+
"p-",
|
|
380
|
+
"px-",
|
|
381
|
+
"py-",
|
|
382
|
+
"pt-",
|
|
383
|
+
"pr-",
|
|
384
|
+
"pb-",
|
|
385
|
+
"pl-",
|
|
386
|
+
"m-",
|
|
387
|
+
"mx-",
|
|
388
|
+
"my-",
|
|
389
|
+
"mt-",
|
|
390
|
+
"mr-",
|
|
391
|
+
"mb-",
|
|
392
|
+
"ml-",
|
|
393
|
+
"gap-",
|
|
394
|
+
"gap-x-",
|
|
395
|
+
"gap-y-",
|
|
396
|
+
"space-x-",
|
|
397
|
+
"space-y-"
|
|
398
|
+
],
|
|
399
|
+
examples: [
|
|
400
|
+
{
|
|
401
|
+
description: "Padding and margin",
|
|
402
|
+
code: `<div className="p-sds-m mx-sds-l my-sds-s">
|
|
403
|
+
Content with medium padding and different margins
|
|
404
|
+
</div>`
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
description: "Flexbox and grid gaps",
|
|
408
|
+
code: `<div className="flex gap-sds-m">
|
|
409
|
+
<div>Item 1</div>
|
|
410
|
+
<div>Item 2</div>
|
|
411
|
+
</div>
|
|
412
|
+
|
|
413
|
+
<div className="grid grid-cols-3 gap-sds-l">
|
|
414
|
+
<div>Grid item</div>
|
|
415
|
+
</div>`
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
description: "Negative margins for overlapping",
|
|
419
|
+
code: `<div className="-mt-sds-s">
|
|
420
|
+
Overlapping element
|
|
421
|
+
</div>`
|
|
422
|
+
}
|
|
423
|
+
],
|
|
424
|
+
tips: [
|
|
425
|
+
"Scale: sds-s (small), sds-default (default), sds-m (medium), sds-l (large), sds-xl (extra large)",
|
|
426
|
+
"Use consistent spacing throughout your component",
|
|
427
|
+
"Combine with responsive prefixes: sm:p-sds-m lg:p-sds-l"
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
borderRadius: {
|
|
431
|
+
category: "Border Radius",
|
|
432
|
+
description: "Corner radius values for rounded elements",
|
|
433
|
+
prefixes: [
|
|
434
|
+
"rounded-",
|
|
435
|
+
"rounded-t-",
|
|
436
|
+
"rounded-r-",
|
|
437
|
+
"rounded-b-",
|
|
438
|
+
"rounded-l-"
|
|
439
|
+
],
|
|
440
|
+
examples: [
|
|
441
|
+
{
|
|
442
|
+
description: "Basic rounded corners",
|
|
443
|
+
code: `<div className="rounded-sds-default">
|
|
444
|
+
Standard rounded corners
|
|
445
|
+
</div>
|
|
446
|
+
|
|
447
|
+
<button className="rounded-sds-m">
|
|
448
|
+
More rounded button
|
|
449
|
+
</button>`
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
description: "Directional radius",
|
|
453
|
+
code: `<div className="rounded-t-sds-l rounded-b-none">
|
|
454
|
+
Only top corners rounded
|
|
455
|
+
</div>`
|
|
456
|
+
}
|
|
457
|
+
],
|
|
458
|
+
tips: [
|
|
459
|
+
"Use sds-default for most UI elements",
|
|
460
|
+
"Larger values (sds-l, sds-xl) for prominent elements",
|
|
461
|
+
"Combine with borders: border rounded-sds-m"
|
|
462
|
+
]
|
|
463
|
+
},
|
|
464
|
+
boxShadow: {
|
|
465
|
+
category: "Box Shadow",
|
|
466
|
+
description: "Elevation shadows for depth and hierarchy",
|
|
467
|
+
prefixes: ["shadow-", "hover:shadow-", "focus:shadow-"],
|
|
468
|
+
examples: [
|
|
469
|
+
{
|
|
470
|
+
description: "Basic shadows",
|
|
471
|
+
code: `<div className="shadow-sds-s">
|
|
472
|
+
Subtle shadow
|
|
473
|
+
</div>
|
|
474
|
+
|
|
475
|
+
<div className="shadow-sds-m">
|
|
476
|
+
Medium elevation
|
|
477
|
+
</div>`
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
description: "Interactive shadows",
|
|
481
|
+
code: `<button className="
|
|
482
|
+
shadow-sds-s
|
|
483
|
+
hover:shadow-sds-m
|
|
484
|
+
active:shadow-sds-xs
|
|
485
|
+
transition-shadow
|
|
486
|
+
">
|
|
487
|
+
Interactive element
|
|
488
|
+
</button>`
|
|
489
|
+
}
|
|
490
|
+
],
|
|
491
|
+
tips: [
|
|
492
|
+
"Use smaller shadows (sds-xs, sds-s) for subtle depth",
|
|
493
|
+
"Use larger shadows (sds-l, sds-xl) for modals and popovers",
|
|
494
|
+
"Combine with hover states for interactive feedback"
|
|
495
|
+
]
|
|
496
|
+
}
|
|
497
|
+
};
|
|
498
|
+
function getTokenGuidance(category) {
|
|
499
|
+
if (!category || category === "all") {
|
|
500
|
+
return `SDS Design System Tokens for Tailwind CSS
|
|
501
|
+
|
|
502
|
+
The Science Design System provides a comprehensive set of design tokens that map directly to Tailwind utilities.
|
|
503
|
+
|
|
504
|
+
QUICK START:
|
|
505
|
+
1. Request specific categories for detailed guidance: fontFamily, fontSize, fontVariantNumeric, letterSpacing, lineHeight, textDecoration, textTransform, typography, height, width, borderRadius, boxShadow, breakpoints, colors, spacing
|
|
506
|
+
2. Use semantic tokens over primitive ones when available
|
|
507
|
+
3. Include responsive and theme variants for robust implementations
|
|
508
|
+
4. Use the @czi-sds/components/dist/tailwind.json file to get the exact token name and value
|
|
509
|
+
5. To use the typography tokens, you need to add the @tailwindcss/typography plugin to your tailwind.config.js file and then use the typography tokens in your tailwind classes like prose-[typography-token-name] for example prose-sds-body-m-400-wide.
|
|
510
|
+
6. Colors have been defined in light and dark mode with the same name. Use the dark:color-token-name to use the dark mode color.
|
|
511
|
+
7. Use spacing tokens like sds-m for paddings, margins, etc. for example p-sds-m for padding-medium.
|
|
512
|
+
8. Use borderRadius tokens like sds-default for rounded corners for example rounded-sds-default.
|
|
513
|
+
9. Use boxShadow tokens like sds-s for subtle shadows for example shadow-sds-s.
|
|
514
|
+
10. Use breakpoints tokens like sds-m for medium breakpoints for example md:sds-m.
|
|
515
|
+
11. Use fontFamily tokens like sds-body for body font for example font-sds-body.
|
|
516
|
+
12. Use fontSize tokens like sds-body-m-400-wide for body font size for example text-sds-body-m-400-wide.
|
|
517
|
+
13. Use fontVariantNumeric tokens like sds-body-m-400-wide for body font variant numeric for example font-variant-numeric-sds-body-m-400-wide.
|
|
518
|
+
14. Use letterSpacing tokens like sds-body-m-400-wide for body letter spacing for example tracking-sds-body-m-400-wide.
|
|
519
|
+
|
|
520
|
+
For detailed examples, request a specific category.`;
|
|
521
|
+
}
|
|
522
|
+
const guidance = TAILWIND_TOKEN_GUIDANCE[category];
|
|
523
|
+
if (!guidance) {
|
|
524
|
+
return `Category "${category}" not found. Available categories: ${Object.keys(
|
|
525
|
+
TAILWIND_TOKEN_GUIDANCE
|
|
526
|
+
).join(", ")}`;
|
|
527
|
+
}
|
|
528
|
+
let output = `## ${guidance.category} Tokens
|
|
529
|
+
|
|
530
|
+
`;
|
|
531
|
+
output += `${guidance.description}
|
|
532
|
+
|
|
533
|
+
`;
|
|
534
|
+
output += `**Tailwind Prefixes:** ${guidance.prefixes.join(", ")}
|
|
535
|
+
|
|
536
|
+
`;
|
|
537
|
+
output += `### Examples:
|
|
538
|
+
|
|
539
|
+
`;
|
|
540
|
+
guidance.examples.forEach((example, index) => {
|
|
541
|
+
output += `${index + 1}. **${example.description}**
|
|
542
|
+
\`\`\`jsx
|
|
543
|
+
${example.code}
|
|
544
|
+
\`\`\`
|
|
545
|
+
|
|
546
|
+
`;
|
|
547
|
+
});
|
|
548
|
+
if (guidance.tips && guidance.tips.length > 0) {
|
|
549
|
+
output += `### Tips:
|
|
550
|
+
`;
|
|
551
|
+
guidance.tips.forEach((tip) => {
|
|
552
|
+
output += `- ${tip}
|
|
553
|
+
`;
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
return output;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
// src/tools/get-tailwind-tokens.ts
|
|
257
560
|
var getTailwindTokensTool = {
|
|
258
561
|
name: "get_tailwind_tokens",
|
|
259
|
-
description: "Get all available Tailwind tokens from the SDS design system.
|
|
562
|
+
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.",
|
|
260
563
|
async ctx() {
|
|
261
|
-
|
|
564
|
+
try {
|
|
565
|
+
const tailwindTokens = await fetchTailwindTokens();
|
|
566
|
+
return { tailwindTokens };
|
|
567
|
+
} catch (error) {
|
|
568
|
+
throw new Error(
|
|
569
|
+
`Failed to initialize tailwind tokens tool: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
570
|
+
);
|
|
571
|
+
}
|
|
262
572
|
},
|
|
263
|
-
exec(server2, { name, description }) {
|
|
573
|
+
exec(server2, { ctx, name, description }) {
|
|
264
574
|
server2.tool(
|
|
265
575
|
name,
|
|
266
576
|
description,
|
|
@@ -288,20 +598,25 @@ var getTailwindTokensTool = {
|
|
|
288
598
|
},
|
|
289
599
|
async ({ category }) => {
|
|
290
600
|
try {
|
|
291
|
-
const
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
601
|
+
const tokens = ctx.tailwindTokens;
|
|
602
|
+
let result;
|
|
603
|
+
if (!category || category === "all") {
|
|
604
|
+
result = tokens;
|
|
605
|
+
} else {
|
|
296
606
|
result = tokens[category] || {};
|
|
297
607
|
}
|
|
608
|
+
const responseContent = [];
|
|
609
|
+
const guidance = getTokenGuidance(category);
|
|
610
|
+
responseContent.push({
|
|
611
|
+
type: "text",
|
|
612
|
+
text: guidance
|
|
613
|
+
});
|
|
614
|
+
responseContent.push({
|
|
615
|
+
type: "text",
|
|
616
|
+
text: JSON.stringify(result, null, 2)
|
|
617
|
+
});
|
|
298
618
|
return {
|
|
299
|
-
content:
|
|
300
|
-
{
|
|
301
|
-
type: "text",
|
|
302
|
-
text: JSON.stringify(result, null, 2)
|
|
303
|
-
}
|
|
304
|
-
]
|
|
619
|
+
content: responseContent
|
|
305
620
|
};
|
|
306
621
|
} catch (error) {
|
|
307
622
|
return {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@czi-sds/mcp",
|
|
3
3
|
"description": "The official MCP server for SDS",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.2",
|
|
5
5
|
"main": "dist/stdio.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"tsx": "^4.20.3",
|
|
63
63
|
"typescript": "^5.9.2"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "34691ada3ef3cc877dcf1e2eef0f09efab53e668"
|
|
66
66
|
}
|