sonance-brand-mcp 1.3.117 → 1.3.118

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +198 -12
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2635,6 +2635,25 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
2635
2635
  required: ["logo_path"],
2636
2636
  },
2637
2637
  },
2638
+ {
2639
+ name: "get_logo_base64",
2640
+ description: "Returns a logo as base64-encoded data URL ready for embedding in React artifacts, HTML, or web applications. USE THIS for artifacts instead of drawing/approximating logos. Returns a data URL that works directly in <img src='...'> tags. CRITICAL: NEVER draw, recreate, or approximate logos with SVG, CSS, or styled text - always use this tool to get the actual image data.",
2641
+ inputSchema: {
2642
+ type: "object",
2643
+ properties: {
2644
+ logo_path: {
2645
+ type: "string",
2646
+ description: "Path to the logo from list_logos output (e.g., 'sonance/Sonance_Logo_2C_Dark_RGB.png')",
2647
+ },
2648
+ format: {
2649
+ type: "string",
2650
+ enum: ["dataUrl", "base64", "both"],
2651
+ description: "Output format. 'dataUrl' for img src (default), 'base64' for raw data, 'both' for both formats",
2652
+ },
2653
+ },
2654
+ required: ["logo_path"],
2655
+ },
2656
+ },
2638
2657
  {
2639
2658
  name: "diagnose_logos",
2640
2659
  description: "Diagnose logo loading issues. Returns validation status, path resolution examples, and environment info. Use this when logos fail to embed or appear in responses.",
@@ -3109,6 +3128,8 @@ ${formatCodeBlock(content, { language: "typescript", filename: "lib/utils.ts" })
3109
3128
  const base64Data = imageBuffer.toString('base64');
3110
3129
  const mimeType = getImageMimeType(resolvedPath);
3111
3130
  const fileName = path.basename(resolvedPath);
3131
+ // Create data URL for artifact use
3132
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3112
3133
  // Determine logo variant info for recommendations
3113
3134
  const isLightLogo = /light|reverse|white/i.test(fileName);
3114
3135
  const isDarkLogo = /dark|black/i.test(fileName);
@@ -3139,28 +3160,45 @@ ${variantSuggestion}
3139
3160
 
3140
3161
  ---
3141
3162
 
3142
- ### Implementation (Next.js with next/image)
3163
+ ## CRITICAL: Logo Usage Rules
3164
+
3165
+ > **NEVER draw, recreate, or approximate this logo.** This includes:
3166
+ > - SVG drawings or paths
3167
+ > - Styled text (e.g., colored letters spelling "SONANCE")
3168
+ > - CSS recreations or shapes
3169
+ > - Unicode character approximations
3170
+ >
3171
+ > **ALWAYS use the actual image data provided below.**
3172
+
3173
+ ---
3174
+
3175
+ ### For React Artifacts (USE THIS - includes actual image data)
3176
+ \`\`\`tsx
3177
+ <img
3178
+ src="${dataUrl}"
3179
+ alt="${brandName}"
3180
+ className="h-10 w-auto"
3181
+ />
3182
+ \`\`\`
3183
+
3184
+ ### For Next.js Projects (with file system access)
3143
3185
  \`\`\`tsx
3144
3186
  import Image from 'next/image';
3145
3187
 
3146
- // In your component:
3147
3188
  <Image
3148
3189
  src="${normalizedPath}"
3149
3190
  alt="${brandName}"
3150
3191
  width={150}
3151
3192
  height={40}
3152
3193
  className="h-10 w-auto"
3153
- priority // Add if logo is above the fold
3194
+ priority
3154
3195
  />
3155
3196
  \`\`\`
3156
3197
 
3157
- ### Implementation (React/HTML)
3158
- \`\`\`tsx
3159
- <img
3160
- src="${normalizedPath}"
3161
- alt="${brandName}"
3162
- className="h-10 w-auto"
3163
- />
3198
+ ### Base64 Data URL (copy for artifacts)
3199
+ Use this data URL directly in img src for artifacts:
3200
+ \`\`\`
3201
+ ${dataUrl}
3164
3202
  \`\`\`
3165
3203
 
3166
3204
  ### With Dark Mode Support
@@ -3169,12 +3207,12 @@ import Image from 'next/image';
3169
3207
  <img
3170
3208
  src="${normalizedPath}"
3171
3209
  alt="${brandName}"
3172
- className="h-10 w-auto dark:hidden" {/* Light mode */}
3210
+ className="h-10 w-auto dark:hidden"
3173
3211
  />
3174
3212
  <img
3175
3213
  src="${normalizedPath.replace(/dark/gi, 'Light').replace(/black/gi, 'Reverse')}"
3176
3214
  alt="${brandName}"
3177
- className="h-10 w-auto hidden dark:block" {/* Dark mode */}
3215
+ className="h-10 w-auto hidden dark:block"
3178
3216
  />
3179
3217
  \`\`\`
3180
3218
 
@@ -3211,6 +3249,98 @@ import Image from 'next/image';
3211
3249
  };
3212
3250
  }
3213
3251
  }
3252
+ case "get_logo_base64": {
3253
+ const logoArgs = args;
3254
+ const logoPath = logoArgs.logo_path;
3255
+ const format = logoArgs.format || "dataUrl";
3256
+ if (!logoPath) {
3257
+ return {
3258
+ content: [{ type: "text", text: "Error: logo_path is required. Use list_logos to see available logos." }],
3259
+ isError: true,
3260
+ };
3261
+ }
3262
+ try {
3263
+ const resolvedPath = resolveLogoPath(logoPath);
3264
+ if (!resolvedPath) {
3265
+ return {
3266
+ content: [{ type: "text", text: `Error: Invalid logo path: ${logoPath}` }],
3267
+ isError: true,
3268
+ };
3269
+ }
3270
+ if (!fs.existsSync(resolvedPath)) {
3271
+ return {
3272
+ content: [{ type: "text", text: `Error: Logo not found: ${logoPath}. Use list_logos to see available logos.` }],
3273
+ isError: true,
3274
+ };
3275
+ }
3276
+ // Read and encode the image
3277
+ const imageBuffer = fs.readFileSync(resolvedPath);
3278
+ const base64Data = imageBuffer.toString('base64');
3279
+ const mimeType = getImageMimeType(resolvedPath);
3280
+ const fileName = path.basename(resolvedPath);
3281
+ const dataUrl = `data:${mimeType};base64,${base64Data}`;
3282
+ // Determine brand for alt text
3283
+ const brandMatch = logoPath.match(/\/(sonance|iport|blaze|james|trufig)/i);
3284
+ const brandName = brandMatch ? brandMatch[1].charAt(0).toUpperCase() + brandMatch[1].slice(1) : "Brand";
3285
+ // Build response based on format
3286
+ let responseText = `## Logo for Artifacts: ${fileName}
3287
+
3288
+ > **CRITICAL:** Use ONLY this image data. NEVER draw, recreate, or approximate this logo with SVG, CSS, styled text, or any other method.
3289
+
3290
+ ### Ready-to-Use Code (copy this directly)
3291
+ \`\`\`tsx
3292
+ <img
3293
+ src="${dataUrl}"
3294
+ alt="${brandName}"
3295
+ className="h-10 w-auto"
3296
+ />
3297
+ \`\`\`
3298
+ `;
3299
+ if (format === "dataUrl" || format === "both") {
3300
+ responseText += `
3301
+ ### Data URL (use in img src)
3302
+ \`\`\`
3303
+ ${dataUrl}
3304
+ \`\`\`
3305
+ `;
3306
+ }
3307
+ if (format === "base64" || format === "both") {
3308
+ responseText += `
3309
+ ### Raw Base64 Data
3310
+ \`\`\`
3311
+ ${base64Data}
3312
+ \`\`\`
3313
+
3314
+ **MIME Type:** ${mimeType}
3315
+ `;
3316
+ }
3317
+ responseText += `
3318
+ ---
3319
+
3320
+ **File:** ${fileName}
3321
+ **Size:** ${imageBuffer.length} bytes
3322
+ `;
3323
+ return {
3324
+ content: [
3325
+ {
3326
+ type: "image",
3327
+ data: base64Data,
3328
+ mimeType: mimeType,
3329
+ },
3330
+ {
3331
+ type: "text",
3332
+ text: responseText,
3333
+ },
3334
+ ],
3335
+ };
3336
+ }
3337
+ catch (e) {
3338
+ return {
3339
+ content: [{ type: "text", text: `Error reading logo: ${e}` }],
3340
+ isError: true,
3341
+ };
3342
+ }
3343
+ }
3214
3344
  case "diagnose_logos": {
3215
3345
  // Run validation and collect diagnostic info
3216
3346
  const validation = validateLogoMap();
@@ -3994,6 +4124,28 @@ Now design the **${component_description}** following these tokens and principle
3994
4124
  // Single-theme mode: embed the appropriate logo
3995
4125
  await embedLogoWithFeedback(logoPath, `Brand Logo (${theme === "light" ? "for Light Backgrounds" : "for Dark Backgrounds"})`, contentBlocks);
3996
4126
  }
