sonance-brand-mcp 1.3.39 → 1.3.41

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.
@@ -504,6 +504,8 @@ export async function POST(request: Request) {
504
504
  // PHASE 1+2: LLM-driven smart file discovery
505
505
  // The LLM analyzes the screenshot and deduces component names, code patterns, and visible text
506
506
  let smartSearchFiles: { path: string; content: string }[] = [];
507
+ let recommendedFile: { path: string; reason: string } | null = null;
508
+
507
509
  if (screenshot) {
508
510
  debugLog("Starting Phase 1: LLM screenshot analysis");
509
511
  const analysis = await analyzeScreenshotForSearch(screenshot, userPrompt, apiKey);
@@ -516,13 +518,39 @@ export async function POST(request: Request) {
516
518
  // PHASE 2: Smart search using component names, text, and code patterns
517
519
  const searchResults = searchFilesSmart(analysis, projectRoot, 10);
518
520
  smartSearchFiles = searchResults.map(r => ({ path: r.path, content: r.content }));
521
+
522
+ // Identify the recommended file (highest scoring file, prefer filename matches)
523
+ if (searchResults.length > 0) {
524
+ // Find the best filename match first
525
+ const filenameMatch = searchResults.find(r =>
526
+ analysis.componentNames.some(name =>
527
+ r.path.toLowerCase().includes(name.toLowerCase())
528
+ )
529
+ );
530
+
531
+ if (filenameMatch) {
532
+ recommendedFile = {
533
+ path: filenameMatch.path,
534
+ reason: `Component name match from screenshot analysis`
535
+ };
536
+ } else {
537
+ // Fall back to highest score
538
+ recommendedFile = {
539
+ path: searchResults[0].path,
540
+ reason: `Highest content match score (${searchResults[0].score} points)`
541
+ };
542
+ }
543
+ debugLog("Recommended file for editing", recommendedFile);
544
+ }
545
+
519
546
  debugLog("Phase 1+2 complete", {
520
547
  analysis: {
521
548
  visibleText: analysis.visibleText.slice(0, 5),
522
549
  componentNames: analysis.componentNames,
523
550
  codePatterns: analysis.codePatterns.slice(0, 5)
524
551
  },
525
- filesFound: smartSearchFiles.map(f => f.path)
552
+ filesFound: smartSearchFiles.map(f => f.path),
553
+ recommendedFile
526
554
  });
527
555
  }
528
556
  }
@@ -625,9 +653,47 @@ GLOBALS.CSS (relevant theme variables):
625
653
  ${pageContext.globalsCSS.substring(0, 2000)}${pageContext.globalsCSS.length > 2000 ? "\n/* ... (truncated) */" : ""}
626
654
  \`\`\`
627
655
 
628
- VALID FILES YOU MAY EDIT:
629
- ${pageContext.pageFile ? `- ${pageContext.pageFile}` : ""}
630
- ${pageContext.componentSources.map((c) => `- ${c.path}`).join("\n")}
656
+ `;
657
+
658
+ // Add recommendation block just before VALID FILES if we have one
659
+ if (recommendedFile) {
660
+ textContent += `═══════════════════════════════════════════════════════════════════════════════
661
+ ⚡ RECOMMENDED FILE TO EDIT
662
+ ═══════════════════════════════════════════════════════════════════════════════
663
+
664
+ Based on the screenshot analysis, the component you should edit is:
665
+ **${recommendedFile.path}**
666
+ Reason: ${recommendedFile.reason}
667
+
668
+ The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
669
+ YOU MUST edit the recommended file unless you have a specific reason not to.
670
+
671
+ `;
672
+ }
673
+
674
+ // Build VALID FILES list with recommended file first and marked
675
+ const validFilesList: string[] = [];
676
+ const recommendedPath = recommendedFile?.path;
677
+
678
+ // Add recommended file first with marker
679
+ if (recommendedPath) {
680
+ validFilesList.push(`- ${recommendedPath} (*** RECOMMENDED - EDIT THIS FILE ***)`);
681
+ }
682
+
683
+ // Add page file (if not the recommended file)
684
+ if (pageContext.pageFile && pageContext.pageFile !== recommendedPath) {
685
+ validFilesList.push(`- ${pageContext.pageFile}`);
686
+ }
687
+
688
+ // Add other component sources (excluding recommended file)
689
+ for (const comp of pageContext.componentSources) {
690
+ if (comp.path !== recommendedPath) {
691
+ validFilesList.push(`- ${comp.path}`);
692
+ }
693
+ }
694
+
695
+ textContent += `VALID FILES YOU MAY EDIT:
696
+ ${validFilesList.join("\n")}
631
697
 
632
698
  INSTRUCTIONS:
633
699
  1. Look at the screenshot and identify elements mentioned in the user's request
@@ -636,6 +702,7 @@ INSTRUCTIONS:
636
702
  4. PRESERVE all existing logic, hooks, API calls, and error handling
637
703
  5. Return the FULL file content (no truncation, no "// ... existing ..." comments)
638
704
  6. Only use file paths from the VALID FILES list above
705
+ 7. ALWAYS prioritize the (*** RECOMMENDED ***) file if one is marked - it contains the UI you see in the screenshot
639
706
 
640
707
  CRITICAL: Your modified file should have approximately the same number of lines as the original. If the original has 200 lines and your output has 50 lines, you have made a mistake.`;
641
708
 
@@ -514,6 +514,8 @@ export async function POST(request: Request) {
514
514
  // PHASE 1+2: LLM-driven smart file discovery
515
515
  // The LLM analyzes the screenshot and deduces component names, code patterns, and visible text
516
516
  let smartSearchFiles: { path: string; content: string }[] = [];
517
+ let recommendedFile: { path: string; reason: string } | null = null;
518
+
517
519
  if (screenshot) {
518
520
  debugLog("Starting Phase 1: LLM screenshot analysis");
519
521
  const analysis = await analyzeScreenshotForSearch(screenshot, userPrompt, apiKey);
@@ -526,13 +528,39 @@ export async function POST(request: Request) {
526
528
  // PHASE 2: Smart search using component names, text, and code patterns
527
529
  const searchResults = searchFilesSmart(analysis, projectRoot, 10);
528
530
  smartSearchFiles = searchResults.map(r => ({ path: r.path, content: r.content }));
531
+
532
+ // Identify the recommended file (highest scoring file, prefer filename matches)
533
+ if (searchResults.length > 0) {
534
+ // Find the best filename match first
535
+ const filenameMatch = searchResults.find(r =>
536
+ analysis.componentNames.some(name =>
537
+ r.path.toLowerCase().includes(name.toLowerCase())
538
+ )
539
+ );
540
+
541
+ if (filenameMatch) {
542
+ recommendedFile = {
543
+ path: filenameMatch.path,
544
+ reason: `Component name match from screenshot analysis`
545
+ };
546
+ } else {
547
+ // Fall back to highest score
548
+ recommendedFile = {
549
+ path: searchResults[0].path,
550
+ reason: `Highest content match score (${searchResults[0].score} points)`
551
+ };
552
+ }
553
+ debugLog("Recommended file for editing", recommendedFile);
554
+ }
555
+
529
556
  debugLog("Phase 1+2 complete", {
530
557
  analysis: {
531
558
  visibleText: analysis.visibleText.slice(0, 5),
532
559
  componentNames: analysis.componentNames,
533
560
  codePatterns: analysis.codePatterns.slice(0, 5)
534
561
  },
535
- filesFound: smartSearchFiles.map(f => f.path)
562
+ filesFound: smartSearchFiles.map(f => f.path),
563
+ recommendedFile
536
564
  });
537
565
  }
538
566
  }
@@ -635,9 +663,47 @@ GLOBALS.CSS (relevant theme variables):
635
663
  ${pageContext.globalsCSS.substring(0, 2000)}${pageContext.globalsCSS.length > 2000 ? "\n/* ... (truncated) */" : ""}
636
664
  \`\`\`
637
665
 
638
- VALID FILES YOU MAY EDIT:
639
- ${pageContext.pageFile ? `- ${pageContext.pageFile}` : ""}
640
- ${pageContext.componentSources.map((c) => `- ${c.path}`).join("\n")}
666
+ `;
667
+
668
+ // Add recommendation block just before VALID FILES if we have one
669
+ if (recommendedFile) {
670
+ textContent += `═══════════════════════════════════════════════════════════════════════════════
671
+ ⚡ RECOMMENDED FILE TO EDIT
672
+ ═══════════════════════════════════════════════════════════════════════════════
673
+
674
+ Based on the screenshot analysis, the component you should edit is:
675
+ **${recommendedFile.path}**
676
+ Reason: ${recommendedFile.reason}
677
+
678
+ The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
679
+ YOU MUST edit the recommended file unless you have a specific reason not to.
680
+
681
+ `;
682
+ }
683
+
684
+ // Build VALID FILES list with recommended file first and marked
685
+ const validFilesList: string[] = [];
686
+ const recommendedPath = recommendedFile?.path;
687
+
688
+ // Add recommended file first with marker
689
+ if (recommendedPath) {
690
+ validFilesList.push(`- ${recommendedPath} (*** RECOMMENDED - EDIT THIS FILE ***)`);
691
+ }
692
+
693
+ // Add page file (if not the recommended file)
694
+ if (pageContext.pageFile && pageContext.pageFile !== recommendedPath) {
695
+ validFilesList.push(`- ${pageContext.pageFile}`);
696
+ }
697
+
698
+ // Add other component sources (excluding recommended file)
699
+ for (const comp of pageContext.componentSources) {
700
+ if (comp.path !== recommendedPath) {
701
+ validFilesList.push(`- ${comp.path}`);
702
+ }
703
+ }
704
+
705
+ textContent += `VALID FILES YOU MAY EDIT:
706
+ ${validFilesList.join("\n")}
641
707
 
642
708
  INSTRUCTIONS:
643
709
  1. Look at the screenshot and identify elements mentioned in the user's request
@@ -646,6 +712,7 @@ INSTRUCTIONS:
646
712
  4. Generate complete modified code for each file
647
713
  5. Provide previewCSS for immediate visual feedback
648
714
  6. Return as JSON in the specified format
715
+ 7. ALWAYS prioritize the (*** RECOMMENDED ***) file if one is marked - it contains the UI you see in the screenshot
649
716
 
650
717
  CRITICAL: Only use file paths from the VALID FILES list above. Do NOT create new files.`;
651
718
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sonance-brand-mcp",
3
- "version": "1.3.39",
3
+ "version": "1.3.41",
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",