sonance-brand-mcp 1.1.0 → 1.1.1

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.
@@ -14,6 +14,7 @@ const AccordionContext = createContext<AccordionContextValue | null>(null);
14
14
 
15
15
  interface AccordionProps {
16
16
  type?: "single" | "multiple";
17
+ collapsible?: boolean;
17
18
  defaultValue?: string | string[];
18
19
  className?: string;
19
20
  children: React.ReactNode;
@@ -21,6 +22,7 @@ interface AccordionProps {
21
22
 
22
23
  export function Accordion({
23
24
  type = "single",
25
+ collapsible = false,
24
26
  defaultValue,
25
27
  className,
26
28
  children,
@@ -33,7 +35,11 @@ export function Accordion({
33
35
  const toggleItem = (value: string) => {
34
36
  setOpenItems((prev) => {
35
37
  if (type === "single") {
36
- return prev.includes(value) ? [] : [value];
38
+ // If collapsible, allow closing the open item; otherwise, keep it open
39
+ if (prev.includes(value)) {
40
+ return collapsible ? [] : prev;
41
+ }
42
+ return [value];
37
43
  }
38
44
  return prev.includes(value)
39
45
  ? prev.filter((v) => v !== value)
@@ -33,12 +33,14 @@ interface AlertProps
33
33
  extends React.HTMLAttributes<HTMLDivElement>,
34
34
  VariantProps<typeof alertVariants> {
35
35
  title?: string;
36
+ dismissible?: boolean;
36
37
  onClose?: () => void;
37
38
  }
38
39
 
39
40
  export const Alert = forwardRef<HTMLDivElement, AlertProps>(
40
- ({ className, variant = "default", title, children, onClose, ...props }, ref) => {
41
+ ({ className, variant = "default", title, children, dismissible, onClose, ...props }, ref) => {
41
42
  const Icon = iconMap[variant || "default"];
43
+ const showCloseButton = dismissible || onClose;
42
44
 
43
45
  return (
44
46
  <div
@@ -60,7 +62,7 @@ export const Alert = forwardRef<HTMLDivElement, AlertProps>(
60
62
  </div>
61
63
  )}
62
64
  </div>
63
- {onClose && (
65
+ {showCloseButton && (
64
66
  <button
65
67
  onClick={onClose}
66
68
  className="shrink-0 rounded-sm p-1 opacity-70 transition-opacity hover:opacity-100"
@@ -121,8 +121,7 @@ export function ZoomImage({ zoomScale = 1.1, className, ...props }: ZoomImagePro
121
121
  <Image
122
122
  {...props}
123
123
  className={cn(
124
- "transition-transform duration-300 hover:scale-[var(--zoom-scale)]",
125
- props.className
124
+ "transition-transform duration-300 hover:scale-[var(--zoom-scale)]"
126
125
  )}
127
126
  style={{ "--zoom-scale": zoomScale } as React.CSSProperties}
128
127
  />
@@ -27,7 +27,7 @@ const kbdVariants = cva(
27
27
  interface KbdProps
28
28
  extends React.HTMLAttributes<HTMLElement>,
29
29
  VariantProps<typeof kbdVariants> {
30
- keys?: string | string[];
30
+ keys?: string | readonly string[];
31
31
  }
32
32
 
33
33
  export const Kbd = forwardRef<HTMLElement, KbdProps>(
@@ -62,32 +62,39 @@ Progress.displayName = "Progress";
62
62
  interface CircularProgressProps {
63
63
  value?: number;
64
64
  max?: number;
65
- size?: number;
65
+ size?: "sm" | "md" | "lg" | number;
66
66
  strokeWidth?: number;
67
67
  showValue?: boolean;
68
68
  className?: string;
69
69
  }
70
70
 
71
+ const circularSizeMap = {
72
+ sm: 32,
73
+ md: 48,
74
+ lg: 64,
75
+ };
76
+
71
77
  export function CircularProgress({
72
78
  value = 0,
73
79
  max = 100,
74
- size = 48,
80
+ size = "md",
75
81
  strokeWidth = 4,
76
82
  showValue = false,
77
83
  className,
78
84
  }: CircularProgressProps) {
85
+ const resolvedSize = typeof size === "number" ? size : circularSizeMap[size];
79
86
  const percentage = Math.min(100, Math.max(0, (value / max) * 100));
80
- const radius = (size - strokeWidth) / 2;
87
+ const radius = (resolvedSize - strokeWidth) / 2;
81
88
  const circumference = 2 * Math.PI * radius;
82
89
  const strokeDashoffset = circumference - (percentage / 100) * circumference;
83
90
 
84
91
  return (
85
92
  <div className={cn("relative inline-flex items-center justify-center", className)}>
86
- <svg width={size} height={size} className="-rotate-90">
93
+ <svg width={resolvedSize} height={resolvedSize} className="-rotate-90">
87
94
  {/* Background circle */}
88
95
  <circle
89
- cx={size / 2}
90
- cy={size / 2}
96
+ cx={resolvedSize / 2}
97
+ cy={resolvedSize / 2}
91
98
  r={radius}
92
99
  fill="none"
93
100
  stroke="currentColor"
@@ -96,8 +103,8 @@ export function CircularProgress({
96
103
  />
97
104
  {/* Progress circle */}
98
105
  <circle
99
- cx={size / 2}
100
- cy={size / 2}
106
+ cx={resolvedSize / 2}
107
+ cy={resolvedSize / 2}
101
108
  r={radius}
102
109
  fill="none"
103
110
  stroke="currentColor"
@@ -8,7 +8,9 @@ type TooltipPosition = "top" | "bottom" | "left" | "right";
8
8
  interface TooltipProps {
9
9
  content: React.ReactNode;
10
10
  children: React.ReactNode;
11
+ /** @deprecated Use `side` instead */
11
12
  position?: TooltipPosition;
13
+ side?: TooltipPosition;
12
14
  delay?: number;
13
15
  className?: string;
14
16
  }
@@ -16,10 +18,13 @@ interface TooltipProps {
16
18
  export function Tooltip({
17
19
  content,
18
20
  children,
19
- position = "top",
21
+ position,
22
+ side = "top",
20
23
  delay = 200,
21
24
  className,
22
25
  }: TooltipProps) {
26
+ // Support both `position` (legacy) and `side` (preferred)
27
+ const resolvedPosition = position ?? side;
23
28
  const [isVisible, setIsVisible] = useState(false);
24
29
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
25
30
 
@@ -73,7 +78,7 @@ export function Tooltip({
73
78
  className={cn(
74
79
  "absolute z-50 px-3 py-1.5 text-xs font-medium text-white bg-sonance-charcoal whitespace-nowrap",
75
80
  "animate-in fade-in zoom-in-95 duration-150",
76
- positionClasses[position],
81
+ positionClasses[resolvedPosition],
77
82
  className
78
83
  )}
79
84
  >
@@ -81,7 +86,7 @@ export function Tooltip({
81
86
  <span
82
87
  className={cn(
83
88
  "absolute border-4",
84
- arrowClasses[position]
89
+ arrowClasses[resolvedPosition]
85
90
  )}
86
91
  />
87
92
  </div>
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
- import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
5
  import * as fs from "fs";
6
6
  import * as path from "path";
7
7
  import * as os from "os";
@@ -168,6 +168,7 @@ const server = new Server({
168
168
  capabilities: {
169
169
  tools: {},
170
170
  resources: {},
171
+ prompts: {},
171
172
  },
172
173
  });
173
174
  // ============================================
@@ -309,6 +310,35 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
309
310
  required: [],
310
311
  },
311
312
  },
313
+ {
314
+ name: "design_component",
315
+ description: "Returns brand-specific design tokens, colors, implementation rules, and logo assets for designing a component. Smart defaults: Sonance/Light/Default logo lockup if not specified.",
316
+ inputSchema: {
317
+ type: "object",
318
+ properties: {
319
+ brand: {
320
+ type: "string",
321
+ enum: ["sonance", "iport", "blaze"],
322
+ description: "Which brand's styling to use. Defaults to 'sonance' if not specified.",
323
+ },
324
+ theme: {
325
+ type: "string",
326
+ enum: ["light", "dark"],
327
+ description: "The color scheme to use. Defaults to 'light' if not specified.",
328
+ },
329
+ logo_preference: {
330
+ type: "string",
331
+ enum: ["default", "sonance", "iport", "blaze"],
332
+ description: "Which logo to use. 'default' = Sonance+James+IPORT lockup. Or specify 'sonance', 'iport', or 'blaze' for individual brand logos. Defaults to 'default' if not specified.",
333
+ },
334
+ component_description: {
335
+ type: "string",
336
+ description: "What the user wants to design (e.g., 'hero section', 'pricing card', 'navigation bar')",
337
+ },
338
+ },
339
+ required: ["component_description"],
340
+ },
341
+ },
312
342
  ],
313
343
  };
314
344
  });
@@ -530,6 +560,258 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
530
560
  };
531
561
  }
532
562
  }
563
+ case "design_component": {
564
+ const rawArgs = args;
565
+ if (!rawArgs.component_description) {
566
+ return {
567
+ content: [{ type: "text", text: "Error: component_description is required. What would you like to design?" }],
568
+ isError: true,
569
+ };
570
+ }
571
+ // Apply smart defaults and track what was defaulted
572
+ const defaultsUsed = [];
573
+ const brand = rawArgs.brand || (() => { defaultsUsed.push("brand → Sonance"); return "sonance"; })();
574
+ const theme = rawArgs.theme || (() => { defaultsUsed.push("theme → Light"); return "light"; })();
575
+ const logoPreference = rawArgs.logo_preference || (() => { defaultsUsed.push("logo → Default lockup"); return "default"; })();
576
+ const component_description = rawArgs.component_description;
577
+ // Logo path mapping based on preference and theme
578
+ // Light theme = dark logo (for light backgrounds), Dark theme = light logo (for dark backgrounds)
579
+ const logoMap = {
580
+ default: {
581
+ light: "/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png",
582
+ dark: "/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png",
583
+ },
584
+ sonance: {
585
+ light: "/logos/sonance/Sonance_Logo_2C_Dark_RGB.png",
586
+ dark: "/logos/sonance/Sonance_Logo_2C_Light_RGB.png",
587
+ },
588
+ iport: {
589
+ light: "/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png",
590
+ dark: "/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png",
591
+ },
592
+ blaze: {
593
+ light: "/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png",
594
+ dark: "/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png",
595
+ },
596
+ };
597
+ const logoPath = logoMap[logoPreference]?.[theme] || logoMap.default[theme];
598
+ const logoPreferenceLabel = logoPreference === "default"
599
+ ? "Sonance + James + IPORT Lockup"
600
+ : `${logoPreference.charAt(0).toUpperCase() + logoPreference.slice(1)} Only`;
601
+ // Brand-specific design tokens
602
+ const brandTokens = {
603
+ sonance: {
604
+ light: `## Sonance Light Theme Design Tokens
605
+
606
+ ### Colors
607
+ - **Primary/Accent**: \`#00D3C8\` (Sonance Teal) — \`bg-sonance-blue\`, \`text-sonance-blue\`
608
+ - **Text Primary**: \`#333F48\` (Charcoal) — \`text-sonance-charcoal\`
609
+ - **Background**: \`#FFFFFF\` or \`#F5F5F5\` — \`bg-white\`, \`bg-sonance-light-gray\`
610
+ - **Borders/Dividers**: \`#D9D9D6\` — \`border-sonance-light-gray\`
611
+
612
+ ### Implementation Rules
613
+ - Use light backgrounds (white or light gray)
614
+ - Charcoal text on light backgrounds for readability
615
+ - Teal accent for CTAs, links, and interactive elements
616
+ - Minimal borders, prefer subtle shadows for elevation
617
+
618
+ ### Tailwind Classes
619
+ \`\`\`jsx
620
+ // Primary Button
621
+ <button className="bg-sonance-blue text-white px-6 py-3 text-sm font-medium uppercase tracking-wide">
622
+
623
+ // Card
624
+ <div className="bg-white border border-sonance-light-gray rounded-sm p-6 shadow-sm">
625
+
626
+ // Section
627
+ <section className="bg-sonance-light-gray text-sonance-charcoal">
628
+ \`\`\``,
629
+ dark: `## Sonance Dark Theme Design Tokens
630
+
631
+ ### Colors
632
+ - **Primary/Accent**: \`#00D3C8\` (Sonance Teal) — \`bg-sonance-blue\`, \`text-sonance-blue\`
633
+ - **Text Primary**: \`#FFFFFF\` — \`text-white\`
634
+ - **Background**: \`#333F48\` (Charcoal) — \`bg-sonance-charcoal\`
635
+ - **Text Secondary**: \`#D9D9D6\` — \`text-sonance-light-gray\`
636
+
637
+ ### Implementation Rules
638
+ - Use charcoal background for dark sections
639
+ - White text on charcoal for primary content
640
+ - Teal accent for CTAs and highlights
641
+ - Use light-gray for secondary text and borders
642
+
643
+ ### Tailwind Classes
644
+ \`\`\`jsx
645
+ // Primary Button
646
+ <button className="bg-sonance-blue text-sonance-charcoal px-6 py-3 text-sm font-medium uppercase tracking-wide">
647
+
648
+ // Card
649
+ <div className="bg-sonance-charcoal border border-white/10 rounded-sm p-6">
650
+
651
+ // Section
652
+ <section className="bg-sonance-charcoal text-white">
653
+ \`\`\``,
654
+ },
655
+ iport: {
656
+ light: `## IPORT Light Theme Design Tokens
657
+
658
+ ### Colors
659
+ - **Primary/Accent**: \`#FC4C02\` (IPORT Orange) — \`bg-iport-orange\`, \`text-iport-orange\`
660
+ - **Text Primary**: \`#0F161D\` — \`text-iport-dark\`
661
+ - **Background**: \`#FFFFFF\` — \`bg-white\`
662
+ - **Card Background**: \`#F5F5F5\` — \`bg-gray-100\`
663
+
664
+ ### Implementation Rules
665
+ - IPORT typically uses dark UI, but light mode should use orange accents sparingly
666
+ - Orange for CTAs and interactive elements only
667
+ - Dark text on light backgrounds
668
+ - Clean, minimal aesthetic
669
+
670
+ ### Tailwind Classes
671
+ \`\`\`jsx
672
+ // Primary Button
673
+ <button className="bg-iport-orange text-white px-6 py-3 text-sm font-medium uppercase tracking-wide">
674
+
675
+ // Card
676
+ <div className="bg-white border border-gray-200 rounded-sm p-6">
677
+
678
+ // Section
679
+ <section className="bg-gray-100 text-iport-dark">
680
+ \`\`\``,
681
+ dark: `## IPORT Dark Theme Design Tokens
682
+
683
+ ### Colors
684
+ - **Primary/Accent**: \`#FC4C02\` (IPORT Orange) — \`bg-iport-orange\`, \`text-iport-orange\`
685
+ - **Text Primary**: \`#FFFFFF\` — \`text-iport-white\`, \`text-white\`
686
+ - **Background**: \`#0F161D\` — \`bg-iport-dark\`
687
+ - **Card Background**: \`#1C1E20\` — \`bg-iport-dark-gray\`
688
+
689
+ ### Implementation Rules
690
+ - IPORT's signature is dark UI with orange accents
691
+ - Use orange for primary CTAs and interactive elements
692
+ - White text on dark backgrounds
693
+ - Cards should use slightly lighter dark gray for contrast
694
+
695
+ ### Tailwind Classes
696
+ \`\`\`jsx
697
+ // Primary Button
698
+ <button className="bg-iport-orange text-white px-6 py-3 text-sm font-medium uppercase tracking-wide hover:bg-iport-orange/90">
699
+
700
+ // Card
701
+ <div className="bg-iport-dark-gray border border-white/10 rounded-sm p-6">
702
+
703
+ // Section
704
+ <section className="bg-iport-dark text-iport-white">
705
+ \`\`\``,
706
+ },
707
+ blaze: {
708
+ light: `## Blaze Audio Light Theme Design Tokens
709
+
710
+ ### Colors
711
+ - **Primary Accent**: \`#00A3E1\` (Blaze Blue) — \`bg-blaze-blue\`, \`text-blaze-blue\`
712
+ - **Secondary Accent**: \`#C02B0A\` (Blaze Red) — \`bg-blaze-red\` (for alerts/emphasis)
713
+ - **Text Primary**: \`#28282B\` — \`text-blaze-dark-gray\`
714
+ - **Background**: \`#FFFFFF\` — \`bg-white\`
715
+
716
+ ### Implementation Rules
717
+ - Blaze typically uses dark UI, but light mode should feature blue accents
718
+ - Blue for primary CTAs, red for alerts or secondary emphasis
719
+ - Dark text on light backgrounds
720
+ - Modern, tech-forward aesthetic
721
+
722
+ ### Tailwind Classes
723
+ \`\`\`jsx
724
+ // Primary Button
725
+ <button className="bg-blaze-blue text-white px-6 py-3 text-sm font-medium uppercase tracking-wide">
726
+
727
+ // Alert/Emphasis Button
728
+ <button className="bg-blaze-red text-white px-6 py-3 text-sm font-medium uppercase tracking-wide">
729
+
730
+ // Card
731
+ <div className="bg-white border border-gray-200 rounded-sm p-6">
732
+ \`\`\``,
733
+ dark: `## Blaze Audio Dark Theme Design Tokens
734
+
735
+ ### Colors
736
+ - **Primary Accent**: \`#00A3E1\` (Blaze Blue) — \`bg-blaze-blue\`, \`text-blaze-blue\`
737
+ - **Secondary Accent**: \`#C02B0A\` (Blaze Red) — \`bg-blaze-red\` (for alerts/emphasis)
738
+ - **Text Primary**: \`#FFFFFF\` — \`text-blaze-white\`, \`text-white\`
739
+ - **Background**: \`#28282B\` — \`bg-blaze-dark-gray\`
740
+ - **Card Background**: \`#313131\` — \`bg-blaze-gray\`
741
+
742
+ ### Implementation Rules
743
+ - Blaze's signature is dark UI with blue accents
744
+ - Blue for primary CTAs and interactive elements
745
+ - Red for alerts, errors, or secondary emphasis
746
+ - White text on dark backgrounds
747
+ - Cards use slightly lighter gray for contrast
748
+
749
+ ### Tailwind Classes
750
+ \`\`\`jsx
751
+ // Primary Button
752
+ <button className="bg-blaze-blue text-white px-6 py-3 text-sm font-medium uppercase tracking-wide hover:bg-blaze-blue/90">
753
+
754
+ // Alert Button
755
+ <button className="bg-blaze-red text-white px-6 py-3 text-sm font-medium uppercase tracking-wide">
756
+
757
+ // Card
758
+ <div className="bg-blaze-gray border border-white/10 rounded-sm p-6">
759
+
760
+ // Section
761
+ <section className="bg-blaze-dark-gray text-blaze-white">
762
+ \`\`\``,
763
+ },
764
+ };
765
+ const tokens = brandTokens[brand]?.[theme];
766
+ if (!tokens) {
767
+ return {
768
+ content: [{ type: "text", text: `Invalid brand/theme combination: ${brand}/${theme}` }],
769
+ isError: true,
770
+ };
771
+ }
772
+ // Build defaults notice if any were applied
773
+ const defaultsNotice = defaultsUsed.length > 0
774
+ ? `\n> **Note**: Defaults applied: ${defaultsUsed.join(", ")}. Specify \`brand\`, \`theme\`, or \`logo_preference\` explicitly for different styling.\n`
775
+ : "";
776
+ const response = `# Design Context for: ${component_description}
777
+
778
+ **Brand**: ${brand.toUpperCase()}
779
+ **Theme**: ${theme.charAt(0).toUpperCase() + theme.slice(1)}
780
+ **Logo**: ${logoPreferenceLabel}
781
+ ${defaultsNotice}
782
+ ${tokens}
783
+
784
+ ## Logo Asset
785
+ - **Selected**: ${logoPreferenceLabel}
786
+ - **Path**: \`${logoPath}\`
787
+ - **Usage**:
788
+ \`\`\`jsx
789
+ <img src="${logoPath}" alt="${logoPreferenceLabel}" className="h-8 w-auto" />
790
+ // or with Next.js Image:
791
+ <Image src="${logoPath}" alt="${logoPreferenceLabel}" width={200} height={40} />
792
+ \`\`\`
793
+
794
+ > **Tip**: To use a different logo, specify \`logo_preference\`: "default" (Sonance+James+IPORT), "sonance", "iport", or "blaze"
795
+
796
+ ## Typography (All Brands)
797
+ - **Font Family**: Montserrat
798
+ - **Headlines**: font-weight 300 (Light) or 500 (Medium), letter-spacing -0.02em
799
+ - **Body**: font-weight 400 (Regular), line-height 1.6
800
+ - **Buttons/CTAs**: font-weight 500, uppercase, letter-spacing 0.08em
801
+
802
+ ## Design Principles
803
+ 1. Generous whitespace — layouts should feel "breathable"
804
+ 2. Minimal borders — use subtle dividers, not heavy borders
805
+ 3. Refined shadows — subtle elevation, not aggressive drop shadows
806
+ 4. Premium feel — every element should feel high-end and intentional
807
+
808
+ ---
809
+
810
+ Now design the **${component_description}** following these tokens and principles.`;
811
+ return {
812
+ content: [{ type: "text", text: response }],
813
+ };
814
+ }
533
815
  default:
534
816
  return {
535
817
  content: [{ type: "text", text: `Unknown tool: ${name}` }],
@@ -538,6 +820,105 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
538
820
  }
539
821
  });
540
822
  // ============================================
823
+ // PROMPTS (user-initiated templates)
824
+ // ============================================
825
+ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
826
+ prompts: [
827
+ {
828
+ name: "design",
829
+ description: "Design a new Sonance-branded UI component with the correct brand colors and styling",
830
+ arguments: [
831
+ {
832
+ name: "component",
833
+ description: "What to design (e.g., hero section, pricing card, navigation bar)",
834
+ required: true,
835
+ },
836
+ {
837
+ name: "brand",
838
+ description: "Which brand: sonance, iport, or blaze",
839
+ required: true,
840
+ },
841
+ {
842
+ name: "theme",
843
+ description: "Color scheme: light or dark",
844
+ required: true,
845
+ },
846
+ ],
847
+ },
848
+ {
849
+ name: "brand-check",
850
+ description: "Verify if code follows Sonance brand guidelines",
851
+ arguments: [
852
+ {
853
+ name: "code",
854
+ description: "The code to check against brand guidelines",
855
+ required: true,
856
+ },
857
+ ],
858
+ },
859
+ ],
860
+ }));
861
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
862
+ const { name, arguments: promptArgs } = request.params;
863
+ if (name === "design") {
864
+ const component = promptArgs?.component || "component";
865
+ const brand = promptArgs?.brand || "sonance";
866
+ const theme = promptArgs?.theme || "light";
867
+ return {
868
+ messages: [
869
+ {
870
+ role: "user",
871
+ content: {
872
+ type: "text",
873
+ text: `Design a ${component} for the ${brand.toUpperCase()} brand using ${theme} theme.
874
+
875
+ Please use the design_component tool first to get the correct design tokens, then create the component following Sonance brand guidelines.
876
+
877
+ Requirements:
878
+ - Brand: ${brand}
879
+ - Theme: ${theme} mode
880
+ - Component: ${component}
881
+
882
+ Follow these steps:
883
+ 1. Call design_component with the brand, theme, and component description
884
+ 2. Use the returned design tokens and Tailwind classes
885
+ 3. Generate clean, production-ready React/JSX code
886
+ 4. Follow typography rules (Montserrat font, correct weights)
887
+ 5. Apply design principles (generous whitespace, minimal borders, premium feel)`,
888
+ },
889
+ },
890
+ ],
891
+ };
892
+ }
893
+ if (name === "brand-check") {
894
+ const code = promptArgs?.code || "";
895
+ return {
896
+ messages: [
897
+ {
898
+ role: "user",
899
+ content: {
900
+ type: "text",
901
+ text: `Check this code against Sonance brand guidelines:
902
+
903
+ \`\`\`
904
+ ${code}
905
+ \`\`\`
906
+
907
+ Use get_brand_guidelines to verify:
908
+ 1. Correct color usage (no hardcoded colors, proper semantic tokens)
909
+ 2. Typography (Montserrat font, correct weights - never bold/700 for headlines)
910
+ 3. Design patterns (generous whitespace, minimal borders, premium feel)
911
+ 4. Component patterns (correct button styles, card styling, etc.)
912
+
913
+ Provide specific feedback on what matches and what needs to change.`,
914
+ },
915
+ },
916
+ ],
917
+ };
918
+ }
919
+ throw new Error(`Unknown prompt: ${name}`);
920
+ });
921
+ // ============================================
541
922
  // START SERVER
542
923
  // ============================================
543
924
  async function main() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "MCP Server for Sonance Brand Guidelines and Component Library - gives Claude instant access to brand colors, typography, and UI components.",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",