4127
+ // Add critical logo usage warning
4128
+ contentBlocks.push({
4129
+ type: "text",
4130
+ text: `## Logo Usage Warning
4131
+
4132
+ > **CRITICAL:** The logo image(s) shown above are the ONLY acceptable representations.
4133
+ >
4134
+ > **NEVER:**
4135
+ > - Draw the logo with SVG paths or shapes
4136
+ > - Recreate it with styled text or colored letters
4137
+ > - Approximate it with CSS or Unicode characters
4138
+ >
4139
+ > **ALWAYS:**
4140
+ > - Use the embedded image directly in your artifact
4141
+ > - Or use \`get_logo_base64\` for a ready-to-use data URL
4142
+ > - If you cannot embed the image, use placeholder text: "[Logo: ${brand.charAt(0).toUpperCase() + brand.slice(1)}]"
4143
+
4144
+ To get the logo as a base64 data URL for artifacts, use:
4145
+ \`\`\`
4146
+ get_logo_base64({ logo_path: "${logoPath}" })
4147
+ \`\`\``,
4148
+ });
3997
4149
  // Add the main response text
3998
4150
  contentBlocks.push({ type: "text", text: response });
3999
4151
  return {
@@ -5031,6 +5183,23 @@ ${palette.preferredTheme === "dark" ? `- **Note**: ${palette.name} prefers dark
5031
5183
  type: "text",
5032
5184
  text: `## Logo Usage\n\nTo add the logo to your document:\n1. Save the appropriate logo image above (right-click → Save as)\n2. Use the saved path in your code:\n\n**Word (python-docx):**\n\`\`\`python\ndoc.add_picture('logo_dark.png', width=Inches(2)) # For light backgrounds\n\`\`\`\n\n**PDF (ReportLab):**\n\`\`\`python\ncontent.append(Image('logo_dark.png', width=2*inch, height=0.5*inch))\n\`\`\`\n`,
5033
5185
  });
