@atomixstudio/mcp 0.1.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/dist/index.js ADDED
@@ -0,0 +1,2974 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
5
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
6
+ import {
7
+ CallToolRequestSchema,
8
+ ListToolsRequestSchema,
9
+ ListResourcesRequestSchema,
10
+ ReadResourceRequestSchema
11
+ } from "@modelcontextprotocol/sdk/types.js";
12
+
13
+ // src/tokens.ts
14
+ import { fileURLToPath } from "url";
15
+ import { dirname, join } from "path";
16
+ var __filename = fileURLToPath(import.meta.url);
17
+ var __dirname = dirname(__filename);
18
+ var atomixPath = join(__dirname, "../../atomix/dist/index.mjs");
19
+ var loadedPrimitives = null;
20
+ async function loadPrimitives() {
21
+ if (loadedPrimitives) return loadedPrimitives;
22
+ try {
23
+ const module = await import(atomixPath);
24
+ loadedPrimitives = module.primitives;
25
+ return loadedPrimitives;
26
+ } catch (error) {
27
+ console.error(`Failed to load @atomix/tokens from ${atomixPath}:`, error);
28
+ console.error("Falling back to inline primitives...");
29
+ loadedPrimitives = FALLBACK_PRIMITIVES;
30
+ return FALLBACK_PRIMITIVES;
31
+ }
32
+ }
33
+ var primitives = {};
34
+ loadPrimitives().then((p) => {
35
+ primitives = p;
36
+ });
37
+ var TOKEN_CATEGORIES = [
38
+ "colors",
39
+ "typography",
40
+ "spacing",
41
+ "sizing",
42
+ "shadows",
43
+ "radius",
44
+ "motion",
45
+ "zIndex",
46
+ "borders"
47
+ ];
48
+ var FALLBACK_PRIMITIVES = {
49
+ colors: {
50
+ static: {
51
+ brand: {
52
+ primary: "#007061",
53
+ primaryLight: "#00A389",
54
+ primaryDark: "#005A4D",
55
+ primaryForeground: "#FFFFFF"
56
+ },
57
+ white: "#FFFFFF",
58
+ black: "#000000"
59
+ },
60
+ modes: {
61
+ light: {
62
+ bgPage: "#FFFFFF",
63
+ bgSurface: "#FFFFFF",
64
+ bgMuted: "#F5F5F5",
65
+ textPrimary: "#171717",
66
+ textSecondary: "#525252",
67
+ textMuted: "#A3A3A3",
68
+ // Icon colors (derived from brand/text)
69
+ iconBrand: "#007061",
70
+ // = brand.primary
71
+ iconStrong: "#171717",
72
+ // = textPrimary
73
+ iconSubtle: "#525252",
74
+ // = textSecondary
75
+ iconDisabled: "#A3A3A3",
76
+ // = textMuted
77
+ borderPrimary: "#E5E5E5"
78
+ },
79
+ dark: {
80
+ bgPage: "#0A0A0A",
81
+ bgSurface: "#1A1A1A",
82
+ bgMuted: "#262626",
83
+ textPrimary: "#FAFAFA",
84
+ textSecondary: "#A3A3A3",
85
+ textMuted: "#737373",
86
+ // Icon colors (derived from brand/text)
87
+ iconBrand: "#007061",
88
+ // = brand.primary
89
+ iconStrong: "#FAFAFA",
90
+ // = textPrimary
91
+ iconSubtle: "#A3A3A3",
92
+ // = textSecondary
93
+ iconDisabled: "#737373",
94
+ // = textMuted
95
+ borderPrimary: "#404040"
96
+ }
97
+ },
98
+ scales: {
99
+ green: {
100
+ 50: "#E6F5F2",
101
+ 500: "#007061",
102
+ 900: "#002E28"
103
+ }
104
+ }
105
+ },
106
+ typography: {
107
+ fontFamily: {
108
+ sans: "Inter, system-ui, sans-serif",
109
+ mono: "JetBrains Mono, monospace"
110
+ },
111
+ fontSize: {
112
+ xs: "0.75rem",
113
+ sm: "0.875rem",
114
+ md: "1rem",
115
+ lg: "1.125rem",
116
+ xl: "1.25rem"
117
+ },
118
+ fontWeight: {
119
+ regular: 400,
120
+ medium: 500,
121
+ semibold: 600,
122
+ bold: 700
123
+ },
124
+ lineHeight: {
125
+ tight: 1.25,
126
+ normal: 1.5,
127
+ relaxed: 1.625
128
+ }
129
+ },
130
+ spacing: {
131
+ scale: {
132
+ xs: "0.25rem",
133
+ sm: "0.5rem",
134
+ md: "1rem",
135
+ lg: "1.5rem",
136
+ xl: "2rem"
137
+ },
138
+ inset: {
139
+ xs: "0.25rem",
140
+ sm: "0.5rem",
141
+ md: "1rem",
142
+ lg: "1.5rem"
143
+ }
144
+ },
145
+ sizing: {
146
+ button: {
147
+ sm: { height: "32px" },
148
+ md: { height: "40px" },
149
+ lg: { height: "48px" }
150
+ }
151
+ },
152
+ shadows: {
153
+ elevation: {
154
+ none: "none",
155
+ sm: "0 1px 2px rgba(0, 0, 0, 0.05)",
156
+ md: "0 4px 6px rgba(0, 0, 0, 0.1)",
157
+ lg: "0 10px 15px rgba(0, 0, 0, 0.1)"
158
+ },
159
+ focus: {
160
+ ring: "0 0 0 2px var(--atomix-brand)"
161
+ }
162
+ },
163
+ radius: {
164
+ scale: {
165
+ none: "0",
166
+ sm: "0.25rem",
167
+ md: "0.5rem",
168
+ lg: "0.75rem",
169
+ xl: "1rem",
170
+ full: "9999px"
171
+ }
172
+ },
173
+ motion: {
174
+ duration: {
175
+ instant: "0ms",
176
+ fast: "150ms",
177
+ normal: "200ms",
178
+ slow: "300ms"
179
+ },
180
+ easing: {
181
+ ease: "cubic-bezier(0.4, 0, 0.2, 1)",
182
+ easeIn: "cubic-bezier(0.4, 0, 1, 1)",
183
+ easeOut: "cubic-bezier(0, 0, 0.2, 1)"
184
+ }
185
+ },
186
+ zIndex: {
187
+ dropdown: 1e3,
188
+ modal: 1100,
189
+ tooltip: 1200
190
+ },
191
+ borders: {
192
+ width: {
193
+ none: "0",
194
+ thin: "1px",
195
+ medium: "2px"
196
+ }
197
+ }
198
+ };
199
+
200
+ // src/utils.ts
201
+ function getTokenByPath(obj, path) {
202
+ const parts = path.split(".");
203
+ let current = obj;
204
+ for (const part of parts) {
205
+ if (current === null || current === void 0) return void 0;
206
+ if (typeof current !== "object") return void 0;
207
+ current = current[part];
208
+ }
209
+ return current;
210
+ }
211
+ function listTokensInCategory(primitives3, category, subcategory) {
212
+ let base = primitives3[category];
213
+ if (!base) return {};
214
+ if (subcategory) {
215
+ const subParts = subcategory.split(".");
216
+ for (const part of subParts) {
217
+ if (typeof base !== "object" || base === null) return {};
218
+ base = base[part];
219
+ }
220
+ }
221
+ if (typeof base !== "object" || base === null) {
222
+ return { [subcategory || category]: base };
223
+ }
224
+ return flattenTokens(base);
225
+ }
226
+ function flattenTokens(obj, prefix = "") {
227
+ const result = {};
228
+ for (const [key, value] of Object.entries(obj)) {
229
+ const path = prefix ? `${prefix}.${key}` : key;
230
+ if (value !== null && typeof value === "object" && !Array.isArray(value)) {
231
+ Object.assign(result, flattenTokens(value, path));
232
+ } else {
233
+ result[path] = value;
234
+ }
235
+ }
236
+ return result;
237
+ }
238
+ function getTokenCategories() {
239
+ return [...TOKEN_CATEGORIES];
240
+ }
241
+ function getCssVariableName(path) {
242
+ const dashPath = path.replace(/\./g, "-").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
243
+ return `--atomix-${dashPath}`;
244
+ }
245
+ function getTokenMetadata(path) {
246
+ if (path.match(/^colors\.scales\./)) {
247
+ return {
248
+ tier: "primitive",
249
+ mutable: false,
250
+ guidance: "Raw color palette. Use semantic colors (colors.modes.*) in components instead."
251
+ };
252
+ }
253
+ if (path.match(/^colors\.scales\.(black|white|green)Alpha\./)) {
254
+ return {
255
+ tier: "primitive",
256
+ mutable: false,
257
+ guidance: "Alpha transparency scale. Reference only for overlays/effects."
258
+ };
259
+ }
260
+ if (path.match(/^spacing\.scale\./)) {
261
+ return {
262
+ tier: "primitive",
263
+ mutable: false,
264
+ guidance: "Spacing scale values. Use semantic spacing keys (xs, sm, md, lg) in components."
265
+ };
266
+ }
267
+ if (path.match(/^spacing\.(inset|stack|inline|gap)\./)) {
268
+ return {
269
+ tier: "primitive",
270
+ mutable: false,
271
+ guidance: "Spacing presets derived from scale. Reference only."
272
+ };
273
+ }
274
+ if (path.match(/^typography\.(fontSize|fontWeight|lineHeight|lineHeightPx|letterSpacing|paragraphSpacing)\./)) {
275
+ return {
276
+ tier: "primitive",
277
+ mutable: false,
278
+ guidance: "Raw typography values. Use typeSets (title-lg, text-normal-regular) in components."
279
+ };
280
+ }
281
+ if (path.match(/^radius\.scale\./)) {
282
+ return {
283
+ tier: "primitive",
284
+ mutable: false,
285
+ guidance: "Border radius scale. Use semantic radius (radius.semantic.*) or scale keys in components."
286
+ };
287
+ }
288
+ if (path.match(/^borders\.width\./)) {
289
+ return {
290
+ tier: "primitive",
291
+ mutable: false,
292
+ guidance: "Border width scale. Use semantic border keys in components."
293
+ };
294
+ }
295
+ if (path.match(/^shadows\.elevation\./)) {
296
+ return {
297
+ tier: "primitive",
298
+ mutable: false,
299
+ guidance: "Elevation shadow values. Use elevation keys (sm, md, lg) in components."
300
+ };
301
+ }
302
+ if (path.match(/^motion\.(duration|easing)\./)) {
303
+ return {
304
+ tier: "primitive",
305
+ mutable: false,
306
+ guidance: "Motion primitives. Use semantic motion presets (motion.semantic.*) when available."
307
+ };
308
+ }
309
+ if (path.match(/^zIndex\.scale\./)) {
310
+ return {
311
+ tier: "primitive",
312
+ mutable: false,
313
+ guidance: "Z-index scale. Use semantic z-index (zIndex.semantic.*) in components."
314
+ };
315
+ }
316
+ if (path.match(/^sizing\./)) {
317
+ return {
318
+ tier: "primitive",
319
+ mutable: false,
320
+ guidance: "Component sizing values. Reference only for layout calculations."
321
+ };
322
+ }
323
+ if (path.match(/^colors\.modes\.(light|dark)\./)) {
324
+ return {
325
+ tier: "semantic",
326
+ mutable: true,
327
+ editVia: "designer",
328
+ guidance: "Semantic color for theming. Use this in components. Editable via Atomix Designer."
329
+ };
330
+ }
331
+ if (path.match(/^colors\.adaptive\./)) {
332
+ return {
333
+ tier: "semantic",
334
+ mutable: true,
335
+ editVia: "designer",
336
+ guidance: "Adaptive feedback color (error, warning, success, info). Use for validation states."
337
+ };
338
+ }
339
+ if (path.match(/^colors\.static\.brand/)) {
340
+ return {
341
+ tier: "semantic",
342
+ mutable: false,
343
+ // Brand colors are locked
344
+ guidance: "Brand identity color. Use for primary brand elements. Protected from modification."
345
+ };
346
+ }
347
+ if (path.match(/^colors\.static\.(white|black|transparent)/)) {
348
+ return {
349
+ tier: "primitive",
350
+ mutable: false,
351
+ guidance: "Static utility color. Use for absolute white/black when needed."
352
+ };
353
+ }
354
+ if (path.match(/^radius\.semantic\./)) {
355
+ return {
356
+ tier: "semantic",
357
+ mutable: true,
358
+ editVia: "designer",
359
+ guidance: "Semantic border radius for component types. Use this in component styling."
360
+ };
361
+ }
362
+ if (path.match(/^borders\.semantic\./)) {
363
+ return {
364
+ tier: "semantic",
365
+ mutable: true,
366
+ editVia: "designer",
367
+ guidance: "Semantic border width for component types. Use this in component styling."
368
+ };
369
+ }
370
+ if (path.match(/^motion\.semantic\./)) {
371
+ return {
372
+ tier: "semantic",
373
+ mutable: true,
374
+ editVia: "designer",
375
+ guidance: "Semantic animation preset. Use for consistent motion patterns."
376
+ };
377
+ }
378
+ if (path.match(/^zIndex\.semantic\./)) {
379
+ return {
380
+ tier: "semantic",
381
+ mutable: true,
382
+ editVia: "designer",
383
+ guidance: "Semantic z-index for UI layers. Use for proper stacking order."
384
+ };
385
+ }
386
+ if (path.match(/^shadows\.focus\./)) {
387
+ return {
388
+ tier: "semantic",
389
+ mutable: true,
390
+ editVia: "designer",
391
+ guidance: "Focus ring styles for accessibility. Use for keyboard focus indicators."
392
+ };
393
+ }
394
+ if (path.match(/^typography\.typeSets\./)) {
395
+ return {
396
+ tier: "semantic",
397
+ mutable: true,
398
+ editVia: "designer",
399
+ guidance: "Composed typography style. Use these for consistent text styling."
400
+ };
401
+ }
402
+ if (path.match(/^typography\.fontFamily\./)) {
403
+ return {
404
+ tier: "semantic",
405
+ mutable: true,
406
+ editVia: "designer",
407
+ guidance: "Font family selection. Use 'sans', 'mono', or 'display' keys."
408
+ };
409
+ }
410
+ if (path.match(/^typography\.textStyles\./)) {
411
+ return {
412
+ tier: "semantic",
413
+ mutable: true,
414
+ editVia: "designer",
415
+ guidance: "Complete text style definition. Use for consistent typography."
416
+ };
417
+ }
418
+ return {
419
+ tier: "primitive",
420
+ mutable: false,
421
+ guidance: "Token classification unknown. Treat as read-only reference."
422
+ };
423
+ }
424
+
425
+ // src/component-tokens.ts
426
+ var COMPONENT_TOKENS = {
427
+ "button": {
428
+ "description": "Interactive button component with multiple variants and sizes",
429
+ "sizes": {
430
+ "sm": {
431
+ "tokens": {
432
+ "top": "xs",
433
+ "right": "sm",
434
+ "bottom": "xs",
435
+ "left": "sm",
436
+ "borderRadius": "radius.scale.lg",
437
+ "typeSet": "typography.typeSets.text-small-bold"
438
+ }
439
+ },
440
+ "padding": {
441
+ "tokens": {
442
+ "top": "xs",
443
+ "right": "sm",
444
+ "bottom": "xs",
445
+ "left": "sm",
446
+ "borderRadius": "radius.scale.lg",
447
+ "typeSet": "typography.typeSets.text-small-bold"
448
+ }
449
+ },
450
+ "md": {
451
+ "tokens": {
452
+ "top": "sm",
453
+ "right": "lg",
454
+ "bottom": "sm",
455
+ "left": "lg",
456
+ "borderRadius": "radius.scale.4xl",
457
+ "typeSet": "typography.typeSets.text-normal-bold"
458
+ }
459
+ },
460
+ "lg": {
461
+ "tokens": {
462
+ "top": "sm",
463
+ "right": "lg",
464
+ "bottom": "sm",
465
+ "left": "lg",
466
+ "borderRadius": "radius.scale.4xl",
467
+ "typeSet": "typography.typeSets.text-large-bold"
468
+ }
469
+ }
470
+ }
471
+ },
472
+ "card": {
473
+ "description": "Container component for grouping related content",
474
+ "variants": {
475
+ "default": {
476
+ "description": "default variant",
477
+ "tokens": {
478
+ "background": "colors.modes.{mode}.bgSurface",
479
+ "borderColor": "colors.modes.{mode}.borderStrong",
480
+ "borderWidth": "sm",
481
+ "borderRadius": "xl",
482
+ "shadow": "none",
483
+ "titleColor": "colors.modes.{mode}.textPrimary",
484
+ "bodyColor": "colors.modes.{mode}.textSecondary",
485
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
486
+ "interaction": "elevation",
487
+ "hoverShadow": "elevation-lg",
488
+ "hoverTranslateY": "-2px",
489
+ "hoverBorderColor": "colors.modes.{mode}.borderStrong"
490
+ }
491
+ },
492
+ "elevated": {
493
+ "description": "elevated variant",
494
+ "tokens": {
495
+ "background": "colors.modes.{mode}.bgSurface",
496
+ "borderColor": "colors.modes.{mode}.borderPrimary",
497
+ "borderWidth": "sm",
498
+ "borderRadius": "2xl",
499
+ "shadow": "elevation-md",
500
+ "titleColor": "colors.modes.{mode}.textPrimary",
501
+ "bodyColor": "colors.modes.{mode}.textSecondary",
502
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
503
+ "interaction": "elevation",
504
+ "hoverShadow": "elevation-lg",
505
+ "hoverTranslateY": "-2px",
506
+ "hoverBorderColor": "transparent"
507
+ }
508
+ },
509
+ "outlined": {
510
+ "description": "outlined variant",
511
+ "tokens": {
512
+ "background": "transparent",
513
+ "borderColor": "colors.modes.{mode}.borderSecondary",
514
+ "borderWidth": "lg",
515
+ "borderRadius": "2xl",
516
+ "shadow": "none",
517
+ "titleColor": "colors.modes.{mode}.textPrimary",
518
+ "bodyColor": "colors.modes.{mode}.textSecondary",
519
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
520
+ "interaction": "border",
521
+ "hoverShadow": "none",
522
+ "hoverTranslateY": "0",
523
+ "hoverBorderColor": "colors.modes.{mode}.borderStrong"
524
+ }
525
+ },
526
+ "ghost": {
527
+ "description": "ghost variant",
528
+ "tokens": {
529
+ "background": "transparent",
530
+ "borderColor": "transparent",
531
+ "borderWidth": "none",
532
+ "borderRadius": "xl",
533
+ "shadow": "none",
534
+ "titleColor": "colors.modes.{mode}.textPrimary",
535
+ "bodyColor": "colors.modes.{mode}.textMuted",
536
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
537
+ "interaction": "none",
538
+ "hoverShadow": "none",
539
+ "hoverTranslateY": "0",
540
+ "hoverBorderColor": "transparent"
541
+ }
542
+ }
543
+ },
544
+ "sizes": {
545
+ "sm": {
546
+ "tokens": {
547
+ "top": "lg",
548
+ "right": "xl",
549
+ "bottom": "lg",
550
+ "left": "xl",
551
+ "headingSize": "sm"
552
+ }
553
+ },
554
+ "padding": {
555
+ "tokens": {
556
+ "top": "lg",
557
+ "right": "xl",
558
+ "bottom": "lg",
559
+ "left": "xl",
560
+ "headingSize": "sm"
561
+ }
562
+ },
563
+ "md": {
564
+ "tokens": {
565
+ "top": "xl",
566
+ "right": "2xl",
567
+ "bottom": "xl",
568
+ "left": "2xl",
569
+ "headingSize": "md"
570
+ }
571
+ },
572
+ "lg": {
573
+ "tokens": {
574
+ "top": "2xl",
575
+ "right": "3xl",
576
+ "bottom": "2xl",
577
+ "left": "3xl",
578
+ "headingSize": "lg"
579
+ }
580
+ }
581
+ },
582
+ "shared": {
583
+ "titleFontFamily": "typography.fontFamily.sans",
584
+ "bodyFontFamily": "typography.fontFamily.sans"
585
+ }
586
+ },
587
+ "input": {
588
+ "description": "Text input field component with validation states",
589
+ "variants": {
590
+ "default": {
591
+ "description": "default variant",
592
+ "tokens": {
593
+ "borderWidth": "sm",
594
+ "borderColor": "colors.modes.{mode}.borderPrimary",
595
+ "borderColorFocus": "colors.modes.{mode}.borderStrong",
596
+ "helperTextColor": "colors.modes.{mode}.textMuted"
597
+ }
598
+ },
599
+ "error": {
600
+ "description": "error variant",
601
+ "tokens": {
602
+ "borderWidth": "md",
603
+ "borderColor": "colors.adaptive.error.{mode}.border",
604
+ "borderColorFocus": "colors.adaptive.error.{mode}.border",
605
+ "helperTextColor": "colors.adaptive.error.{mode}.text"
606
+ }
607
+ },
608
+ "success": {
609
+ "description": "success variant",
610
+ "tokens": {
611
+ "borderWidth": "md",
612
+ "borderColor": "colors.modes.{mode}.ring",
613
+ "borderColorFocus": "colors.modes.{mode}.ring",
614
+ "helperTextColor": "colors.adaptive.success.{mode}.text"
615
+ }
616
+ }
617
+ },
618
+ "sizes": {
619
+ "sm": {
620
+ "tokens": {
621
+ "fieldHeight": "32px",
622
+ "helperTypeSet": "helper-text",
623
+ "borderRadius": "radius.scale.lg",
624
+ "top": "xs",
625
+ "right": "md",
626
+ "bottom": "xs",
627
+ "left": "md"
628
+ }
629
+ },
630
+ "padding": {
631
+ "tokens": {
632
+ "top": "xs",
633
+ "right": "md",
634
+ "bottom": "xs",
635
+ "left": "md"
636
+ }
637
+ },
638
+ "md": {
639
+ "tokens": {
640
+ "fieldHeight": "40px",
641
+ "helperTypeSet": "helper-text",
642
+ "borderRadius": "radius.scale.xl",
643
+ "top": "sm",
644
+ "right": "md",
645
+ "bottom": "sm",
646
+ "left": "md"
647
+ }
648
+ },
649
+ "lg": {
650
+ "tokens": {
651
+ "fieldHeight": "48px",
652
+ "helperTypeSet": "helper-text",
653
+ "borderRadius": "radius.scale.2xl",
654
+ "top": "xl",
655
+ "right": "lg",
656
+ "bottom": "xl",
657
+ "left": "lg"
658
+ }
659
+ }
660
+ }
661
+ },
662
+ "select": {
663
+ "description": "Unified text field component supporting input, select, and textarea",
664
+ "variants": {
665
+ "default": {
666
+ "description": "default variant",
667
+ "tokens": {
668
+ "borderWidth": "md",
669
+ "borderColor": "colors.modes.{mode}.borderPrimary",
670
+ "borderColorFocus": "colors.modes.{mode}.borderSecondary",
671
+ "helperTextColor": "colors.modes.{mode}.textMuted"
672
+ }
673
+ },
674
+ "error": {
675
+ "description": "error variant",
676
+ "tokens": {
677
+ "borderWidth": "md",
678
+ "borderColor": "colors.adaptive.error.{mode}.border",
679
+ "borderColorFocus": "colors.adaptive.error.{mode}.border",
680
+ "helperTextColor": "colors.adaptive.error.{mode}.text"
681
+ }
682
+ },
683
+ "success": {
684
+ "description": "success variant",
685
+ "tokens": {
686
+ "borderWidth": "md",
687
+ "borderColor": "colors.modes.{mode}.ring",
688
+ "borderColorFocus": "colors.modes.{mode}.ring",
689
+ "helperTextColor": "colors.adaptive.success.{mode}.text"
690
+ }
691
+ },
692
+ "disabled": {
693
+ "description": "disabled variant",
694
+ "tokens": {
695
+ "borderWidth": "sm",
696
+ "borderColor": "colors.modes.{mode}.borderSecondary",
697
+ "borderColorFocus": "colors.modes.{mode}.borderSecondary",
698
+ "helperTextColor": "colors.modes.{mode}.textDisabled"
699
+ }
700
+ }
701
+ },
702
+ "sizes": {
703
+ "sm": {
704
+ "tokens": {
705
+ "fieldHeight": "32px",
706
+ "helperTypeSet": "helper-text",
707
+ "borderRadius": "radius.scale.lg",
708
+ "top": "xs",
709
+ "right": "md",
710
+ "bottom": "xs",
711
+ "left": "md"
712
+ }
713
+ },
714
+ "padding": {
715
+ "tokens": {
716
+ "top": "xs",
717
+ "right": "md",
718
+ "bottom": "xs",
719
+ "left": "md"
720
+ }
721
+ },
722
+ "md": {
723
+ "tokens": {
724
+ "fieldHeight": "44px",
725
+ "helperTypeSet": "helper-text",
726
+ "borderRadius": "none",
727
+ "top": "sm",
728
+ "right": "md",
729
+ "bottom": "sm",
730
+ "left": "md"
731
+ }
732
+ },
733
+ "lg": {
734
+ "tokens": {
735
+ "fieldHeight": "48px",
736
+ "helperTypeSet": "helper-text",
737
+ "borderRadius": "radius.scale.2xl",
738
+ "top": "xl",
739
+ "right": "lg",
740
+ "bottom": "xl",
741
+ "left": "lg"
742
+ }
743
+ }
744
+ }
745
+ },
746
+ "dialog": {
747
+ "description": "Modal dialog for focused interactions",
748
+ "variants": {
749
+ "default": {
750
+ "description": "default variant",
751
+ "tokens": {
752
+ "titleColor": "colors.modes.{mode}.textPrimary",
753
+ "bodyColor": "colors.modes.{mode}.textSecondary",
754
+ "contentAlign": "center",
755
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
756
+ "buttonAlign": "center"
757
+ }
758
+ },
759
+ "with-footer": {
760
+ "description": "with-footer variant",
761
+ "tokens": {
762
+ "titleColor": "colors.modes.{mode}.textPrimary",
763
+ "bodyColor": "colors.modes.{mode}.textSecondary",
764
+ "contentAlign": "left",
765
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
766
+ "buttonAlign": "space-between"
767
+ }
768
+ },
769
+ "minimal": {
770
+ "description": "minimal variant",
771
+ "tokens": {
772
+ "titleColor": "colors.modes.{mode}.textPrimary",
773
+ "bodyColor": "colors.modes.{mode}.textMuted",
774
+ "contentAlign": "center",
775
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
776
+ "buttonAlign": "center"
777
+ }
778
+ }
779
+ },
780
+ "sizes": {
781
+ "sm": {
782
+ "tokens": {
783
+ "headingSize": "sm",
784
+ "top": "xl",
785
+ "right": "xl",
786
+ "bottom": "xl",
787
+ "left": "xl",
788
+ "buttonSize": "sm"
789
+ }
790
+ },
791
+ "padding": {
792
+ "tokens": {
793
+ "top": "xl",
794
+ "right": "xl",
795
+ "bottom": "xl",
796
+ "left": "xl",
797
+ "buttonSize": "sm"
798
+ }
799
+ },
800
+ "md": {
801
+ "tokens": {
802
+ "headingSize": "md",
803
+ "top": "xl",
804
+ "right": "xl",
805
+ "bottom": "xl",
806
+ "left": "xl",
807
+ "buttonSize": "md"
808
+ }
809
+ },
810
+ "lg": {
811
+ "tokens": {
812
+ "headingSize": "lg",
813
+ "top": "xl",
814
+ "right": "xl",
815
+ "bottom": "xl",
816
+ "left": "xl",
817
+ "buttonSize": "lg"
818
+ }
819
+ }
820
+ },
821
+ "shared": {
822
+ "titleFontFamily": "typography.fontFamily.sans",
823
+ "bodyFontFamily": "typography.fontFamily.sans"
824
+ }
825
+ },
826
+ "heading": {
827
+ "description": "Typography component for titles, descriptions, and eyebrows",
828
+ "variants": {
829
+ "title-only": {
830
+ "description": "title-only variant",
831
+ "tokens": {
832
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
833
+ "titleColor": "colors.modes.{mode}.textPrimary",
834
+ "descriptionColor": "colors.modes.{mode}.textSecondary",
835
+ "textAlign": "left",
836
+ "eyebrowGap": "xs",
837
+ "descriptionGap": "sm",
838
+ "footerGap": "sm"
839
+ }
840
+ },
841
+ "title-description": {
842
+ "description": "title-description variant",
843
+ "tokens": {
844
+ "eyebrowColor": "colors.modes.{mode}.textMuted",
845
+ "titleColor": "colors.modes.{mode}.textPrimary",
846
+ "descriptionColor": "colors.modes.{mode}.textSecondary",
847
+ "textAlign": "left",
848
+ "eyebrowGap": "xs",
849
+ "descriptionGap": "xs",
850
+ "footerGap": "sm"
851
+ }
852
+ },
853
+ "full": {
854
+ "description": "full variant",
855
+ "tokens": {
856
+ "eyebrowColor": "colors.modes.{mode}.textSecondary",
857
+ "titleColor": "colors.modes.{mode}.textPrimary",
858
+ "descriptionColor": "colors.modes.{mode}.textSecondary",
859
+ "textAlign": "left",
860
+ "eyebrowGap": "xs",
861
+ "descriptionGap": "xs",
862
+ "footerGap": "sm"
863
+ }
864
+ }
865
+ },
866
+ "sizes": {
867
+ "sm": {
868
+ "tokens": {
869
+ "eyebrowTypeSet": "typography.typeSets.title-sm",
870
+ "titleTypeSet": "typography.typeSets.title-md",
871
+ "descriptionTypeSet": "typography.typeSets.text-normal-regular"
872
+ }
873
+ },
874
+ "md": {
875
+ "tokens": {
876
+ "eyebrowTypeSet": "typography.typeSets.title-sm",
877
+ "titleTypeSet": "typography.typeSets.title-lg",
878
+ "descriptionTypeSet": "typography.typeSets.text-normal-regular"
879
+ }
880
+ },
881
+ "lg": {
882
+ "tokens": {
883
+ "eyebrowTypeSet": "typography.typeSets.title-sm",
884
+ "titleTypeSet": "typography.typeSets.title-2xl",
885
+ "descriptionTypeSet": "typography.typeSets.text-normal-regular"
886
+ }
887
+ }
888
+ },
889
+ "shared": {
890
+ "fontFamily": "typography.fontFamily.sans"
891
+ }
892
+ },
893
+ "selectionControls": {
894
+ "description": "Selection control components: checkbox, radio, and toggle switch",
895
+ "variants": {
896
+ "checkbox": {
897
+ "description": "checkbox variant",
898
+ "tokens": {
899
+ "background": "colors.modes.{mode}.bgMuted",
900
+ "backgroundChecked": "colors.modes.{mode}.actionPrimary",
901
+ "backgroundDisabled": "colors.modes.{mode}.actionSecondary",
902
+ "backgroundError": "colors.modes.{mode}.bgMuted",
903
+ "borderWidth": "md",
904
+ "borderWidthError": "md",
905
+ "borderWidthDisabled": "md",
906
+ "borderColor": "colors.modes.{mode}.borderStrong",
907
+ "borderColorChecked": "transparent",
908
+ "borderColorDisabled": "colors.modes.{mode}.borderSecondary",
909
+ "borderColorError": "colors.adaptive.error.{mode}.border",
910
+ "indicatorColor": "colors.static.white",
911
+ "labelColor": "colors.modes.{mode}.textPrimary",
912
+ "interaction": "subtle"
913
+ }
914
+ },
915
+ "radio": {
916
+ "description": "radio variant",
917
+ "tokens": {
918
+ "background": "colors.modes.{mode}.bgMuted",
919
+ "backgroundChecked": "colors.modes.{mode}.actionPrimary",
920
+ "backgroundDisabled": "colors.modes.{mode}.actionSecondary",
921
+ "backgroundError": "colors.modes.{mode}.bgMuted",
922
+ "borderWidth": "md",
923
+ "borderWidthError": "md",
924
+ "borderWidthDisabled": "md",
925
+ "borderColor": "colors.modes.{mode}.borderStrong",
926
+ "borderColorChecked": "transparent",
927
+ "borderColorDisabled": "colors.modes.{mode}.borderSecondary",
928
+ "borderColorError": "colors.adaptive.error.{mode}.border",
929
+ "indicatorColor": "colors.static.white",
930
+ "labelColor": "colors.modes.{mode}.textPrimary",
931
+ "interaction": "subtle"
932
+ }
933
+ },
934
+ "toggle": {
935
+ "description": "toggle variant",
936
+ "tokens": {
937
+ "background": "colors.modes.{mode}.bgMuted",
938
+ "backgroundChecked": "colors.modes.{mode}.actionPrimary",
939
+ "backgroundDisabled": "colors.modes.{mode}.actionSecondary",
940
+ "backgroundError": "colors.modes.{mode}.bgMuted",
941
+ "borderWidth": "md",
942
+ "borderWidthError": "md",
943
+ "borderWidthDisabled": "md",
944
+ "borderColor": "colors.modes.{mode}.borderStrong",
945
+ "borderColorChecked": "transparent",
946
+ "borderColorDisabled": "colors.modes.{mode}.borderSecondary",
947
+ "borderColorError": "colors.adaptive.error.{mode}.border",
948
+ "indicatorColor": "colors.static.white",
949
+ "labelColor": "colors.modes.{mode}.textPrimary",
950
+ "interaction": "press"
951
+ }
952
+ }
953
+ },
954
+ "sizes": {
955
+ "md": {
956
+ "tokens": {
957
+ "controlSize": "20px",
958
+ "labelTypeSet": "typography.typeSets.text-normal-regular",
959
+ "gap": "spacing.scale.sm",
960
+ "borderRadius": "radius.scale.lg"
961
+ }
962
+ }
963
+ }
964
+ },
965
+ "checkbox": {
966
+ "description": "Checkbox selection control",
967
+ "variants": {
968
+ "default": {
969
+ "description": "checkbox variant",
970
+ "tokens": {
971
+ "background": "colors.modes.{mode}.bgMuted",
972
+ "backgroundChecked": "colors.modes.{mode}.actionPrimary",
973
+ "backgroundDisabled": "colors.modes.{mode}.actionSecondary",
974
+ "backgroundError": "colors.modes.{mode}.bgMuted",
975
+ "borderWidth": "md",
976
+ "borderWidthError": "md",
977
+ "borderWidthDisabled": "md",
978
+ "borderColor": "colors.modes.{mode}.borderStrong",
979
+ "borderColorChecked": "transparent",
980
+ "borderColorDisabled": "colors.modes.{mode}.borderSecondary",
981
+ "borderColorError": "colors.adaptive.error.{mode}.border",
982
+ "indicatorColor": "colors.static.white",
983
+ "labelColor": "colors.modes.{mode}.textPrimary",
984
+ "interaction": "subtle"
985
+ }
986
+ }
987
+ },
988
+ "sizes": {
989
+ "md": {
990
+ "tokens": {
991
+ "controlSize": "20px",
992
+ "labelTypeSet": "typography.typeSets.text-normal-regular",
993
+ "gap": "spacing.scale.sm",
994
+ "borderRadius": "radius.scale.lg"
995
+ }
996
+ }
997
+ },
998
+ "shared": {
999
+ "transitionDuration": "motion.duration.fast",
1000
+ "focusRing": "shadows.focus.ring"
1001
+ }
1002
+ },
1003
+ "radio": {
1004
+ "description": "Radio selection control",
1005
+ "variants": {
1006
+ "default": {
1007
+ "description": "radio variant",
1008
+ "tokens": {
1009
+ "background": "colors.modes.{mode}.bgMuted",
1010
+ "backgroundChecked": "colors.modes.{mode}.actionPrimary",
1011
+ "backgroundDisabled": "colors.modes.{mode}.actionSecondary",
1012
+ "backgroundError": "colors.modes.{mode}.bgMuted",
1013
+ "borderWidth": "md",
1014
+ "borderWidthError": "md",
1015
+ "borderWidthDisabled": "md",
1016
+ "borderColor": "colors.modes.{mode}.borderStrong",
1017
+ "borderColorChecked": "transparent",
1018
+ "borderColorDisabled": "colors.modes.{mode}.borderSecondary",
1019
+ "borderColorError": "colors.adaptive.error.{mode}.border",
1020
+ "indicatorColor": "colors.static.white",
1021
+ "labelColor": "colors.modes.{mode}.textPrimary",
1022
+ "interaction": "subtle"
1023
+ }
1024
+ }
1025
+ },
1026
+ "sizes": {
1027
+ "md": {
1028
+ "tokens": {
1029
+ "controlSize": "20px",
1030
+ "labelTypeSet": "typography.typeSets.text-normal-regular",
1031
+ "gap": "spacing.scale.sm",
1032
+ "borderRadius": "radius.scale.lg"
1033
+ }
1034
+ }
1035
+ },
1036
+ "shared": {
1037
+ "transitionDuration": "motion.duration.fast",
1038
+ "focusRing": "shadows.focus.ring"
1039
+ }
1040
+ },
1041
+ "toggle": {
1042
+ "description": "Toggle selection control",
1043
+ "variants": {
1044
+ "default": {
1045
+ "description": "toggle variant",
1046
+ "tokens": {
1047
+ "background": "colors.modes.{mode}.bgMuted",
1048
+ "backgroundChecked": "colors.modes.{mode}.actionPrimary",
1049
+ "backgroundDisabled": "colors.modes.{mode}.actionSecondary",
1050
+ "backgroundError": "colors.modes.{mode}.bgMuted",
1051
+ "borderWidth": "md",
1052
+ "borderWidthError": "md",
1053
+ "borderWidthDisabled": "md",
1054
+ "borderColor": "colors.modes.{mode}.borderStrong",
1055
+ "borderColorChecked": "transparent",
1056
+ "borderColorDisabled": "colors.modes.{mode}.borderSecondary",
1057
+ "borderColorError": "colors.adaptive.error.{mode}.border",
1058
+ "indicatorColor": "colors.static.white",
1059
+ "labelColor": "colors.modes.{mode}.textPrimary",
1060
+ "interaction": "press"
1061
+ }
1062
+ }
1063
+ },
1064
+ "sizes": {
1065
+ "md": {
1066
+ "tokens": {
1067
+ "controlSize": "20px",
1068
+ "labelTypeSet": "typography.typeSets.text-normal-regular",
1069
+ "gap": "spacing.scale.sm",
1070
+ "borderRadius": "radius.scale.lg"
1071
+ }
1072
+ }
1073
+ },
1074
+ "shared": {
1075
+ "transitionDuration": "motion.duration.fast",
1076
+ "focusRing": "shadows.focus.ring"
1077
+ }
1078
+ }
1079
+ };
1080
+
1081
+ // src/user-tokens.ts
1082
+ var DEFAULT_BASE_URL = "https://atomixstudio.eu";
1083
+ async function fetchUserDesignSystem(options) {
1084
+ const { dsId, apiKey, baseUrl = DEFAULT_BASE_URL } = options;
1085
+ try {
1086
+ const headers = {
1087
+ "Content-Type": "application/json"
1088
+ };
1089
+ if (apiKey) {
1090
+ headers["Authorization"] = `Bearer ${apiKey}`;
1091
+ }
1092
+ const tokensResponse = await fetch(`${baseUrl}/api/ds/${dsId}/tokens`, {
1093
+ method: "GET",
1094
+ headers
1095
+ });
1096
+ if (!tokensResponse.ok) {
1097
+ const error = await tokensResponse.text();
1098
+ return {
1099
+ success: false,
1100
+ error: `Failed to fetch tokens: ${tokensResponse.status} ${error}`
1101
+ };
1102
+ }
1103
+ const tokensData = await tokensResponse.json();
1104
+ const meta = "meta" in tokensData && tokensData.meta ? tokensData.meta : void 0;
1105
+ let governance;
1106
+ try {
1107
+ const rulesResponse = await fetch(`${baseUrl}/api/ds/${dsId}/rules`, {
1108
+ method: "GET",
1109
+ headers
1110
+ });
1111
+ if (rulesResponse.ok) {
1112
+ const rulesData = await rulesResponse.json();
1113
+ governance = rulesData;
1114
+ }
1115
+ } catch {
1116
+ console.error("[atomix-mcp] Could not fetch governance rules, continuing without them");
1117
+ }
1118
+ const tokens = "tokens" in tokensData && tokensData.tokens ? tokensData.tokens : tokensData;
1119
+ return {
1120
+ success: true,
1121
+ tokens,
1122
+ governance,
1123
+ meta
1124
+ };
1125
+ } catch (error) {
1126
+ return {
1127
+ success: false,
1128
+ error: `Network error: ${error instanceof Error ? error.message : String(error)}`
1129
+ };
1130
+ }
1131
+ }
1132
+ function parseCLIArgs(argv = process.argv) {
1133
+ const args = {};
1134
+ for (let i = 0; i < argv.length; i++) {
1135
+ const arg = argv[i];
1136
+ const next = argv[i + 1];
1137
+ switch (arg) {
1138
+ case "--ds-id":
1139
+ if (next && !next.startsWith("--")) {
1140
+ args.dsId = next;
1141
+ i++;
1142
+ }
1143
+ break;
1144
+ case "--api-key":
1145
+ if (next && !next.startsWith("--")) {
1146
+ args.apiKey = next;
1147
+ i++;
1148
+ }
1149
+ break;
1150
+ case "--tenant":
1151
+ if (next && !next.startsWith("--")) {
1152
+ args.tenant = next;
1153
+ args.dsId = args.dsId || next;
1154
+ i++;
1155
+ }
1156
+ break;
1157
+ case "--base-url":
1158
+ if (next && !next.startsWith("--")) {
1159
+ args.baseUrl = next;
1160
+ i++;
1161
+ }
1162
+ break;
1163
+ }
1164
+ }
1165
+ return args;
1166
+ }
1167
+ function isUserDSMode(args) {
1168
+ return Boolean(args.dsId);
1169
+ }
1170
+ function transformUserTokens(userTokens) {
1171
+ if (userTokens.colors && userTokens.typography && userTokens.spacing) {
1172
+ return userTokens;
1173
+ }
1174
+ if (typeof userTokens.tokens === "object" && userTokens.tokens !== null) {
1175
+ return userTokens.tokens;
1176
+ }
1177
+ return userTokens;
1178
+ }
1179
+
1180
+ // src/ai-rules-generator.ts
1181
+ var AI_TOOLS = {
1182
+ cursor: {
1183
+ id: "cursor",
1184
+ name: "Cursor",
1185
+ rulesFilename: ".cursorrules",
1186
+ rulesPath: ".cursorrules",
1187
+ mcpConfigPath: ".cursor/mcp.json",
1188
+ supportsMarkdown: true,
1189
+ supportsMCP: true,
1190
+ description: "Cursor IDE - AI-first code editor"
1191
+ },
1192
+ copilot: {
1193
+ id: "copilot",
1194
+ name: "GitHub Copilot",
1195
+ rulesFilename: "copilot-instructions.md",
1196
+ rulesPath: ".github/copilot-instructions.md",
1197
+ supportsMarkdown: true,
1198
+ supportsMCP: false,
1199
+ // Uses rules file instead
1200
+ description: "GitHub Copilot in VS Code, JetBrains, etc."
1201
+ },
1202
+ windsurf: {
1203
+ id: "windsurf",
1204
+ name: "Windsurf",
1205
+ rulesFilename: ".windsurfrules",
1206
+ rulesPath: ".windsurfrules",
1207
+ mcpConfigPath: ".windsurf/mcp.json",
1208
+ supportsMarkdown: true,
1209
+ supportsMCP: true,
1210
+ description: "Windsurf Editor by Codeium"
1211
+ },
1212
+ cline: {
1213
+ id: "cline",
1214
+ name: "Cline",
1215
+ rulesFilename: ".clinerules",
1216
+ rulesPath: ".clinerules",
1217
+ supportsMarkdown: true,
1218
+ supportsMCP: true,
1219
+ description: "Cline VS Code extension (formerly Claude Dev)"
1220
+ },
1221
+ continue: {
1222
+ id: "continue",
1223
+ name: "Continue",
1224
+ rulesFilename: ".continuerules",
1225
+ rulesPath: ".continuerules",
1226
+ mcpConfigPath: ".continue/config.json",
1227
+ supportsMarkdown: true,
1228
+ supportsMCP: true,
1229
+ description: "Continue - open source AI code assistant"
1230
+ },
1231
+ zed: {
1232
+ id: "zed",
1233
+ name: "Zed",
1234
+ rulesFilename: ".zed/assistant/rules.md",
1235
+ rulesPath: ".zed/assistant/rules.md",
1236
+ supportsMarkdown: true,
1237
+ supportsMCP: true,
1238
+ description: "Zed Editor with AI assistant"
1239
+ },
1240
+ "claude-desktop": {
1241
+ id: "claude-desktop",
1242
+ name: "Claude Desktop",
1243
+ rulesFilename: "",
1244
+ rulesPath: "",
1245
+ mcpConfigPath: "~/Library/Application Support/Claude/claude_desktop_config.json",
1246
+ supportsMarkdown: false,
1247
+ supportsMCP: true,
1248
+ description: "Claude Desktop App by Anthropic"
1249
+ },
1250
+ generic: {
1251
+ id: "generic",
1252
+ name: "Generic AI",
1253
+ rulesFilename: "AI_GUIDELINES.md",
1254
+ rulesPath: "AI_GUIDELINES.md",
1255
+ supportsMarkdown: true,
1256
+ supportsMCP: false,
1257
+ description: "Generic guidelines for any AI tool"
1258
+ }
1259
+ };
1260
+ function generateMCPConfig(tool, options = {}) {
1261
+ const {
1262
+ serverPath,
1263
+ useNpx = true,
1264
+ dsId,
1265
+ apiKey,
1266
+ tenantId,
1267
+ // Legacy support
1268
+ projectName = "my-project"
1269
+ } = options;
1270
+ const npxCommand = useNpx ? "npx" : "node";
1271
+ const npxArgs = useNpx ? ["@atomixstudio/mcp@latest"] : [serverPath || "./node_modules/@atomixstudio/mcp/dist/index.js"];
1272
+ const effectiveDsId = dsId || tenantId;
1273
+ if (effectiveDsId && effectiveDsId !== "default") {
1274
+ npxArgs.push("--ds-id", effectiveDsId);
1275
+ if (apiKey) {
1276
+ npxArgs.push("--api-key", apiKey);
1277
+ }
1278
+ }
1279
+ switch (tool) {
1280
+ case "cursor": {
1281
+ const config = {
1282
+ mcpServers: {
1283
+ atomix: {
1284
+ command: npxCommand,
1285
+ args: npxArgs
1286
+ }
1287
+ }
1288
+ };
1289
+ return {
1290
+ tool: "cursor",
1291
+ filename: "mcp.json",
1292
+ path: ".cursor/mcp.json",
1293
+ content: JSON.stringify(config, null, 2),
1294
+ instructions: `
1295
+ ## Cursor MCP Setup
1296
+
1297
+ 1. Create the file \`.cursor/mcp.json\` in your project root
1298
+ 2. Paste the configuration below
1299
+ 3. Restart Cursor IDE
1300
+ 4. The Atomix MCP server will be available in Cursor's AI features
1301
+
1302
+ ### Configuration File
1303
+ \`\`\`json
1304
+ ${JSON.stringify(config, null, 2)}
1305
+ \`\`\`
1306
+
1307
+ ### Verify Setup
1308
+ After restarting Cursor, you can verify the MCP server is working by:
1309
+ - Opening the AI chat (Cmd/Ctrl + L)
1310
+ - Asking: "What design tokens are available?"
1311
+ - The AI should query the Atomix MCP server and list token categories
1312
+ `.trim()
1313
+ };
1314
+ }
1315
+ case "claude-desktop": {
1316
+ const config = {
1317
+ mcpServers: {
1318
+ atomix: {
1319
+ command: npxCommand,
1320
+ args: npxArgs
1321
+ }
1322
+ }
1323
+ };
1324
+ const configPath = process.platform === "darwin" ? "~/Library/Application Support/Claude/claude_desktop_config.json" : process.platform === "win32" ? "%APPDATA%\\Claude\\claude_desktop_config.json" : "~/.config/Claude/claude_desktop_config.json";
1325
+ return {
1326
+ tool: "claude-desktop",
1327
+ filename: "claude_desktop_config.json",
1328
+ path: configPath,
1329
+ content: JSON.stringify(config, null, 2),
1330
+ instructions: `
1331
+ ## Claude Desktop MCP Setup
1332
+
1333
+ 1. Locate your Claude Desktop config file:
1334
+ - **macOS**: \`${configPath}\`
1335
+ - **Windows**: \`%APPDATA%\\Claude\\claude_desktop_config.json\`
1336
+ - **Linux**: \`~/.config/Claude/claude_desktop_config.json\`
1337
+
1338
+ 2. Create or edit the file with the configuration below
1339
+
1340
+ 3. Restart Claude Desktop
1341
+
1342
+ 4. The Atomix MCP server will be available when chatting with Claude
1343
+
1344
+ ### Configuration File
1345
+ \`\`\`json
1346
+ ${JSON.stringify(config, null, 2)}
1347
+ \`\`\`
1348
+
1349
+ ### Verify Setup
1350
+ After restarting Claude Desktop:
1351
+ - Start a new conversation
1352
+ - Ask: "Can you check what Atomix design tokens are available?"
1353
+ - Claude should use the MCP server to query tokens
1354
+ `.trim()
1355
+ };
1356
+ }
1357
+ case "windsurf": {
1358
+ const config = {
1359
+ mcpServers: {
1360
+ atomix: {
1361
+ command: npxCommand,
1362
+ args: npxArgs
1363
+ }
1364
+ }
1365
+ };
1366
+ return {
1367
+ tool: "windsurf",
1368
+ filename: "mcp.json",
1369
+ path: ".windsurf/mcp.json",
1370
+ content: JSON.stringify(config, null, 2),
1371
+ instructions: `
1372
+ ## Windsurf MCP Setup
1373
+
1374
+ 1. Create the file \`.windsurf/mcp.json\` in your project root
1375
+ 2. Paste the configuration below
1376
+ 3. Restart Windsurf Editor
1377
+ 4. The Atomix MCP server will be available in Cascade
1378
+
1379
+ ### Configuration File
1380
+ \`\`\`json
1381
+ ${JSON.stringify(config, null, 2)}
1382
+ \`\`\`
1383
+ `.trim()
1384
+ };
1385
+ }
1386
+ case "continue": {
1387
+ const config = {
1388
+ models: [],
1389
+ mcpServers: [
1390
+ {
1391
+ name: "atomix",
1392
+ command: npxCommand,
1393
+ args: npxArgs
1394
+ }
1395
+ ]
1396
+ };
1397
+ return {
1398
+ tool: "continue",
1399
+ filename: "config.json",
1400
+ path: ".continue/config.json",
1401
+ content: JSON.stringify(config, null, 2),
1402
+ instructions: `
1403
+ ## Continue MCP Setup
1404
+
1405
+ 1. Create or edit \`.continue/config.json\` in your project root
1406
+ 2. Add the mcpServers section below
1407
+ 3. Restart VS Code
1408
+ 4. The Atomix MCP server will be available in Continue
1409
+
1410
+ ### Configuration File
1411
+ \`\`\`json
1412
+ ${JSON.stringify(config, null, 2)}
1413
+ \`\`\`
1414
+
1415
+ Note: If you already have a config.json, merge the mcpServers array.
1416
+ `.trim()
1417
+ };
1418
+ }
1419
+ case "vscode": {
1420
+ return {
1421
+ tool: "vscode",
1422
+ filename: "settings.json",
1423
+ path: ".vscode/settings.json",
1424
+ content: JSON.stringify({
1425
+ "mcp.servers": {
1426
+ atomix: {
1427
+ command: npxCommand,
1428
+ args: npxArgs
1429
+ }
1430
+ }
1431
+ }, null, 2),
1432
+ instructions: `
1433
+ ## VS Code MCP Setup
1434
+
1435
+ For VS Code, MCP support depends on your AI extension:
1436
+
1437
+ ### Option 1: Use GitHub Copilot Instructions
1438
+ Create \`.github/copilot-instructions.md\` with Atomix rules (use getAIToolRules)
1439
+
1440
+ ### Option 2: Use Continue Extension
1441
+ See Continue setup instructions above
1442
+
1443
+ ### Option 3: Use Cline Extension
1444
+ 1. Install Cline extension
1445
+ 2. Cline will auto-detect MCP servers in .cursor/mcp.json or .vscode/settings.json
1446
+
1447
+ ### Settings.json (for MCP-aware extensions)
1448
+ \`\`\`json
1449
+ {
1450
+ "mcp.servers": {
1451
+ "atomix": {
1452
+ "command": "${npxCommand}",
1453
+ "args": ${JSON.stringify(npxArgs)}
1454
+ }
1455
+ }
1456
+ }
1457
+ \`\`\`
1458
+ `.trim()
1459
+ };
1460
+ }
1461
+ default:
1462
+ throw new Error(`Unknown MCP config tool: ${tool}`);
1463
+ }
1464
+ }
1465
+ function generateAllMCPConfigs(options = {}) {
1466
+ const tools = ["cursor", "claude-desktop", "windsurf", "continue", "vscode"];
1467
+ return tools.map((tool) => generateMCPConfig(tool, options));
1468
+ }
1469
+ function getSetupInstructions(toolId) {
1470
+ const tool = AI_TOOLS[toolId];
1471
+ if (!tool) {
1472
+ throw new Error(`Unknown AI tool: ${toolId}. Available: ${Object.keys(AI_TOOLS).join(", ")}`);
1473
+ }
1474
+ const baseInstructions = `
1475
+ # ${tool.name} Setup for Atomix Design System
1476
+
1477
+ ${tool.description}
1478
+
1479
+ ## Overview
1480
+
1481
+ ${tool.supportsMCP ? `${tool.name} supports MCP (Model Context Protocol), allowing direct integration with the Atomix design token server.` : `${tool.name} uses a rules file to understand the Atomix design system.`}
1482
+
1483
+ `;
1484
+ switch (toolId) {
1485
+ case "cursor":
1486
+ return baseInstructions + `
1487
+ ## Quick Setup
1488
+
1489
+ ### Step 1: Add MCP Configuration
1490
+
1491
+ Create \`.cursor/mcp.json\` in your project root:
1492
+
1493
+ \`\`\`json
1494
+ {
1495
+ "mcpServers": {
1496
+ "atomix": {
1497
+ "command": "npx",
1498
+ "args": ["@atomixstudio/mcp@latest"]
1499
+ }
1500
+ }
1501
+ }
1502
+ \`\`\`
1503
+
1504
+ ### Step 2: Add Rules File (Optional but Recommended)
1505
+
1506
+ Create \`.cursorrules\` in your project root with Atomix guidelines.
1507
+ Use \`getAIToolRules({ tool: "cursor" })\` to generate this file.
1508
+
1509
+ ### Step 3: Restart Cursor
1510
+
1511
+ After adding the MCP config, restart Cursor IDE completely.
1512
+
1513
+ ## Verification
1514
+
1515
+ 1. Open AI chat (Cmd/Ctrl + L)
1516
+ 2. Ask: "What Atomix design tokens are available?"
1517
+ 3. Cursor should query the MCP server and respond with token information
1518
+
1519
+ ## Available MCP Tools
1520
+
1521
+ Once configured, you can use these in conversations:
1522
+ - \`getToken("colors.static.brand.primary")\` - Get a specific token
1523
+ - \`listTokens("colors")\` - List tokens in a category
1524
+ - \`getComponentTokens("button")\` - Get component tokens
1525
+ - \`validateUsage("#ff0000")\` - Check if a value is allowed
1526
+ - \`searchTokens("brand")\` - Search for tokens
1527
+ `;
1528
+ case "claude-desktop":
1529
+ return baseInstructions + `
1530
+ ## Quick Setup
1531
+
1532
+ ### Step 1: Locate Config File
1533
+
1534
+ - **macOS**: \`~/Library/Application Support/Claude/claude_desktop_config.json\`
1535
+ - **Windows**: \`%APPDATA%\\Claude\\claude_desktop_config.json\`
1536
+ - **Linux**: \`~/.config/Claude/claude_desktop_config.json\`
1537
+
1538
+ ### Step 2: Add MCP Configuration
1539
+
1540
+ Create or edit the config file:
1541
+
1542
+ \`\`\`json
1543
+ {
1544
+ "mcpServers": {
1545
+ "atomix": {
1546
+ "command": "npx",
1547
+ "args": ["@atomixstudio/mcp@latest"]
1548
+ }
1549
+ }
1550
+ }
1551
+ \`\`\`
1552
+
1553
+ ### Step 3: Restart Claude Desktop
1554
+
1555
+ Completely quit and reopen Claude Desktop.
1556
+
1557
+ ## Verification
1558
+
1559
+ Start a new conversation and ask:
1560
+ "Can you check what Atomix design tokens are available?"
1561
+
1562
+ Claude should use the MCP server to query and list tokens.
1563
+ `;
1564
+ case "copilot":
1565
+ return baseInstructions + `
1566
+ ## Quick Setup
1567
+
1568
+ GitHub Copilot doesn't support MCP directly, but uses instruction files.
1569
+
1570
+ ### Step 1: Create Instructions File
1571
+
1572
+ Create \`.github/copilot-instructions.md\` in your project:
1573
+
1574
+ Use \`getAIToolRules({ tool: "copilot" })\` to generate the content.
1575
+
1576
+ ### Step 2: Enable Custom Instructions
1577
+
1578
+ In VS Code settings, ensure:
1579
+ \`\`\`json
1580
+ {
1581
+ "github.copilot.chat.codeGeneration.useInstructionFiles": true
1582
+ }
1583
+ \`\`\`
1584
+
1585
+ ## Verification
1586
+
1587
+ 1. Open Copilot Chat
1588
+ 2. Ask about design tokens
1589
+ 3. Copilot should follow the Atomix guidelines from the instructions file
1590
+ `;
1591
+ case "windsurf":
1592
+ return baseInstructions + `
1593
+ ## Quick Setup
1594
+
1595
+ ### Step 1: Add MCP Configuration
1596
+
1597
+ Create \`.windsurf/mcp.json\` in your project root:
1598
+
1599
+ \`\`\`json
1600
+ {
1601
+ "mcpServers": {
1602
+ "atomix": {
1603
+ "command": "npx",
1604
+ "args": ["@atomixstudio/mcp@latest"]
1605
+ }
1606
+ }
1607
+ }
1608
+ \`\`\`
1609
+
1610
+ ### Step 2: Add Rules File
1611
+
1612
+ Create \`.windsurfrules\` in your project root.
1613
+ Use \`getAIToolRules({ tool: "windsurf" })\` to generate this file.
1614
+
1615
+ ### Step 3: Restart Windsurf
1616
+
1617
+ Restart the editor to load the MCP configuration.
1618
+ `;
1619
+ case "cline":
1620
+ return baseInstructions + `
1621
+ ## Quick Setup
1622
+
1623
+ ### Step 1: Create Rules File
1624
+
1625
+ Create \`.clinerules\` in your project root.
1626
+ Use \`getAIToolRules({ tool: "cline" })\` to generate this file.
1627
+
1628
+ ### Step 2: MCP Auto-Detection
1629
+
1630
+ Cline can auto-detect MCP servers from:
1631
+ - \`.cursor/mcp.json\`
1632
+ - Project configuration
1633
+
1634
+ If you have Cursor's MCP config, Cline will use it automatically.
1635
+
1636
+ ### Step 3: Manual MCP Setup (if needed)
1637
+
1638
+ In Cline settings, add MCP server configuration:
1639
+ - Command: \`npx\`
1640
+ - Args: \`@atomixstudio/mcp@latest\`
1641
+ `;
1642
+ case "continue":
1643
+ return baseInstructions + `
1644
+ ## Quick Setup
1645
+
1646
+ ### Step 1: Add MCP Configuration
1647
+
1648
+ Create or edit \`.continue/config.json\`:
1649
+
1650
+ \`\`\`json
1651
+ {
1652
+ "mcpServers": [
1653
+ {
1654
+ "name": "atomix",
1655
+ "command": "npx",
1656
+ "args": ["@atomixstudio/mcp@latest"]
1657
+ }
1658
+ ]
1659
+ }
1660
+ \`\`\`
1661
+
1662
+ ### Step 2: Add Rules File (Optional)
1663
+
1664
+ Create \`.continuerules\` in your project root.
1665
+ Use \`getAIToolRules({ tool: "continue" })\` to generate this file.
1666
+
1667
+ ### Step 3: Restart VS Code
1668
+
1669
+ Restart VS Code to load the Continue configuration.
1670
+ `;
1671
+ case "zed":
1672
+ return baseInstructions + `
1673
+ ## Quick Setup
1674
+
1675
+ ### Step 1: Add Rules File
1676
+
1677
+ Create \`.zed/assistant/rules.md\` in your project root.
1678
+ Use \`getAIToolRules({ tool: "zed" })\` to generate this file.
1679
+
1680
+ ### Step 2: MCP Configuration
1681
+
1682
+ Zed's MCP support is configured in Zed settings.
1683
+ Check Zed documentation for the latest MCP configuration format.
1684
+ `;
1685
+ default:
1686
+ return baseInstructions + `
1687
+ ## Generic Setup
1688
+
1689
+ ### Step 1: Create Guidelines File
1690
+
1691
+ Create \`AI_GUIDELINES.md\` in your project root.
1692
+ Use \`getAIToolRules({ tool: "generic" })\` to generate this file.
1693
+
1694
+ ### Step 2: Reference in Prompts
1695
+
1696
+ When working with AI tools, reference the guidelines file in your prompts
1697
+ or include it in your context.
1698
+ `;
1699
+ }
1700
+ }
1701
+ function generateCursorRules(projectName, strict) {
1702
+ const componentList = Object.keys(COMPONENT_TOKENS).join(", ");
1703
+ const categoryList = TOKEN_CATEGORIES.join(", ");
1704
+ const strictRules = strict ? `
1705
+ ## Hard Rules (Strict Mode)
1706
+
1707
+ 1. **NO arbitrary values** \u2014 \`w-[350px]\`, \`bg-[#ff0000]\` are FORBIDDEN
1708
+ 2. **NO hardcoded colors** \u2014 All colors must use CSS variables or token imports
1709
+ 3. **NO hardcoded spacing** \u2014 Use \`spacing.*\` tokens (e.g., \`@spacing.md\`, \`@spacing.lg\`)
1710
+ 4. **NO hardcoded typography** \u2014 Use \`typography.fontSize.*\` and \`typography.fontWeight.*\`
1711
+ 5. **Token vocabulary only** \u2014 If a value isn't in the design system, don't use it
1712
+
1713
+ ### Escape Hatch
1714
+
1715
+ If external constraints require arbitrary values:
1716
+
1717
+ \`\`\`tsx
1718
+ {/* @design-override: YouTube embed requires 16:9 aspect ratio */}
1719
+ <div className="aspect-[16/9]">
1720
+ \`\`\`
1721
+
1722
+ Document the reason. The override comment signals intentional deviation.
1723
+ ` : `
1724
+ ## Guidelines (Non-Strict Mode)
1725
+
1726
+ 1. **Prefer tokens** \u2014 Use design system tokens when available
1727
+ 2. **Document overrides** \u2014 If using arbitrary values, add a comment explaining why
1728
+ 3. **Consistency** \u2014 Match existing patterns in the codebase
1729
+ `;
1730
+ const tierGuidance = `
1731
+ ## Token Tier System (Critical)
1732
+
1733
+ Atomix tokens are organized in tiers. Understanding this hierarchy is essential:
1734
+
1735
+ ### Tier 1: Primitives (Read-Only Reference)
1736
+
1737
+ Raw foundational values. **DO NOT use these directly in components.**
1738
+
1739
+ | Type | Example Path | Example Value | Use For |
1740
+ |------|-------------|---------------|---------|
1741
+ | Color scales | \`colors.scales.green.500\` | \`#10B981\` | Reference only |
1742
+ | Spacing scale | \`spacing.md\` | \`1rem\` | Token reference |
1743
+ | Font sizes | \`typography.fontSize.sm\` | \`0.875rem\` | Reference only |
1744
+ | Radius scale | \`radius.lg\` | \`12px\` | Token reference |
1745
+
1746
+ These values are **locked** \u2014 AI tools should never suggest modifying them.
1747
+
1748
+ ### Tier 2: Semantics (Primary API)
1749
+
1750
+ Purpose-driven tokens that reference primitives. **USE THESE in components.**
1751
+
1752
+ | Type | Example Path | Maps To | Use For |
1753
+ |------|-------------|---------|---------|
1754
+ | Mode colors | \`colors.modes.light.bgSurface\` | \`neutral[5]\` | Backgrounds |
1755
+ | Semantic radius | \`radius.semantic.button\` | \`scale.md\` | Component corners |
1756
+ | TypeSets | \`typography.typeSets.title-lg\` | Composed style | Text styling |
1757
+ | Focus rings | \`shadows.focus.ring\` | Composed shadow | A11y focus |
1758
+
1759
+ These are **editable via Atomix Designer** and auto-switch for dark mode.
1760
+
1761
+ ### Tier 3: Component Tokens
1762
+
1763
+ Component-specific token assignments. Managed via Atomix Designer.
1764
+
1765
+ - Button variants: primary, secondary, outline, ghost
1766
+ - Card variants: default, outlined, elevated
1767
+ - Sizes: sm, md, lg
1768
+
1769
+ ---
1770
+
1771
+ ### Correct Token Usage
1772
+
1773
+ \`\`\`tsx
1774
+ // \u2705 CORRECT: Use semantic color (Tier 2)
1775
+ style={{ backgroundColor: "var(--atomix-bg-surface)" }}
1776
+
1777
+ // \u274C WRONG: Using primitive directly (Tier 1)
1778
+ style={{ backgroundColor: colors.scales.neutral[5] }}
1779
+
1780
+ // \u2705 CORRECT: Use typeSet (Tier 2)
1781
+ style={{ ...typography.typeSets["title-lg"] }}
1782
+
1783
+ // \u274C WRONG: Using primitive font size (Tier 1)
1784
+ style={{ fontSize: typography.fontSize["2xl"] }}
1785
+ \`\`\`
1786
+
1787
+ ### When to Reference Primitives
1788
+
1789
+ Primitives are useful for:
1790
+ 1. **Validation** \u2014 Checking if a hardcoded value matches a token
1791
+ 2. **Documentation** \u2014 Explaining what a semantic token resolves to
1792
+ 3. **A11y calculations** \u2014 Contrast ratio checks need actual hex values
1793
+ 4. **Debug logging** \u2014 Showing resolved values in dev tools
1794
+
1795
+ But **NEVER** use primitive paths directly in component styling code.
1796
+ `;
1797
+ return `# ${projectName} \u2014 Atomix Design System Rules
1798
+
1799
+ This project uses the **Atomix Design System**. All UI code must follow these guidelines.
1800
+
1801
+ ---
1802
+ ${strictRules}
1803
+ ---
1804
+ ${tierGuidance}
1805
+ ---
1806
+
1807
+ ## Token Categories
1808
+
1809
+ Available token categories: ${categoryList}
1810
+
1811
+ ### Color Tokens
1812
+
1813
+ Use CSS variables for all colors:
1814
+
1815
+ \`\`\`tsx
1816
+ // \u2705 Correct
1817
+ style={{ backgroundColor: "var(--atomix-bg-surface)" }}
1818
+ style={{ color: "var(--atomix-text-primary)" }}
1819
+
1820
+ // \u274C Wrong
1821
+ style={{ backgroundColor: "#ffffff" }}
1822
+ style={{ color: "rgb(0, 0, 0)" }}
1823
+ \`\`\`
1824
+
1825
+ **Semantic color aliases:**
1826
+ - \`--atomix-brand\` \u2014 Primary brand color
1827
+ - \`--atomix-bg-page\` \u2014 Page background
1828
+ - \`--atomix-bg-surface\` \u2014 Card/surface background
1829
+ - \`--atomix-bg-muted\` \u2014 Muted/secondary background
1830
+ - \`--atomix-text-primary\` \u2014 Primary text color
1831
+ - \`--atomix-text-secondary\` \u2014 Secondary text color
1832
+ - \`--atomix-text-muted\` \u2014 Muted/placeholder text
1833
+ - \`--atomix-icon-brand\` \u2014 Brand-colored icons
1834
+ - \`--atomix-icon-strong\` \u2014 High contrast icons
1835
+ - \`--atomix-icon-subtle\` \u2014 Medium contrast icons
1836
+ - \`--atomix-icon-disabled\` \u2014 Disabled state icons
1837
+ - \`--atomix-border-primary\` \u2014 Default border color
1838
+
1839
+ ### Spacing Tokens
1840
+
1841
+ Use spacing tokens for all padding, margin, and gap values:
1842
+
1843
+ \`\`\`tsx
1844
+ import { spacing } from "@atomix/tokens/primitives";
1845
+
1846
+ // \u2705 Correct
1847
+ style={{ padding: spacing.inset.md }}
1848
+ style={{ gap: spacing.gap.sm }}
1849
+
1850
+ // \u274C Wrong
1851
+ style={{ padding: "16px" }}
1852
+ style={{ gap: "8px" }}
1853
+ \`\`\`
1854
+
1855
+ **Spacing scale:** xs, sm, md, lg, xl, 2xl, 3xl
1856
+
1857
+ ### Typography Tokens
1858
+
1859
+ Use typography tokens for font properties:
1860
+
1861
+ \`\`\`tsx
1862
+ import { typography } from "@atomix/tokens/primitives";
1863
+
1864
+ // \u2705 Correct
1865
+ style={{
1866
+ fontSize: typography.fontSize.sm,
1867
+ fontWeight: typography.fontWeight.medium,
1868
+ lineHeight: typography.lineHeight.normal,
1869
+ }}
1870
+
1871
+ // \u274C Wrong
1872
+ style={{ fontSize: "14px", fontWeight: 500 }}
1873
+ \`\`\`
1874
+
1875
+ ### Motion Tokens
1876
+
1877
+ Use motion tokens for animations:
1878
+
1879
+ \`\`\`tsx
1880
+ import { motion } from "@atomix/tokens/primitives";
1881
+
1882
+ // \u2705 Correct
1883
+ style={{
1884
+ transitionDuration: motion.duration.fast,
1885
+ transitionTimingFunction: motion.easing.ease,
1886
+ }}
1887
+
1888
+ // \u274C Wrong
1889
+ style={{ transition: "all 150ms ease" }}
1890
+ \`\`\`
1891
+
1892
+ ---
1893
+
1894
+ ## Component Usage
1895
+
1896
+ Available components: ${componentList}
1897
+
1898
+ ### Using the MCP Server
1899
+
1900
+ This project has an MCP server for querying design tokens. Use these tools:
1901
+
1902
+ - \`getToken("path.to.token")\` \u2014 Get a specific token value
1903
+ - \`listTokens("colors")\` \u2014 List all tokens in a category
1904
+ - \`getComponentTokens("button")\` \u2014 Get tokens for a component
1905
+ - \`validateUsage("value")\` \u2014 Check if a value follows the design system
1906
+ - \`searchTokens("brand")\` \u2014 Search for tokens by name or value
1907
+
1908
+ ### Component Patterns
1909
+
1910
+ When implementing components:
1911
+
1912
+ 1. Check the component tokens first: \`getComponentTokens("componentName")\`
1913
+ 2. Use the documented variants and sizes
1914
+ 3. Apply tokens through CSS variables or direct imports
1915
+ 4. Follow the existing component architecture
1916
+
1917
+ ---
1918
+
1919
+ ## Import Patterns
1920
+
1921
+ \`\`\`tsx
1922
+ // Import primitives for direct use
1923
+ import { colors, spacing, typography, motion } from "@atomix/tokens/primitives";
1924
+
1925
+ // Or import the combined object
1926
+ import { primitives } from "@atomix/tokens";
1927
+
1928
+ // Use CSS variables in styles (preferred for colors)
1929
+ const style = {
1930
+ backgroundColor: "var(--atomix-bg-surface)",
1931
+ padding: spacing.inset.md,
1932
+ borderRadius: "var(--atomix-radius-scale-md)",
1933
+ };
1934
+ \`\`\`
1935
+
1936
+ ---
1937
+
1938
+ ## Dark Mode
1939
+
1940
+ Colors automatically switch in dark mode when using CSS variables:
1941
+
1942
+ \`\`\`tsx
1943
+ // This works in both light and dark mode
1944
+ style={{
1945
+ backgroundColor: "var(--atomix-bg-surface)",
1946
+ color: "var(--atomix-text-primary)",
1947
+ }}
1948
+ \`\`\`
1949
+
1950
+ The \`.dark\` class on the root element toggles all color variables.
1951
+
1952
+ ---
1953
+
1954
+ ## When Unsure
1955
+
1956
+ 1. **Search tokens first:** Use \`searchTokens("query")\` to find relevant tokens
1957
+ 2. **Check component tokens:** Use \`getComponentTokens("component")\` for component-specific values
1958
+ 3. **Use the nearest token:** If exact match unavailable, use the closest semantic token
1959
+ 4. **Flag for review:** Add \`{/* TODO: need new token? */}\` comment if a token seems missing
1960
+
1961
+ ---
1962
+
1963
+ ## Reference
1964
+
1965
+ - Token package: \`@atomix/tokens\`
1966
+ - CSS variables: All prefixed with \`--atomix-\`
1967
+ - MCP server: \`atomix-mcp\` (run \`npm run start\` in packages/atomix-mcp)
1968
+ `;
1969
+ }
1970
+ function generateRulesForTool(toolId, projectName, strict) {
1971
+ const tool = AI_TOOLS[toolId];
1972
+ if (!tool) {
1973
+ throw new Error(`Unknown AI tool: ${toolId}. Available: ${Object.keys(AI_TOOLS).join(", ")}`);
1974
+ }
1975
+ const header = `<!-- Generated for ${tool.name} by Atomix MCP Server -->
1976
+ <!-- Tool: ${tool.description} -->
1977
+ <!-- Rules file: ${tool.rulesPath} -->
1978
+ <!-- Generated: ${(/* @__PURE__ */ new Date()).toISOString()} -->
1979
+
1980
+ `;
1981
+ const content = header + generateCursorRules(projectName, strict);
1982
+ return {
1983
+ tool,
1984
+ filename: tool.rulesFilename,
1985
+ path: tool.rulesPath,
1986
+ content
1987
+ };
1988
+ }
1989
+ function generateRulesForAllTools(projectName, strict) {
1990
+ return Object.keys(AI_TOOLS).filter((id) => AI_TOOLS[id].rulesPath !== "").map(
1991
+ (toolId) => generateRulesForTool(toolId, projectName, strict)
1992
+ );
1993
+ }
1994
+ function getSupportedAITools() {
1995
+ return Object.values(AI_TOOLS);
1996
+ }
1997
+ function generateToolSetupGuide(projectName) {
1998
+ const tools = getSupportedAITools();
1999
+ const mcpTools = tools.filter((t) => t.supportsMCP);
2000
+ const rulesTools = tools.filter((t) => t.rulesPath);
2001
+ return `# AI Tool Setup Guide for ${projectName}
2002
+
2003
+ This project uses the **Atomix Design System** with MCP (Model Context Protocol).
2004
+
2005
+ ## Quick Start
2006
+
2007
+ Choose your AI tool and follow the setup:
2008
+
2009
+ | Tool | MCP Support | Rules File | Setup Command |
2010
+ |------|-------------|------------|---------------|
2011
+ ${tools.map((t) => `| ${t.name} | ${t.supportsMCP ? "Yes" : "No"} | ${t.rulesPath || "N/A"} | \`getSetupInstructions("${t.id}")\` |`).join("\n")}
2012
+
2013
+ ## MCP-Enabled Tools (Recommended)
2014
+
2015
+ These tools can query Atomix tokens directly:
2016
+
2017
+ ${mcpTools.map((t) => `- **${t.name}** \u2014 ${t.description}`).join("\n")}
2018
+
2019
+ ### Generate MCP Config
2020
+
2021
+ \`\`\`
2022
+ exportMCPConfig({ tool: "cursor" }) // For Cursor
2023
+ exportMCPConfig({ tool: "claude-desktop" }) // For Claude Desktop
2024
+ exportMCPConfig({ tool: "all" }) // All configs at once
2025
+ \`\`\`
2026
+
2027
+ ## Rules-Based Tools
2028
+
2029
+ These tools use instruction files:
2030
+
2031
+ ${rulesTools.filter((t) => !t.supportsMCP).map((t) => `- **${t.name}** \u2014 \`${t.rulesPath}\``).join("\n")}
2032
+
2033
+ ### Generate Rules Files
2034
+
2035
+ \`\`\`
2036
+ getAIToolRules({ tool: "copilot" }) // For GitHub Copilot
2037
+ getAIToolRules({ tool: "all" }) // All rules at once
2038
+ \`\`\`
2039
+
2040
+ ## Available MCP Tools
2041
+
2042
+ Once connected, AI tools can use:
2043
+
2044
+ | Tool | Description |
2045
+ |------|-------------|
2046
+ | \`getToken\` | Get a specific token by path |
2047
+ | \`listTokens\` | List tokens in a category |
2048
+ | \`getComponentTokens\` | Get tokens for a component |
2049
+ | \`validateUsage\` | Check if a value follows the design system |
2050
+ | \`searchTokens\` | Search tokens by name or value |
2051
+ | \`exportMCPConfig\` | Generate MCP configuration files |
2052
+ | \`getSetupInstructions\` | Get detailed setup instructions |
2053
+
2054
+ ## Token Tier System
2055
+
2056
+ | Tier | Mutable | Use For |
2057
+ |------|---------|---------|
2058
+ | Primitive | No | Reference only (validation, a11y) |
2059
+ | Semantic | Yes (Designer) | Primary API for styling |
2060
+ | Component | Yes (Designer) | Component-specific tokens |
2061
+
2062
+ **Rule**: Always use semantic tokens in code. Never use primitive paths directly.
2063
+ `;
2064
+ }
2065
+
2066
+ // src/index.ts
2067
+ function formatTimeAgo(timestamp) {
2068
+ const now = Date.now();
2069
+ const diffMs = now - timestamp;
2070
+ const diffSec = Math.floor(diffMs / 1e3);
2071
+ const diffMin = Math.floor(diffSec / 60);
2072
+ const diffHour = Math.floor(diffMin / 60);
2073
+ const diffDay = Math.floor(diffHour / 24);
2074
+ if (diffSec < 60) return "just now";
2075
+ if (diffMin < 60) return `${diffMin} minute${diffMin > 1 ? "s" : ""} ago`;
2076
+ if (diffHour < 24) return `${diffHour} hour${diffHour > 1 ? "s" : ""} ago`;
2077
+ if (diffDay < 7) return `${diffDay} day${diffDay > 1 ? "s" : ""} ago`;
2078
+ const date = new Date(timestamp);
2079
+ return date.toLocaleDateString("en-US", {
2080
+ month: "short",
2081
+ day: "numeric",
2082
+ year: date.getFullYear() !== (/* @__PURE__ */ new Date()).getFullYear() ? "numeric" : void 0
2083
+ });
2084
+ }
2085
+ var server = new Server(
2086
+ {
2087
+ name: "atomix-mcp",
2088
+ version: "0.1.0"
2089
+ },
2090
+ {
2091
+ capabilities: {
2092
+ tools: {},
2093
+ resources: {}
2094
+ }
2095
+ }
2096
+ );
2097
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
2098
+ return {
2099
+ tools: [
2100
+ {
2101
+ name: "getToken",
2102
+ description: "Get a specific design token by its path. Returns value, CSS variable, and tier metadata. IMPORTANT: Tokens are tiered - 'primitive' tokens are read-only reference values, 'semantic' tokens are the primary API for styling.",
2103
+ inputSchema: {
2104
+ type: "object",
2105
+ properties: {
2106
+ path: {
2107
+ type: "string",
2108
+ description: "Token path in dot notation. Prefer semantic paths (colors.modes.light.bgPage) over primitive paths (colors.scales.green.500)"
2109
+ },
2110
+ tenantId: {
2111
+ type: "string",
2112
+ description: "Tenant ID for multi-tenant support (optional, defaults to 'default')"
2113
+ }
2114
+ },
2115
+ required: ["path"]
2116
+ }
2117
+ },
2118
+ {
2119
+ name: "listTokens",
2120
+ description: "List tokens in a category. Use 'tier' filter to get only semantic tokens (recommended) or primitives (reference only). Semantic tokens are the primary API; primitives are read-only reference values.",
2121
+ inputSchema: {
2122
+ type: "object",
2123
+ properties: {
2124
+ category: {
2125
+ type: "string",
2126
+ enum: ["colors", "typography", "spacing", "sizing", "shadows", "radius", "motion", "zIndex", "borders"],
2127
+ description: "Token category to list"
2128
+ },
2129
+ subcategory: {
2130
+ type: "string",
2131
+ description: "Optional subcategory, e.g., 'modes.light' for semantic colors, 'scale' for primitive spacing"
2132
+ },
2133
+ tier: {
2134
+ type: "string",
2135
+ enum: ["semantic", "primitive", "all"],
2136
+ description: "Filter by token tier. 'semantic' (recommended) returns purpose-driven tokens for styling. 'primitive' returns raw reference values. Default: 'all'"
2137
+ },
2138
+ tenantId: {
2139
+ type: "string",
2140
+ description: "Tenant ID for multi-tenant support (optional, defaults to 'default')"
2141
+ }
2142
+ },
2143
+ required: ["category"]
2144
+ }
2145
+ },
2146
+ {
2147
+ name: "getComponentTokens",
2148
+ description: "Get all design tokens used by a specific component (Button, Card, Dialog, etc.)",
2149
+ inputSchema: {
2150
+ type: "object",
2151
+ properties: {
2152
+ component: {
2153
+ type: "string",
2154
+ enum: ["button", "card", "dialog", "input", "select", "heading", "checkbox", "radio", "toggle", "selectionControls"],
2155
+ description: "Component name"
2156
+ },
2157
+ variant: {
2158
+ type: "string",
2159
+ description: "Optional variant name (e.g., 'primary', 'outline', 'ghost')"
2160
+ },
2161
+ size: {
2162
+ type: "string",
2163
+ description: "Optional size name (e.g., 'sm', 'md', 'lg')"
2164
+ },
2165
+ tenantId: {
2166
+ type: "string",
2167
+ description: "Tenant ID for multi-tenant support (optional, defaults to 'default')"
2168
+ }
2169
+ },
2170
+ required: ["component"]
2171
+ }
2172
+ },
2173
+ {
2174
+ name: "validateUsage",
2175
+ description: "Check if a CSS value follows the Atomix design system. Detects arbitrary values that should use tokens.",
2176
+ inputSchema: {
2177
+ type: "object",
2178
+ properties: {
2179
+ value: {
2180
+ type: "string",
2181
+ description: "CSS value to validate, e.g., '#ff0000', '16px', 'rgb(0,112,97)'"
2182
+ },
2183
+ context: {
2184
+ type: "string",
2185
+ enum: ["color", "spacing", "radius", "shadow", "typography", "any"],
2186
+ description: "Context of the value (helps find the right token)"
2187
+ }
2188
+ },
2189
+ required: ["value"]
2190
+ }
2191
+ },
2192
+ {
2193
+ name: "generateCursorRules",
2194
+ description: "[DEPRECATED] Use 'getAIToolRules' instead. Generate .cursorrules content for a project.",
2195
+ inputSchema: {
2196
+ type: "object",
2197
+ properties: {
2198
+ projectName: {
2199
+ type: "string",
2200
+ description: "Name of the project"
2201
+ },
2202
+ strict: {
2203
+ type: "boolean",
2204
+ description: "Whether to enforce strict token usage (no arbitrary values)"
2205
+ }
2206
+ },
2207
+ required: []
2208
+ }
2209
+ },
2210
+ {
2211
+ name: "getAIToolRules",
2212
+ description: "Generate design system rules for AI coding tools. Supports Cursor, GitHub Copilot, Windsurf, Cline, Continue, Zed, and more.",
2213
+ inputSchema: {
2214
+ type: "object",
2215
+ properties: {
2216
+ tool: {
2217
+ type: "string",
2218
+ enum: ["cursor", "copilot", "windsurf", "cline", "continue", "zed", "generic", "all"],
2219
+ description: "AI tool to generate rules for. Use 'all' to generate for all supported tools."
2220
+ },
2221
+ projectName: {
2222
+ type: "string",
2223
+ description: "Name of the project (default: 'My Project')"
2224
+ },
2225
+ strict: {
2226
+ type: "boolean",
2227
+ description: "Enforce strict token usage - no arbitrary values allowed (default: true)"
2228
+ }
2229
+ },
2230
+ required: ["tool"]
2231
+ }
2232
+ },
2233
+ {
2234
+ name: "listAITools",
2235
+ description: "List all supported AI coding tools and their rules file conventions.",
2236
+ inputSchema: {
2237
+ type: "object",
2238
+ properties: {},
2239
+ required: []
2240
+ }
2241
+ },
2242
+ {
2243
+ name: "getAIToolSetupGuide",
2244
+ description: "Get a complete setup guide for integrating Atomix with AI coding tools.",
2245
+ inputSchema: {
2246
+ type: "object",
2247
+ properties: {
2248
+ projectName: {
2249
+ type: "string",
2250
+ description: "Name of the project"
2251
+ }
2252
+ },
2253
+ required: []
2254
+ }
2255
+ },
2256
+ {
2257
+ name: "exportMCPConfig",
2258
+ description: "Generate MCP configuration file for AI tools. Creates ready-to-use config for Cursor (.cursor/mcp.json), Claude Desktop, Windsurf, Continue, or VS Code.",
2259
+ inputSchema: {
2260
+ type: "object",
2261
+ properties: {
2262
+ tool: {
2263
+ type: "string",
2264
+ enum: ["cursor", "claude-desktop", "windsurf", "continue", "vscode", "all"],
2265
+ description: "AI tool to generate MCP config for. Use 'all' to generate for all supported tools."
2266
+ },
2267
+ tenantId: {
2268
+ type: "string",
2269
+ description: "Tenant ID for multi-tenant setups (optional, defaults to 'default')"
2270
+ },
2271
+ projectName: {
2272
+ type: "string",
2273
+ description: "Project name for identification (optional)"
2274
+ },
2275
+ useNpx: {
2276
+ type: "boolean",
2277
+ description: "Use npx to run the server (default: true). Set to false for local development."
2278
+ }
2279
+ },
2280
+ required: ["tool"]
2281
+ }
2282
+ },
2283
+ {
2284
+ name: "getSetupInstructions",
2285
+ description: "Get detailed step-by-step setup instructions for a specific AI tool. Includes MCP configuration, rules file setup, and verification steps.",
2286
+ inputSchema: {
2287
+ type: "object",
2288
+ properties: {
2289
+ tool: {
2290
+ type: "string",
2291
+ enum: ["cursor", "copilot", "windsurf", "cline", "continue", "zed", "claude-desktop", "generic"],
2292
+ description: "AI tool to get setup instructions for."
2293
+ }
2294
+ },
2295
+ required: ["tool"]
2296
+ }
2297
+ },
2298
+ {
2299
+ name: "searchTokens",
2300
+ description: "Search for tokens by name or value. Results include tier metadata - prefer using 'semantic' tier tokens in code, use 'primitive' tier only for reference/validation.",
2301
+ inputSchema: {
2302
+ type: "object",
2303
+ properties: {
2304
+ query: {
2305
+ type: "string",
2306
+ description: "Search query (matches token paths or values)"
2307
+ },
2308
+ tier: {
2309
+ type: "string",
2310
+ enum: ["semantic", "primitive", "all"],
2311
+ description: "Filter results by tier. 'semantic' recommended for styling. Default: 'all'"
2312
+ }
2313
+ },
2314
+ required: ["query"]
2315
+ }
2316
+ }
2317
+ ]
2318
+ };
2319
+ });
2320
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
2321
+ const { name, arguments: args } = request.params;
2322
+ switch (name) {
2323
+ case "getToken": {
2324
+ const path = args?.path;
2325
+ const value = getTokenByPath(primitives2, path);
2326
+ if (value === void 0) {
2327
+ return {
2328
+ content: [
2329
+ {
2330
+ type: "text",
2331
+ text: JSON.stringify({
2332
+ error: `Token not found: ${path}`,
2333
+ suggestion: `Use listTokens to see available tokens. Available categories: ${getTokenCategories().join(", ")}`
2334
+ }, null, 2)
2335
+ }
2336
+ ]
2337
+ };
2338
+ }
2339
+ const cssVar = getCssVariableName(path);
2340
+ const metadata = getTokenMetadata(path);
2341
+ return {
2342
+ content: [
2343
+ {
2344
+ type: "text",
2345
+ text: JSON.stringify({
2346
+ path,
2347
+ value,
2348
+ cssVariable: cssVar,
2349
+ // Token tier classification
2350
+ tier: metadata.tier,
2351
+ mutable: metadata.mutable,
2352
+ editVia: metadata.editVia || null,
2353
+ guidance: metadata.guidance,
2354
+ // Usage examples
2355
+ usage: metadata.tier === "semantic" ? {
2356
+ css: `var(${cssVar})`,
2357
+ tailwind: getTailwindClass(path, value),
2358
+ recommendation: "Use this token in your components."
2359
+ } : {
2360
+ css: `var(${cssVar})`,
2361
+ tailwind: getTailwindClass(path, value),
2362
+ recommendation: "This is a primitive (read-only reference). Consider using a semantic token instead.",
2363
+ semanticAlternatives: getSuggestedSemanticTokens(path)
2364
+ }
2365
+ }, null, 2)
2366
+ }
2367
+ ]
2368
+ };
2369
+ }
2370
+ case "listTokens": {
2371
+ const category = args?.category;
2372
+ const subcategory = args?.subcategory;
2373
+ const tierFilter = args?.tier || "all";
2374
+ const rawTokens = listTokensInCategory(primitives2, category, subcategory);
2375
+ const tokensWithMetadata = {};
2376
+ for (const [tokenPath, value] of Object.entries(rawTokens)) {
2377
+ const fullPath = subcategory ? `${category}.${subcategory}.${tokenPath}` : `${category}.${tokenPath}`;
2378
+ const metadata = getTokenMetadata(fullPath);
2379
+ if (tierFilter !== "all" && metadata.tier !== tierFilter) {
2380
+ continue;
2381
+ }
2382
+ tokensWithMetadata[tokenPath] = {
2383
+ value,
2384
+ tier: metadata.tier,
2385
+ mutable: metadata.mutable,
2386
+ guidance: metadata.guidance
2387
+ };
2388
+ }
2389
+ return {
2390
+ content: [
2391
+ {
2392
+ type: "text",
2393
+ text: JSON.stringify({
2394
+ category,
2395
+ subcategory: subcategory || null,
2396
+ tierFilter,
2397
+ count: Object.keys(tokensWithMetadata).length,
2398
+ note: tierFilter === "all" ? "Results include both primitive (read-only) and semantic (usable) tokens. Use tier='semantic' for styling recommendations." : tierFilter === "semantic" ? "Showing semantic tokens - these are the recommended tokens for styling." : "Showing primitive tokens - use these for reference/validation only, not direct styling.",
2399
+ tokens: tokensWithMetadata
2400
+ }, null, 2)
2401
+ }
2402
+ ]
2403
+ };
2404
+ }
2405
+ case "getComponentTokens": {
2406
+ const component = args?.component;
2407
+ const variant = args?.variant;
2408
+ const size = args?.size;
2409
+ const componentKey = component.toLowerCase();
2410
+ const componentData = COMPONENT_TOKENS[componentKey];
2411
+ if (!componentData) {
2412
+ return {
2413
+ content: [
2414
+ {
2415
+ type: "text",
2416
+ text: JSON.stringify({
2417
+ error: `Component not found: ${component}`,
2418
+ available: Object.keys(COMPONENT_TOKENS)
2419
+ }, null, 2)
2420
+ }
2421
+ ]
2422
+ };
2423
+ }
2424
+ let result = { ...componentData };
2425
+ if (variant && result.variants) {
2426
+ result.variants = { [variant]: result.variants[variant] };
2427
+ }
2428
+ if (size && result.sizes) {
2429
+ result.sizes = { [size]: result.sizes[size] };
2430
+ }
2431
+ return {
2432
+ content: [
2433
+ {
2434
+ type: "text",
2435
+ text: JSON.stringify(result, null, 2)
2436
+ }
2437
+ ]
2438
+ };
2439
+ }
2440
+ case "validateUsage": {
2441
+ const value = args?.value;
2442
+ const context = args?.context || "any";
2443
+ const validation = validateValue(value, context);
2444
+ return {
2445
+ content: [
2446
+ {
2447
+ type: "text",
2448
+ text: JSON.stringify(validation, null, 2)
2449
+ }
2450
+ ]
2451
+ };
2452
+ }
2453
+ case "generateCursorRules": {
2454
+ const projectName = args?.projectName || "My Project";
2455
+ const strict = args?.strict ?? true;
2456
+ const rules = generateCursorRules(projectName, strict);
2457
+ return {
2458
+ content: [
2459
+ {
2460
+ type: "text",
2461
+ text: `<!-- DEPRECATED: Use getAIToolRules instead -->
2462
+ ${rules}`
2463
+ }
2464
+ ]
2465
+ };
2466
+ }
2467
+ case "getAIToolRules": {
2468
+ const tool = args?.tool;
2469
+ const projectName = args?.projectName || "My Project";
2470
+ const strict = args?.strict ?? true;
2471
+ if (tool === "all") {
2472
+ const allRules = generateRulesForAllTools(projectName, strict);
2473
+ return {
2474
+ content: [
2475
+ {
2476
+ type: "text",
2477
+ text: JSON.stringify({
2478
+ message: `Generated rules for ${allRules.length} AI tools`,
2479
+ tools: allRules.map((r) => ({
2480
+ tool: r.tool.name,
2481
+ filename: r.filename,
2482
+ path: r.path,
2483
+ description: r.tool.description
2484
+ })),
2485
+ files: allRules.map((r) => ({
2486
+ path: r.path,
2487
+ content: r.content
2488
+ }))
2489
+ }, null, 2)
2490
+ }
2491
+ ]
2492
+ };
2493
+ }
2494
+ try {
2495
+ const result = generateRulesForTool(tool, projectName, strict);
2496
+ return {
2497
+ content: [
2498
+ {
2499
+ type: "text",
2500
+ text: JSON.stringify({
2501
+ tool: result.tool.name,
2502
+ filename: result.filename,
2503
+ path: result.path,
2504
+ description: result.tool.description,
2505
+ content: result.content
2506
+ }, null, 2)
2507
+ }
2508
+ ]
2509
+ };
2510
+ } catch (error) {
2511
+ return {
2512
+ content: [
2513
+ {
2514
+ type: "text",
2515
+ text: JSON.stringify({
2516
+ error: String(error),
2517
+ availableTools: Object.keys(AI_TOOLS)
2518
+ }, null, 2)
2519
+ }
2520
+ ]
2521
+ };
2522
+ }
2523
+ }
2524
+ case "listAITools": {
2525
+ const tools = getSupportedAITools();
2526
+ return {
2527
+ content: [
2528
+ {
2529
+ type: "text",
2530
+ text: JSON.stringify({
2531
+ count: tools.length,
2532
+ tools: tools.map((t) => ({
2533
+ id: t.id,
2534
+ name: t.name,
2535
+ rulesFile: t.rulesPath,
2536
+ description: t.description
2537
+ })),
2538
+ note: "Use getAIToolRules({ tool: 'toolId' }) to generate rules for a specific tool."
2539
+ }, null, 2)
2540
+ }
2541
+ ]
2542
+ };
2543
+ }
2544
+ case "getAIToolSetupGuide": {
2545
+ const projectName = args?.projectName || "My Project";
2546
+ const guide = generateToolSetupGuide(projectName);
2547
+ return {
2548
+ content: [
2549
+ {
2550
+ type: "text",
2551
+ text: guide
2552
+ }
2553
+ ]
2554
+ };
2555
+ }
2556
+ case "exportMCPConfig": {
2557
+ const tool = args?.tool;
2558
+ const tenantId = args?.tenantId || "default";
2559
+ const projectName = args?.projectName || "my-project";
2560
+ const useNpx = args?.useNpx ?? true;
2561
+ const options = { tenantId, projectName, useNpx };
2562
+ if (tool === "all") {
2563
+ const allConfigs = generateAllMCPConfigs(options);
2564
+ return {
2565
+ content: [
2566
+ {
2567
+ type: "text",
2568
+ text: JSON.stringify({
2569
+ message: `Generated MCP configs for ${allConfigs.length} AI tools`,
2570
+ configs: allConfigs.map((c) => ({
2571
+ tool: c.tool,
2572
+ path: c.path,
2573
+ filename: c.filename
2574
+ })),
2575
+ files: allConfigs.map((c) => ({
2576
+ tool: c.tool,
2577
+ path: c.path,
2578
+ content: c.content,
2579
+ instructions: c.instructions
2580
+ }))
2581
+ }, null, 2)
2582
+ }
2583
+ ]
2584
+ };
2585
+ }
2586
+ try {
2587
+ const config = generateMCPConfig(tool, options);
2588
+ return {
2589
+ content: [
2590
+ {
2591
+ type: "text",
2592
+ text: JSON.stringify({
2593
+ tool: config.tool,
2594
+ path: config.path,
2595
+ filename: config.filename,
2596
+ content: config.content,
2597
+ instructions: config.instructions
2598
+ }, null, 2)
2599
+ }
2600
+ ]
2601
+ };
2602
+ } catch (error) {
2603
+ return {
2604
+ content: [
2605
+ {
2606
+ type: "text",
2607
+ text: JSON.stringify({
2608
+ error: String(error),
2609
+ availableTools: ["cursor", "claude-desktop", "windsurf", "continue", "vscode", "all"]
2610
+ }, null, 2)
2611
+ }
2612
+ ]
2613
+ };
2614
+ }
2615
+ }
2616
+ case "getSetupInstructions": {
2617
+ const toolId = args?.tool;
2618
+ try {
2619
+ const instructions = getSetupInstructions(toolId);
2620
+ return {
2621
+ content: [
2622
+ {
2623
+ type: "text",
2624
+ text: instructions
2625
+ }
2626
+ ]
2627
+ };
2628
+ } catch (error) {
2629
+ return {
2630
+ content: [
2631
+ {
2632
+ type: "text",
2633
+ text: JSON.stringify({
2634
+ error: String(error),
2635
+ availableTools: Object.keys(AI_TOOLS)
2636
+ }, null, 2)
2637
+ }
2638
+ ]
2639
+ };
2640
+ }
2641
+ }
2642
+ case "searchTokens": {
2643
+ const query = (args?.query).toLowerCase();
2644
+ const tierFilter = args?.tier || "all";
2645
+ const allTokens = flattenTokens(primitives2);
2646
+ const matches = Object.entries(allTokens).filter(([path, value]) => {
2647
+ const pathLower = path.toLowerCase();
2648
+ const valueStr = String(value).toLowerCase();
2649
+ const matchesQuery = pathLower.includes(query) || valueStr.includes(query);
2650
+ if (!matchesQuery) return false;
2651
+ if (tierFilter !== "all") {
2652
+ const metadata = getTokenMetadata(path);
2653
+ if (metadata.tier !== tierFilter) return false;
2654
+ }
2655
+ return true;
2656
+ }).slice(0, 50).map(([path, value]) => {
2657
+ const metadata = getTokenMetadata(path);
2658
+ return {
2659
+ path,
2660
+ value,
2661
+ cssVariable: getCssVariableName(path),
2662
+ tier: metadata.tier,
2663
+ mutable: metadata.mutable,
2664
+ guidance: metadata.guidance
2665
+ };
2666
+ });
2667
+ matches.sort((a, b) => {
2668
+ if (a.tier === "semantic" && b.tier !== "semantic") return -1;
2669
+ if (a.tier !== "semantic" && b.tier === "semantic") return 1;
2670
+ return 0;
2671
+ });
2672
+ return {
2673
+ content: [
2674
+ {
2675
+ type: "text",
2676
+ text: JSON.stringify({
2677
+ query,
2678
+ tierFilter,
2679
+ count: matches.length,
2680
+ note: "Semantic tokens are listed first. Use semantic tokens for styling; primitives are for reference only.",
2681
+ matches
2682
+ }, null, 2)
2683
+ }
2684
+ ]
2685
+ };
2686
+ }
2687
+ default:
2688
+ return {
2689
+ content: [
2690
+ {
2691
+ type: "text",
2692
+ text: JSON.stringify({ error: `Unknown tool: ${name}` })
2693
+ }
2694
+ ]
2695
+ };
2696
+ }
2697
+ });
2698
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
2699
+ return {
2700
+ resources: [
2701
+ {
2702
+ uri: "atomix://tokens/all",
2703
+ name: "All Atomix Tokens",
2704
+ description: "Complete design token reference",
2705
+ mimeType: "application/json"
2706
+ },
2707
+ {
2708
+ uri: "atomix://tokens/colors",
2709
+ name: "Color Tokens",
2710
+ description: "All color tokens (static, scales, modes)",
2711
+ mimeType: "application/json"
2712
+ },
2713
+ {
2714
+ uri: "atomix://tokens/typography",
2715
+ name: "Typography Tokens",
2716
+ description: "Font families, sizes, weights, line heights",
2717
+ mimeType: "application/json"
2718
+ },
2719
+ {
2720
+ uri: "atomix://tokens/spacing",
2721
+ name: "Spacing Tokens",
2722
+ description: "Spacing scale, insets, gaps",
2723
+ mimeType: "application/json"
2724
+ },
2725
+ {
2726
+ uri: "atomix://components",
2727
+ name: "Component Tokens",
2728
+ description: "Token mappings for all components",
2729
+ mimeType: "application/json"
2730
+ }
2731
+ ]
2732
+ };
2733
+ });
2734
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
2735
+ const uri = request.params.uri;
2736
+ switch (uri) {
2737
+ case "atomix://tokens/all":
2738
+ return {
2739
+ contents: [
2740
+ {
2741
+ uri,
2742
+ mimeType: "application/json",
2743
+ text: JSON.stringify(primitives2, null, 2)
2744
+ }
2745
+ ]
2746
+ };
2747
+ case "atomix://tokens/colors":
2748
+ return {
2749
+ contents: [
2750
+ {
2751
+ uri,
2752
+ mimeType: "application/json",
2753
+ text: JSON.stringify(primitives2.colors, null, 2)
2754
+ }
2755
+ ]
2756
+ };
2757
+ case "atomix://tokens/typography":
2758
+ return {
2759
+ contents: [
2760
+ {
2761
+ uri,
2762
+ mimeType: "application/json",
2763
+ text: JSON.stringify(primitives2.typography, null, 2)
2764
+ }
2765
+ ]
2766
+ };
2767
+ case "atomix://tokens/spacing":
2768
+ return {
2769
+ contents: [
2770
+ {
2771
+ uri,
2772
+ mimeType: "application/json",
2773
+ text: JSON.stringify(primitives2.spacing, null, 2)
2774
+ }
2775
+ ]
2776
+ };
2777
+ case "atomix://components":
2778
+ return {
2779
+ contents: [
2780
+ {
2781
+ uri,
2782
+ mimeType: "application/json",
2783
+ text: JSON.stringify(COMPONENT_TOKENS, null, 2)
2784
+ }
2785
+ ]
2786
+ };
2787
+ default:
2788
+ throw new Error(`Unknown resource: ${uri}`);
2789
+ }
2790
+ });
2791
+ function getTailwindClass(path, value) {
2792
+ if (path.startsWith("colors.static.brand.primary")) return "bg-brand text-brand";
2793
+ if (path.startsWith("spacing.") && !path.includes(".inset")) {
2794
+ const size = path.split(".").pop();
2795
+ return `p-${size} m-${size} gap-${size}`;
2796
+ }
2797
+ if (path.startsWith("radius.")) {
2798
+ const size = path.split(".").pop();
2799
+ return `rounded-${size}`;
2800
+ }
2801
+ return null;
2802
+ }
2803
+ function getSuggestedSemanticTokens(primitivePath) {
2804
+ const suggestions = [];
2805
+ if (primitivePath.startsWith("colors.scales.")) {
2806
+ suggestions.push(
2807
+ "colors.modes.light.bgPage (page background)",
2808
+ "colors.modes.light.bgSurface (card/panel background)",
2809
+ "colors.modes.light.textPrimary (main text)",
2810
+ "colors.modes.light.borderPrimary (borders)",
2811
+ "colors.modes.light.actionPrimary (interactive elements)"
2812
+ );
2813
+ }
2814
+ if (primitivePath.startsWith("spacing.")) {
2815
+ suggestions.push(
2816
+ "Use spacing tokens (spacing.xs, spacing.sm, spacing.md, spacing.lg, etc.)",
2817
+ "These resolve to CSS variables automatically"
2818
+ );
2819
+ }
2820
+ if (primitivePath.startsWith("typography.fontSize.")) {
2821
+ suggestions.push(
2822
+ "typography.typeSets.title-lg (large titles)",
2823
+ "typography.typeSets.title-md (medium titles)",
2824
+ "typography.typeSets.text-normal-regular (body text)",
2825
+ "typography.typeSets.label-md (form labels)"
2826
+ );
2827
+ }
2828
+ if (primitivePath.startsWith("radius.")) {
2829
+ suggestions.push(
2830
+ "Use radius tokens (radius.sm, radius.md, radius.lg, radius.full, etc.)",
2831
+ "Describe semantic usage in AI guidance (e.g., 'Buttons use @radius.md')"
2832
+ );
2833
+ }
2834
+ if (primitivePath.startsWith("shadows.elevation.")) {
2835
+ suggestions.push(
2836
+ "Use elevation keys (none, sm, md, lg, xl) in component defaults",
2837
+ "These resolve to CSS variables automatically"
2838
+ );
2839
+ }
2840
+ return suggestions;
2841
+ }
2842
+ function validateValue(value, context) {
2843
+ if (/^#[0-9A-Fa-f]{3,8}$/.test(value)) {
2844
+ const allTokens = flattenTokens(primitives2);
2845
+ const matches = Object.entries(allTokens).filter(([path, v]) => {
2846
+ if (typeof v !== "string") return false;
2847
+ return v.toLowerCase() === value.toLowerCase();
2848
+ }).map(([path, v]) => ({
2849
+ path,
2850
+ value: v,
2851
+ cssVariable: getCssVariableName(path)
2852
+ }));
2853
+ if (matches.length > 0) {
2854
+ return {
2855
+ valid: false,
2856
+ issue: "Hardcoded hex color detected",
2857
+ suggestion: `Use token instead: ${matches[0].cssVariable}`,
2858
+ matchingTokens: matches
2859
+ };
2860
+ }
2861
+ return {
2862
+ valid: false,
2863
+ issue: "Hardcoded hex color with no matching token",
2864
+ suggestion: "Check colors.static, colors.scales, or colors.modes for appropriate tokens"
2865
+ };
2866
+ }
2867
+ if (/^(rgb|rgba|hsl|hsla)\(/.test(value)) {
2868
+ return {
2869
+ valid: false,
2870
+ issue: "Hardcoded color function detected",
2871
+ suggestion: "Use CSS variable: var(--atomix-colors-*) or primitives.colors.*"
2872
+ };
2873
+ }
2874
+ if (context === "spacing" && /^\d+px$/.test(value)) {
2875
+ return {
2876
+ valid: false,
2877
+ issue: "Hardcoded pixel value for spacing",
2878
+ suggestion: "Use spacing.* tokens (e.g., @spacing.md, @spacing.lg)"
2879
+ };
2880
+ }
2881
+ if (/^\d+px$/.test(value)) {
2882
+ return {
2883
+ valid: false,
2884
+ issue: "Hardcoded pixel value detected",
2885
+ suggestion: "Consider using design tokens from spacing, sizing, or typography"
2886
+ };
2887
+ }
2888
+ if (/\[.*\]/.test(value)) {
2889
+ return {
2890
+ valid: false,
2891
+ issue: "Tailwind arbitrary value detected",
2892
+ suggestion: "Replace with token-based class or CSS variable"
2893
+ };
2894
+ }
2895
+ return { valid: true };
2896
+ }
2897
+ var primitives2 = {};
2898
+ var userGovernance;
2899
+ var isUserMode = false;
2900
+ var userDsId;
2901
+ async function main() {
2902
+ const cliArgs = parseCLIArgs();
2903
+ if (isUserDSMode(cliArgs)) {
2904
+ console.error(`[atomix-mcp] User DS mode: loading design system ${cliArgs.dsId}`);
2905
+ isUserMode = true;
2906
+ userDsId = cliArgs.dsId;
2907
+ const result = await fetchUserDesignSystem({
2908
+ dsId: cliArgs.dsId,
2909
+ apiKey: cliArgs.apiKey,
2910
+ baseUrl: cliArgs.baseUrl
2911
+ });
2912
+ if (!result.success || !result.tokens) {
2913
+ console.error(`[atomix-mcp] Failed to load user DS: ${result.error}`);
2914
+ console.error("[atomix-mcp] Falling back to Atomix internal tokens");
2915
+ primitives2 = await loadPrimitives();
2916
+ } else {
2917
+ primitives2 = transformUserTokens(result.tokens);
2918
+ userGovernance = result.governance;
2919
+ const meta = result.meta;
2920
+ const dsName = meta?.name || cliArgs.dsId;
2921
+ const tokenCategories = Object.keys(primitives2);
2922
+ const rulesCount = userGovernance?.rules?.length || 0;
2923
+ console.error("");
2924
+ console.error(`[atomix-mcp] ========================================`);
2925
+ console.error(`[atomix-mcp] Design System: ${dsName}`);
2926
+ console.error(`[atomix-mcp] ----------------------------------------`);
2927
+ if (meta?.publishedAt) {
2928
+ const publishedDate = new Date(meta.publishedAt);
2929
+ const timeAgo = formatTimeAgo(meta.publishedAt);
2930
+ console.error(`[atomix-mcp] Published: ${timeAgo}`);
2931
+ console.error(`[atomix-mcp] (${publishedDate.toLocaleString()})`);
2932
+ }
2933
+ if (meta?.version) {
2934
+ console.error(`[atomix-mcp] Version: ${meta.version}`);
2935
+ }
2936
+ console.error(`[atomix-mcp] ----------------------------------------`);
2937
+ console.error(`[atomix-mcp] Tokens: ${tokenCategories.length} categories`);
2938
+ console.error(`[atomix-mcp] ${tokenCategories.join(", ")}`);
2939
+ console.error(`[atomix-mcp] Rules: ${rulesCount} governance rules`);
2940
+ console.error(`[atomix-mcp] ========================================`);
2941
+ console.error("");
2942
+ }
2943
+ } else {
2944
+ console.error("[atomix-mcp] Loading Atomix internal primitives...");
2945
+ primitives2 = await loadPrimitives();
2946
+ console.error(`[atomix-mcp] Loaded ${Object.keys(primitives2).length} token categories`);
2947
+ }
2948
+ const transport = new StdioServerTransport();
2949
+ await server.connect(transport);
2950
+ console.error("[atomix-mcp] Atomix MCP server started");
2951
+ if (isUserMode) {
2952
+ console.error(`[atomix-mcp] Serving design system: ${userDsId}`);
2953
+ }
2954
+ }
2955
+ main().catch((error) => {
2956
+ console.error("[atomix-mcp] Fatal error:", error);
2957
+ process.exit(1);
2958
+ });
2959
+ export {
2960
+ AI_TOOLS,
2961
+ fetchUserDesignSystem,
2962
+ generateAllMCPConfigs,
2963
+ generateCursorRules,
2964
+ generateMCPConfig,
2965
+ generateRulesForAllTools,
2966
+ generateRulesForTool,
2967
+ generateToolSetupGuide,
2968
+ getSetupInstructions,
2969
+ getSupportedAITools,
2970
+ isUserDSMode,
2971
+ parseCLIArgs,
2972
+ transformUserTokens
2973
+ };
2974
+ //# sourceMappingURL=index.js.map