sonance-brand-mcp 1.2.5 → 1.3.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.
- package/dist/assets/components/alert-dialog.stories.tsx +142 -0
- package/dist/assets/components/alert-dialog.tsx +142 -0
- package/dist/assets/components/aspect-ratio.stories.tsx +67 -0
- package/dist/assets/components/aspect-ratio.tsx +8 -0
- package/dist/assets/components/avatar.tsx +64 -20
- package/dist/assets/components/carousel.stories.tsx +158 -0
- package/dist/assets/components/carousel.tsx +262 -0
- package/dist/assets/components/chart.stories.tsx +376 -0
- package/dist/assets/components/chart.tsx +384 -0
- package/dist/assets/components/checkbox.tsx +12 -2
- package/dist/assets/components/code.tsx +22 -20
- package/dist/assets/components/collapsible.stories.tsx +128 -0
- package/dist/assets/components/collapsible.tsx +10 -0
- package/dist/assets/components/command.stories.tsx +183 -0
- package/dist/assets/components/command.tsx +170 -0
- package/dist/assets/components/context-menu.stories.tsx +159 -0
- package/dist/assets/components/context-menu.tsx +218 -0
- package/dist/assets/components/divider.tsx +38 -35
- package/dist/assets/components/dropdown-menu.tsx +217 -0
- package/dist/assets/components/hover-card.stories.tsx +113 -0
- package/dist/assets/components/hover-card.tsx +35 -0
- package/dist/assets/components/kbd.tsx +6 -6
- package/dist/assets/components/menubar.stories.tsx +208 -0
- package/dist/assets/components/menubar.tsx +251 -0
- package/dist/assets/components/navigation-menu.stories.tsx +237 -0
- package/dist/assets/components/navigation-menu.tsx +135 -0
- package/dist/assets/components/resizable.stories.tsx +197 -0
- package/dist/assets/components/resizable.tsx +47 -0
- package/dist/assets/components/scroll-area.stories.tsx +123 -0
- package/dist/assets/components/scroll-area.tsx +48 -0
- package/dist/assets/components/scroll-shadow.tsx +29 -7
- package/dist/assets/components/separator.tsx +32 -0
- package/dist/assets/components/sheet.tsx +141 -0
- package/dist/assets/components/sidebar.stories.tsx +351 -0
- package/dist/assets/components/sidebar.tsx +760 -0
- package/dist/assets/components/toggle-group.stories.tsx +153 -0
- package/dist/assets/components/toggle-group.tsx +61 -0
- package/dist/assets/components/toggle.stories.tsx +77 -0
- package/dist/assets/components/toggle.tsx +46 -0
- package/dist/assets/components/tooltip.tsx +23 -90
- package/dist/assets/globals.css +30 -0
- package/dist/assets/logos/40th-anniversary/Sonance_40_Logo_CMYK_BEAM_BLUE_40_AND_BEAM_DARK.png +0 -0
- package/dist/assets/logos/Sonance logo dark mode.png +0 -0
- package/dist/assets/logos/Sonance logo light mode.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png +0 -0
- package/dist/assets/logos/blaze/BlazeBySonance_Logo_Lockup_White_RGB_05162025.png +0 -0
- package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Black_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_LtGray_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_LtGray_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Polished_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_Reverse_CMYK.png +0 -0
- package/dist/assets/logos/james/James_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/james/James_Logo_White_CMYK.png +0 -0
- package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Dark_RGB.png +0 -0
- package/dist/assets/logos/life-is-better/Sonance_LifeisBetter_Light_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_2C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/my-sonance/My.Sonance_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Dark_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Light_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_2C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Black_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Grayscale_RGB.png +0 -0
- package/dist/assets/logos/sonance/Sonance_Logo_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Dark_CMYK.png +0 -0
- package/dist/assets/logos/sonance-academy/SonanceAcademy_Logo_Light_CMYK.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Dark_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Light_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_3C_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Black_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Grayscale_RGB.png +0 -0
- package/dist/assets/logos/sonance-iport/Sonance_IPORT_LockUp_Reverse_RGB.png +0 -0
- package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Dark.png +0 -0
- package/dist/assets/logos/sonance-james/Sonance_James_Lockup_Light.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Dark.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_LockupStacked_Light.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png +0 -0
- package/dist/assets/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png +0 -0
- package/dist/assets/logos/trufig/TrufigLogo_Black.png +0 -0
- package/dist/assets/logos/trufig/TrufigLogo_Light.png +0 -0
- package/dist/assets/logos/trufig/TrufigWatermark_Black.png +0 -0
- package/dist/assets/logos/trufig/TrufigWatermark_Light.png +0 -0
- package/dist/index.js +278 -7
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -306,6 +306,76 @@ function getAssetPath(assetType) {
|
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
308
|
}
|
|
309
|
+
// ============================================
|
|
310
|
+
// LOGO PATH RESOLUTION
|
|
311
|
+
// ============================================
|
|
312
|
+
/**
|
|
313
|
+
* Resolve a logo path to an absolute file path
|
|
314
|
+
* Handles both bundled and dev mode, with path sanitization
|
|
315
|
+
*/
|
|
316
|
+
function resolveLogoPath(logoPath) {
|
|
317
|
+
// Sanitize path to prevent directory traversal
|
|
318
|
+
const sanitized = logoPath
|
|
319
|
+
.replace(/^\/+/, '') // Remove leading slashes
|
|
320
|
+
.replace(/\.{2,}/g, '') // Remove .. sequences
|
|
321
|
+
.replace(/\/+/g, '/'); // Normalize multiple slashes
|
|
322
|
+
// Remove "logos/" prefix if present (manifest has /logos/xxx format)
|
|
323
|
+
const normalizedPath = sanitized.replace(/^logos\//, '');
|
|
324
|
+
if (IS_BUNDLED) {
|
|
325
|
+
// In bundled mode, logos are in dist/assets/logos/
|
|
326
|
+
const logosDir = path.join(BUNDLED_ASSETS, "logos");
|
|
327
|
+
return path.join(logosDir, normalizedPath);
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
// In dev mode, logos are in public/logos/
|
|
331
|
+
const logosDir = path.join(DEV_PROJECT_ROOT, "public/logos");
|
|
332
|
+
return path.join(logosDir, normalizedPath);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Get MIME type for image file based on extension
|
|
337
|
+
*/
|
|
338
|
+
function getImageMimeType(filePath) {
|
|
339
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
340
|
+
switch (ext) {
|
|
341
|
+
case '.png': return 'image/png';
|
|
342
|
+
case '.jpg':
|
|
343
|
+
case '.jpeg': return 'image/jpeg';
|
|
344
|
+
case '.svg': return 'image/svg+xml';
|
|
345
|
+
case '.gif': return 'image/gif';
|
|
346
|
+
case '.webp': return 'image/webp';
|
|
347
|
+
default: return 'application/octet-stream';
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Embed a logo as base64 image content for MCP responses
|
|
352
|
+
* Returns an MCP-compatible image content block or null if logo not found
|
|
353
|
+
*/
|
|
354
|
+
async function embedLogo(logoPath) {
|
|
355
|
+
try {
|
|
356
|
+
const resolvedPath = resolveLogoPath(logoPath);
|
|
357
|
+
if (!resolvedPath)
|
|
358
|
+
return null;
|
|
359
|
+
// Check if file exists
|
|
360
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
361
|
+
console.error(`Logo not found: ${resolvedPath}`);
|
|
362
|
+
return null;
|
|
363
|
+
}
|
|
364
|
+
// Read file as base64
|
|
365
|
+
const fileBuffer = fs.readFileSync(resolvedPath);
|
|
366
|
+
const base64Data = fileBuffer.toString('base64');
|
|
367
|
+
const mimeType = getImageMimeType(resolvedPath);
|
|
368
|
+
return {
|
|
369
|
+
type: "image",
|
|
370
|
+
data: base64Data,
|
|
371
|
+
mimeType,
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
catch (error) {
|
|
375
|
+
console.error(`Error embedding logo: ${error}`);
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
309
379
|
/**
|
|
310
380
|
* Detect output type from user's request/prompt
|
|
311
381
|
*/
|
|
@@ -545,6 +615,50 @@ server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
|
545
615
|
catch (e) {
|
|
546
616
|
// Components directory might not exist
|
|
547
617
|
}
|
|
618
|
+
// Add logo resources
|
|
619
|
+
try {
|
|
620
|
+
let logoList;
|
|
621
|
+
if (IS_BUNDLED) {
|
|
622
|
+
const manifestPath = getAssetPath("logos");
|
|
623
|
+
logoList = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
624
|
+
}
|
|
625
|
+
else {
|
|
626
|
+
// Scan directory in development
|
|
627
|
+
const logosDir = getAssetPath("logos");
|
|
628
|
+
function listLogoFiles(dir, prefix = "") {
|
|
629
|
+
let results = [];
|
|
630
|
+
if (!fs.existsSync(dir))
|
|
631
|
+
return results;
|
|
632
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
633
|
+
for (const entry of entries) {
|
|
634
|
+
if (entry.isDirectory()) {
|
|
635
|
+
results = [...results, ...listLogoFiles(path.join(dir, entry.name), `${prefix}${entry.name}/`)];
|
|
636
|
+
}
|
|
637
|
+
else if (/\.(png|svg|jpg|jpeg)$/i.test(entry.name)) {
|
|
638
|
+
results.push(`/logos/${prefix}${entry.name}`);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
return results;
|
|
642
|
+
}
|
|
643
|
+
logoList = listLogoFiles(logosDir);
|
|
644
|
+
}
|
|
645
|
+
for (const logoPath of logoList) {
|
|
646
|
+
// Convert /logos/sonance/file.png to sonance/file.png for URI
|
|
647
|
+
const uriPath = logoPath.replace(/^\/logos\//, '');
|
|
648
|
+
const fileName = path.basename(logoPath, path.extname(logoPath));
|
|
649
|
+
const folder = path.dirname(uriPath);
|
|
650
|
+
const mimeType = getImageMimeType(logoPath);
|
|
651
|
+
resources.push({
|
|
652
|
+
uri: `sonance://logo/${uriPath}`,
|
|
653
|
+
name: `${fileName} Logo`,
|
|
654
|
+
description: `${folder !== '.' ? folder + ' - ' : ''}Brand logo image file`,
|
|
655
|
+
mimeType: mimeType,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
catch (e) {
|
|
660
|
+
// Logo resources might not be available
|
|
661
|
+
}
|
|
548
662
|
return { resources };
|
|
549
663
|
});
|
|
550
664
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
@@ -572,6 +686,24 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
|
572
686
|
};
|
|
573
687
|
}
|
|
574
688
|
}
|
|
689
|
+
// Handle logo resources
|
|
690
|
+
if (uri.startsWith("sonance://logo/")) {
|
|
691
|
+
const logoPath = uri.replace("sonance://logo/", "");
|
|
692
|
+
const resolvedPath = resolveLogoPath(logoPath);
|
|
693
|
+
if (!resolvedPath || !fs.existsSync(resolvedPath)) {
|
|
694
|
+
throw new Error(`Logo not found: ${logoPath}`);
|
|
695
|
+
}
|
|
696
|
+
const imageBuffer = fs.readFileSync(resolvedPath);
|
|
697
|
+
const base64Data = imageBuffer.toString('base64');
|
|
698
|
+
const mimeType = getImageMimeType(resolvedPath);
|
|
699
|
+
return {
|
|
700
|
+
contents: [{
|
|
701
|
+
uri,
|
|
702
|
+
mimeType,
|
|
703
|
+
blob: base64Data, // Use blob for binary resources
|
|
704
|
+
}],
|
|
705
|
+
};
|
|
706
|
+
}
|
|
575
707
|
throw new Error(`Resource not found: ${uri}`);
|
|
576
708
|
});
|
|
577
709
|
// ============================================
|
|
@@ -639,6 +771,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
639
771
|
required: [],
|
|
640
772
|
},
|
|
641
773
|
},
|
|
774
|
+
{
|
|
775
|
+
name: "get_logo",
|
|
776
|
+
description: "Returns a brand logo image as base64-encoded data that AI can view and analyze. Use list_logos first to see available logos, then use this tool to retrieve the actual image.",
|
|
777
|
+
inputSchema: {
|
|
778
|
+
type: "object",
|
|
779
|
+
properties: {
|
|
780
|
+
logo_path: {
|
|
781
|
+
type: "string",
|
|
782
|
+
description: "The path to the logo from list_logos output (e.g., '/logos/sonance/Sonance_Logo_2C_Dark_RGB.png' or 'sonance/Sonance_Logo_2C_Dark_RGB.png')",
|
|
783
|
+
},
|
|
784
|
+
},
|
|
785
|
+
required: ["logo_path"],
|
|
786
|
+
},
|
|
787
|
+
},
|
|
642
788
|
{
|
|
643
789
|
name: "get_full_library",
|
|
644
790
|
description: "RECOMMENDED FOR APP REDESIGNS & FULL APPLICATIONS: Returns the complete component library including brand guidelines, CSS theme, utilities, and all component source code. USE THIS TOOL when the user asks to: redesign an application, rebrand an app, build a full application, update an entire codebase to use Sonance/IPORT/Blaze brand, or any multi-file/multi-component project. This is the go-to tool for comprehensive brand implementation across an entire project.",
|
|
@@ -650,7 +796,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
650
796
|
},
|
|
651
797
|
{
|
|
652
798
|
name: "design_component",
|
|
653
|
-
description: "Returns brand-specific design tokens, colors, implementation rules, and logo
|
|
799
|
+
description: "Returns brand-specific design tokens, colors, implementation rules, and AUTO-EMBEDS the correct logo image(s) for designing a component. For UI outputs, embeds both light and dark theme logos. Smart defaults: Sonance+James+IPORT lockup as default logo. Auto-detects output type (ui/doc/marketing/tech).",
|
|
654
800
|
inputSchema: {
|
|
655
801
|
type: "object",
|
|
656
802
|
properties: {
|
|
@@ -666,8 +812,8 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
666
812
|
},
|
|
667
813
|
logo_preference: {
|
|
668
814
|
type: "string",
|
|
669
|
-
enum: ["default", "sonance", "iport", "blaze"],
|
|
670
|
-
description: "Which logo to use. 'default' = Sonance+James+IPORT lockup. Or specify 'sonance', 'iport', or '
|
|
815
|
+
enum: ["default", "sonance", "iport", "blaze", "james"],
|
|
816
|
+
description: "Which logo to use. 'default' = Sonance+James+IPORT lockup. Or specify 'sonance', 'iport', 'blaze', or 'james' for individual brand logos. Defaults to 'default' if not specified.",
|
|
671
817
|
},
|
|
672
818
|
output_type: {
|
|
673
819
|
type: "string",
|
|
@@ -755,7 +901,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
755
901
|
},
|
|
756
902
|
{
|
|
757
903
|
name: "rebrand_document",
|
|
758
|
-
description: "Returns universal rebranding instructions for converting ANY existing document to a specific brand (Sonance, IPORT, or Blaze)
|
|
904
|
+
description: "Returns universal rebranding instructions for converting ANY existing document to a specific brand (Sonance, IPORT, or Blaze) and AUTO-EMBEDS both light and dark logo variants for immediate use. Provides color replacements, font substitutions, and logo placement rules. Default: Sonance+James+IPORT lockup for Sonance brand.",
|
|
759
905
|
inputSchema: {
|
|
760
906
|
type: "object",
|
|
761
907
|
properties: {
|
|
@@ -941,6 +1087,66 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
941
1087
|
};
|
|
942
1088
|
}
|
|
943
1089
|
}
|
|
1090
|
+
case "get_logo": {
|
|
1091
|
+
const logoPath = args.logo_path;
|
|
1092
|
+
if (!logoPath) {
|
|
1093
|
+
return {
|
|
1094
|
+
content: [{ type: "text", text: "Error: logo_path is required. Use list_logos to see available logos." }],
|
|
1095
|
+
isError: true,
|
|
1096
|
+
};
|
|
1097
|
+
}
|
|
1098
|
+
try {
|
|
1099
|
+
const resolvedPath = resolveLogoPath(logoPath);
|
|
1100
|
+
if (!resolvedPath) {
|
|
1101
|
+
return {
|
|
1102
|
+
content: [{ type: "text", text: `Error: Invalid logo path: ${logoPath}` }],
|
|
1103
|
+
isError: true,
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
if (!fs.existsSync(resolvedPath)) {
|
|
1107
|
+
// Try to help user find the right logo
|
|
1108
|
+
let suggestion = '\n\nUse list_logos to see available logos.';
|
|
1109
|
+
if (IS_BUNDLED) {
|
|
1110
|
+
try {
|
|
1111
|
+
const manifestPath = getAssetPath("logos");
|
|
1112
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf-8"));
|
|
1113
|
+
suggestion = `\n\nAvailable logos include:\n${manifest.slice(0, 5).map((p) => ` - ${p}`).join('\n')}\n ... and ${manifest.length - 5} more. Use list_logos to see all.`;
|
|
1114
|
+
}
|
|
1115
|
+
catch {
|
|
1116
|
+
// Keep default suggestion
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
return {
|
|
1120
|
+
content: [{ type: "text", text: `Error: Logo not found: ${logoPath}${suggestion}` }],
|
|
1121
|
+
isError: true,
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
// Read and encode the image
|
|
1125
|
+
const imageBuffer = fs.readFileSync(resolvedPath);
|
|
1126
|
+
const base64Data = imageBuffer.toString('base64');
|
|
1127
|
+
const mimeType = getImageMimeType(resolvedPath);
|
|
1128
|
+
const fileName = path.basename(resolvedPath);
|
|
1129
|
+
return {
|
|
1130
|
+
content: [
|
|
1131
|
+
{
|
|
1132
|
+
type: "image",
|
|
1133
|
+
data: base64Data,
|
|
1134
|
+
mimeType: mimeType,
|
|
1135
|
+
},
|
|
1136
|
+
{
|
|
1137
|
+
type: "text",
|
|
1138
|
+
text: `**Logo:** ${fileName}\n**Path:** ${logoPath}\n**Size:** ${imageBuffer.length} bytes\n**Format:** ${mimeType}`,
|
|
1139
|
+
},
|
|
1140
|
+
],
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
catch (e) {
|
|
1144
|
+
return {
|
|
1145
|
+
content: [{ type: "text", text: `Error reading logo: ${e}` }],
|
|
1146
|
+
isError: true,
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
944
1150
|
case "get_full_library": {
|
|
945
1151
|
try {
|
|
946
1152
|
let fullLibrary = "# Sonance Component Library\n\n";
|
|
@@ -1044,11 +1250,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
1044
1250
|
light: "/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png",
|
|
1045
1251
|
dark: "/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png",
|
|
1046
1252
|
},
|
|
1253
|
+
james: {
|
|
1254
|
+
light: "/logos/james/James_Logo_Black_RGB.png",
|
|
1255
|
+
dark: "/logos/james/James_Logo_Reverse_RGB.png",
|
|
1256
|
+
},
|
|
1047
1257
|
};
|
|
1048
1258
|
const logoPath = logoMap[logoPreference]?.[theme] || logoMap.default[theme];
|
|
1049
1259
|
const logoPreferenceLabel = logoPreference === "default"
|
|
1050
1260
|
? "Sonance + James + IPORT Lockup"
|
|
1051
|
-
:
|
|
1261
|
+
: logoPreference === "james"
|
|
1262
|
+
? "James Only"
|
|
1263
|
+
: `${logoPreference.charAt(0).toUpperCase() + logoPreference.slice(1)} Only`;
|
|
1052
1264
|
// Brand-specific design tokens
|
|
1053
1265
|
const brandTokens = {
|
|
1054
1266
|
sonance: {
|
|
@@ -1524,8 +1736,35 @@ ${outputTypeGuidance[detectedOutputType]}
|
|
|
1524
1736
|
|
|
1525
1737
|
Now design the **${component_description}** following these tokens and principles.`;
|
|
1526
1738
|
}
|
|
1739
|
+
// Embed logos in response
|
|
1740
|
+
const contentBlocks = [];
|
|
1741
|
+
if (isDualThemeMode) {
|
|
1742
|
+
// Dual-theme mode: embed both light and dark theme logos
|
|
1743
|
+
const lightLogoPath = logoMap[logoPreference]?.light || logoMap.default.light;
|
|
1744
|
+
const darkLogoPath = logoMap[logoPreference]?.dark || logoMap.default.dark;
|
|
1745
|
+
const lightLogo = await embedLogo(lightLogoPath);
|
|
1746
|
+
const darkLogo = await embedLogo(darkLogoPath);
|
|
1747
|
+
if (lightLogo) {
|
|
1748
|
+
contentBlocks.push({ type: "text", text: `## Logo for Light Backgrounds\n**Path:** \`${lightLogoPath}\`` });
|
|
1749
|
+
contentBlocks.push(lightLogo);
|
|
1750
|
+
}
|
|
1751
|
+
if (darkLogo) {
|
|
1752
|
+
contentBlocks.push({ type: "text", text: `## Logo for Dark Backgrounds\n**Path:** \`${darkLogoPath}\`` });
|
|
1753
|
+
contentBlocks.push(darkLogo);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
else {
|
|
1757
|
+
// Single-theme mode: embed the appropriate logo
|
|
1758
|
+
const embeddedLogo = await embedLogo(logoPath);
|
|
1759
|
+
if (embeddedLogo) {
|
|
1760
|
+
contentBlocks.push({ type: "text", text: `## Brand Logo (${theme === "light" ? "for Light Backgrounds" : "for Dark Backgrounds"})\n**Path:** \`${logoPath}\`` });
|
|
1761
|
+
contentBlocks.push(embeddedLogo);
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
// Add the main response text
|
|
1765
|
+
contentBlocks.push({ type: "text", text: response });
|
|
1527
1766
|
return {
|
|
1528
|
-
content:
|
|
1767
|
+
content: contentBlocks,
|
|
1529
1768
|
};
|
|
1530
1769
|
}
|
|
1531
1770
|
case "evaluate_design": {
|
|
@@ -2668,8 +2907,40 @@ ${rebrandArgs.source_format === "word" ? `
|
|
|
2668
2907
|
|
|
2669
2908
|
**Remember:** The goal is to make the document unmistakably ${palette.name} while preserving its original structure and content.
|
|
2670
2909
|
`;
|
|
2910
|
+
// Embed logos for rebrand_document
|
|
2911
|
+
// Use the Sonance+James+IPORT lockup as default for Sonance brand
|
|
2912
|
+
const rebrandLogoMap = {
|
|
2913
|
+
sonance: {
|
|
2914
|
+
light: "/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Dark.png",
|
|
2915
|
+
dark: "/logos/sonance-james-iport/Sonance_James_IPORT_Lockup_Light.png",
|
|
2916
|
+
},
|
|
2917
|
+
iport: {
|
|
2918
|
+
light: "/logos/iport/IPORT_Sonance_LockUp_2C_Dark_RGB.png",
|
|
2919
|
+
dark: "/logos/iport/IPORT_Sonance_LockUp_2C_Light_RGB.png",
|
|
2920
|
+
},
|
|
2921
|
+
blaze: {
|
|
2922
|
+
light: "/logos/blaze/BlazeBySonance_Logo_Lockup_3C_Dark_RGB_05162025.png",
|
|
2923
|
+
dark: "/logos/blaze/BlazeBySonance_Logo_Lockup_2C_Light_RGB_05162025.png",
|
|
2924
|
+
},
|
|
2925
|
+
};
|
|
2926
|
+
const rebrandContentBlocks = [];
|
|
2927
|
+
// For documents, provide both light and dark logo variants
|
|
2928
|
+
const lightLogoPath = rebrandLogoMap[targetBrand].light;
|
|
2929
|
+
const darkLogoPath = rebrandLogoMap[targetBrand].dark;
|
|
2930
|
+
const lightLogo = await embedLogo(lightLogoPath);
|
|
2931
|
+
const darkLogo = await embedLogo(darkLogoPath);
|
|
2932
|
+
if (lightLogo) {
|
|
2933
|
+
rebrandContentBlocks.push({ type: "text", text: `## Logo for Light Backgrounds\n**Use on white/light document backgrounds**\n**Path:** \`${lightLogoPath}\`` });
|
|
2934
|
+
rebrandContentBlocks.push(lightLogo);
|
|
2935
|
+
}
|
|
2936
|
+
if (darkLogo) {
|
|
2937
|
+
rebrandContentBlocks.push({ type: "text", text: `## Logo for Dark Backgrounds\n**Use on dark/colored document backgrounds**\n**Path:** \`${darkLogoPath}\`` });
|
|
2938
|
+
rebrandContentBlocks.push(darkLogo);
|
|
2939
|
+
}
|
|
2940
|
+
// Add the main guide text
|
|
2941
|
+
rebrandContentBlocks.push({ type: "text", text: rebrandGuide });
|
|
2671
2942
|
return {
|
|
2672
|
-
content:
|
|
2943
|
+
content: rebrandContentBlocks,
|
|
2673
2944
|
};
|
|
2674
2945
|
}
|
|
2675
2946
|
default:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.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",
|