5186
+ // Add critical logo usage warning
5187
+ templateContentBlocks.push({
5188
+ type: "text",
5189
+ text: `## Logo Warning
5190
+
5191
+ > **CRITICAL:** Use ONLY the actual logo image files shown above.
5192
+ >
5193
+ > **NEVER:**
5194
+ > - Draw the logo with shapes or vector tools in your document
5195
+ > - Recreate it with styled text or colored letters
5196
+ > - Use any visual approximation or placeholder
5197
+ >
5198
+ > **ALWAYS:**
5199
+ > - Save and embed the actual PNG image file
5200
+ > - Use the code snippets above that reference the saved image file
5201
+ > - The logo images are embedded above - save them directly`,
5202
+ });
5034
5203
  // Add the main template text
5035
5204
  templateContentBlocks.push({ type: "text", text: template });
5036
5205
  return {
@@ -5322,6 +5491,23 @@ ${rebrandArgs.source_format === "word" ? `
5322
5491
  text: `> **Logo Note:** Brand logos could not be embedded automatically. Download the appropriate ${palette.name} logo from your brand assets folder or use the \`get_logo\` tool.`,
5323
5492
  });
5324
5493
  }
5494
+ // Add critical logo usage warning
5495
+ rebrandContentBlocks.push({
5496
+ type: "text",
5497
+ text: `## Logo Usage Warning
5498
+
5499
+ > **CRITICAL:** When adding the logo to your document, use the ACTUAL image files shown above.
5500
+ >
5501
+ > **NEVER:**
5502
+ > - Draw the logo with shapes or vector tools
5503
+ > - Recreate it with styled text or colored letters
5504
+ > - Use any visual approximation
5505
+ >
5506
+ > **ALWAYS:**
5507
+ > - Download and embed the actual logo image
5508
+ > - Or use \`get_logo_base64\` for a data URL for web/HTML
5509
+ > - For Word/PDF: Save the image above and use it directly`,
5510
+ });
5325
5511
  // Add the main guide text
5326
5512
  rebrandContentBlocks.push({ type: "text", text: rebrandGuide });
5327
5513
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.3.117",
3
+ "version": "1.3.118",
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",