sonance-brand-mcp 1.3.39 → 1.3.40

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
  }
@@ -569,6 +597,22 @@ User Request: "${userPrompt}"
569
597
 
570
598
  `;
571
599
 
600
+ // Add recommendation if smart search identified a best match
601
+ if (recommendedFile) {
602
+ textContent += `═══════════════════════════════════════════════════════════════════════════════
603
+ ⚡ RECOMMENDED FILE TO EDIT
604
+ ═══════════════════════════════════════════════════════════════════════════════
605
+
606
+ Based on the screenshot analysis, the component you should edit is:
607
+ **${recommendedFile.path}**
608
+ Reason: ${recommendedFile.reason}
609
+
610
+ The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
611
+ STRONGLY PREFER editing the recommended file unless you have a specific reason not to.
612
+
613
+ `;
614
+ }
615
+
572
616
  if (focusedElements && focusedElements.length > 0) {
573
617
  textContent += `FOCUSED ELEMENTS (user clicked on these):
574
618
  ${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
@@ -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
  }
@@ -579,6 +607,22 @@ User Request: "${userPrompt}"
579
607
 
580
608
  `;
581
609
 
610
+ // Add recommendation if smart search identified a best match
611
+ if (recommendedFile) {
612
+ textContent += `═══════════════════════════════════════════════════════════════════════════════
613
+ ⚡ RECOMMENDED FILE TO EDIT
614
+ ═══════════════════════════════════════════════════════════════════════════════
615
+
616
+ Based on the screenshot analysis, the component you should edit is:
617
+ **${recommendedFile.path}**
618
+ Reason: ${recommendedFile.reason}
619
+
620
+ The page file (${pageContext.pageFile}) is just a wrapper - the actual UI elements are in the component above.
621
+ STRONGLY PREFER editing the recommended file unless you have a specific reason not to.
622
+
623
+ `;
624
+ }
625
+
582
626
  if (focusedElements && focusedElements.length > 0) {
583
627
  textContent += `FOCUSED ELEMENTS (user clicked on these):
584
628
  ${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
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.40",
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",