sonance-brand-mcp 1.3.55 → 1.3.56
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.
|
@@ -686,8 +686,9 @@ export async function POST(request: Request) {
|
|
|
686
686
|
const messageContent: Anthropic.MessageCreateParams["messages"][0]["content"] = [];
|
|
687
687
|
|
|
688
688
|
// Add screenshot if provided
|
|
689
|
+
let base64Data = "";
|
|
689
690
|
if (screenshot) {
|
|
690
|
-
|
|
691
|
+
base64Data = screenshot.split(",")[1] || screenshot;
|
|
691
692
|
messageContent.push({
|
|
692
693
|
type: "image",
|
|
693
694
|
source: {
|
|
@@ -698,6 +699,111 @@ export async function POST(request: Request) {
|
|
|
698
699
|
});
|
|
699
700
|
}
|
|
700
701
|
|
|
702
|
+
// ========== PHASE A: VISUAL PROBLEM ANALYSIS ==========
|
|
703
|
+
// Before generating patches, analyze WHAT is visually wrong
|
|
704
|
+
// This forces the LLM to articulate the problem before trying to fix it
|
|
705
|
+
interface VisualAnalysis {
|
|
706
|
+
element: string;
|
|
707
|
+
problem: string;
|
|
708
|
+
currentState: string;
|
|
709
|
+
solution: string;
|
|
710
|
+
confidence: "high" | "medium" | "low";
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
let visualAnalysis: VisualAnalysis | null = null;
|
|
714
|
+
|
|
715
|
+
if (screenshot && userPrompt) {
|
|
716
|
+
debugLog("Phase A: Starting visual problem analysis");
|
|
717
|
+
|
|
718
|
+
const analysisClient = new Anthropic({ apiKey });
|
|
719
|
+
|
|
720
|
+
try {
|
|
721
|
+
const analysisResponse = await analysisClient.messages.create({
|
|
722
|
+
model: "claude-sonnet-4-20250514",
|
|
723
|
+
max_tokens: 1024,
|
|
724
|
+
messages: [
|
|
725
|
+
{
|
|
726
|
+
role: "user",
|
|
727
|
+
content: [
|
|
728
|
+
{
|
|
729
|
+
type: "image",
|
|
730
|
+
source: {
|
|
731
|
+
type: "base64",
|
|
732
|
+
media_type: "image/png",
|
|
733
|
+
data: base64Data,
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
{
|
|
737
|
+
type: "text",
|
|
738
|
+
text: `You are analyzing a UI screenshot to understand a visual problem.
|
|
739
|
+
|
|
740
|
+
User request: "${userPrompt}"
|
|
741
|
+
|
|
742
|
+
${focusedElements && focusedElements.length > 0 ? `User clicked on these elements:
|
|
743
|
+
${focusedElements.map((el) => `- ${el.name} (${el.type}) at position (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
|
744
|
+
` : ""}
|
|
745
|
+
|
|
746
|
+
BEFORE any code changes can be made, you must analyze the visual problem.
|
|
747
|
+
|
|
748
|
+
Answer these questions:
|
|
749
|
+
1. ELEMENT: Which specific UI element has the problem? (describe its location, text content, appearance)
|
|
750
|
+
2. PROBLEM: What exactly is visually wrong? (invisible text, wrong color, poor contrast, wrong size, etc.)
|
|
751
|
+
3. CURRENT STATE: What styling/colors appear to be applied to this element?
|
|
752
|
+
4. SOLUTION: What specific CSS/Tailwind change would fix this problem?
|
|
753
|
+
5. CONFIDENCE: How confident are you that you've identified the correct element and problem? (high/medium/low)
|
|
754
|
+
|
|
755
|
+
Return ONLY valid JSON with no other text:
|
|
756
|
+
{
|
|
757
|
+
"element": "specific description of the UI element",
|
|
758
|
+
"problem": "what is visually wrong",
|
|
759
|
+
"currentState": "what styling appears to be applied",
|
|
760
|
+
"solution": "specific CSS/Tailwind fix needed",
|
|
761
|
+
"confidence": "high"
|
|
762
|
+
}`,
|
|
763
|
+
},
|
|
764
|
+
],
|
|
765
|
+
},
|
|
766
|
+
],
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
const analysisText = analysisResponse.content.find((block) => block.type === "text");
|
|
770
|
+
if (analysisText && analysisText.type === "text") {
|
|
771
|
+
// Parse the JSON response
|
|
772
|
+
let jsonText = analysisText.text.trim();
|
|
773
|
+
// Extract JSON if wrapped in code blocks
|
|
774
|
+
const jsonMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)\s*```/) || jsonText.match(/(\{[\s\S]*\})/);
|
|
775
|
+
if (jsonMatch) {
|
|
776
|
+
jsonText = jsonMatch[1];
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
try {
|
|
780
|
+
visualAnalysis = JSON.parse(jsonText) as VisualAnalysis;
|
|
781
|
+
debugLog("Phase A: Visual problem analysis complete", visualAnalysis);
|
|
782
|
+
|
|
783
|
+
// If low confidence, return early with clarification request
|
|
784
|
+
if (visualAnalysis.confidence === "low") {
|
|
785
|
+
debugLog("Phase A: Low confidence - requesting clarification");
|
|
786
|
+
return NextResponse.json({
|
|
787
|
+
success: false,
|
|
788
|
+
needsClarification: true,
|
|
789
|
+
analysis: visualAnalysis,
|
|
790
|
+
message: `I can see "${visualAnalysis.element}" but I'm not certain about the problem: "${visualAnalysis.problem}". Can you be more specific about what needs to change?`,
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
} catch (parseError) {
|
|
794
|
+
debugLog("Phase A: Failed to parse analysis response", {
|
|
795
|
+
error: String(parseError),
|
|
796
|
+
response: jsonText.substring(0, 500)
|
|
797
|
+
});
|
|
798
|
+
// Continue without analysis if parsing fails
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
} catch (analysisError) {
|
|
802
|
+
debugLog("Phase A: Analysis call failed", { error: String(analysisError) });
|
|
803
|
+
// Continue without analysis - fall back to existing behavior
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
701
807
|
// ========== SMART CONTEXT BUDGETING ==========
|
|
702
808
|
// Claude can handle 200k tokens (~800k chars), so we can safely include large files
|
|
703
809
|
// Priority: Recommended file (NEVER truncate) > Page file (limited) > Other components (dynamic)
|
|
@@ -731,6 +837,24 @@ User Request: "${userPrompt}"
|
|
|
731
837
|
textContent += `FOCUSED ELEMENTS (user clicked on these):
|
|
732
838
|
${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
|
733
839
|
|
|
840
|
+
`;
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// ========== VISUAL PROBLEM ANALYSIS (from Phase A) ==========
|
|
844
|
+
if (visualAnalysis) {
|
|
845
|
+
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
846
|
+
🔍 VISUAL PROBLEM ANALYSIS (I analyzed the screenshot first)
|
|
847
|
+
═══════════════════════════════════════════════════════════════════════════════
|
|
848
|
+
|
|
849
|
+
**Element:** ${visualAnalysis.element}
|
|
850
|
+
**Problem:** ${visualAnalysis.problem}
|
|
851
|
+
**Current State:** ${visualAnalysis.currentState}
|
|
852
|
+
**Required Fix:** ${visualAnalysis.solution}
|
|
853
|
+
**Confidence:** ${visualAnalysis.confidence}
|
|
854
|
+
|
|
855
|
+
⚠️ IMPORTANT: Your patches MUST implement the fix described above for the element described above.
|
|
856
|
+
Find the code that renders "${visualAnalysis.element}" and apply "${visualAnalysis.solution}".
|
|
857
|
+
|
|
734
858
|
`;
|
|
735
859
|
}
|
|
736
860
|
|
|
@@ -695,8 +695,9 @@ export async function POST(request: Request) {
|
|
|
695
695
|
const messageContent: Anthropic.MessageCreateParams["messages"][0]["content"] = [];
|
|
696
696
|
|
|
697
697
|
// Add screenshot if provided
|
|
698
|
+
let base64Data = "";
|
|
698
699
|
if (screenshot) {
|
|
699
|
-
|
|
700
|
+
base64Data = screenshot.split(",")[1] || screenshot;
|
|
700
701
|
messageContent.push({
|
|
701
702
|
type: "image",
|
|
702
703
|
source: {
|
|
@@ -707,6 +708,111 @@ export async function POST(request: Request) {
|
|
|
707
708
|
});
|
|
708
709
|
}
|
|
709
710
|
|
|
711
|
+
// ========== PHASE A: VISUAL PROBLEM ANALYSIS ==========
|
|
712
|
+
// Before generating patches, analyze WHAT is visually wrong
|
|
713
|
+
// This forces the LLM to articulate the problem before trying to fix it
|
|
714
|
+
interface VisualAnalysis {
|
|
715
|
+
element: string;
|
|
716
|
+
problem: string;
|
|
717
|
+
currentState: string;
|
|
718
|
+
solution: string;
|
|
719
|
+
confidence: "high" | "medium" | "low";
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
let visualAnalysis: VisualAnalysis | null = null;
|
|
723
|
+
|
|
724
|
+
if (screenshot && userPrompt) {
|
|
725
|
+
debugLog("Phase A: Starting visual problem analysis");
|
|
726
|
+
|
|
727
|
+
const analysisClient = new Anthropic({ apiKey });
|
|
728
|
+
|
|
729
|
+
try {
|
|
730
|
+
const analysisResponse = await analysisClient.messages.create({
|
|
731
|
+
model: "claude-sonnet-4-20250514",
|
|
732
|
+
max_tokens: 1024,
|
|
733
|
+
messages: [
|
|
734
|
+
{
|
|
735
|
+
role: "user",
|
|
736
|
+
content: [
|
|
737
|
+
{
|
|
738
|
+
type: "image",
|
|
739
|
+
source: {
|
|
740
|
+
type: "base64",
|
|
741
|
+
media_type: "image/png",
|
|
742
|
+
data: base64Data,
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
type: "text",
|
|
747
|
+
text: `You are analyzing a UI screenshot to understand a visual problem.
|
|
748
|
+
|
|
749
|
+
User request: "${userPrompt}"
|
|
750
|
+
|
|
751
|
+
${focusedElements && focusedElements.length > 0 ? `User clicked on these elements:
|
|
752
|
+
${focusedElements.map((el) => `- ${el.name} (${el.type}) at position (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
|
753
|
+
` : ""}
|
|
754
|
+
|
|
755
|
+
BEFORE any code changes can be made, you must analyze the visual problem.
|
|
756
|
+
|
|
757
|
+
Answer these questions:
|
|
758
|
+
1. ELEMENT: Which specific UI element has the problem? (describe its location, text content, appearance)
|
|
759
|
+
2. PROBLEM: What exactly is visually wrong? (invisible text, wrong color, poor contrast, wrong size, etc.)
|
|
760
|
+
3. CURRENT STATE: What styling/colors appear to be applied to this element?
|
|
761
|
+
4. SOLUTION: What specific CSS/Tailwind change would fix this problem?
|
|
762
|
+
5. CONFIDENCE: How confident are you that you've identified the correct element and problem? (high/medium/low)
|
|
763
|
+
|
|
764
|
+
Return ONLY valid JSON with no other text:
|
|
765
|
+
{
|
|
766
|
+
"element": "specific description of the UI element",
|
|
767
|
+
"problem": "what is visually wrong",
|
|
768
|
+
"currentState": "what styling appears to be applied",
|
|
769
|
+
"solution": "specific CSS/Tailwind fix needed",
|
|
770
|
+
"confidence": "high"
|
|
771
|
+
}`,
|
|
772
|
+
},
|
|
773
|
+
],
|
|
774
|
+
},
|
|
775
|
+
],
|
|
776
|
+
});
|
|
777
|
+
|
|
778
|
+
const analysisText = analysisResponse.content.find((block) => block.type === "text");
|
|
779
|
+
if (analysisText && analysisText.type === "text") {
|
|
780
|
+
// Parse the JSON response
|
|
781
|
+
let jsonText = analysisText.text.trim();
|
|
782
|
+
// Extract JSON if wrapped in code blocks
|
|
783
|
+
const jsonMatch = jsonText.match(/```(?:json)?\s*([\s\S]*?)\s*```/) || jsonText.match(/(\{[\s\S]*\})/);
|
|
784
|
+
if (jsonMatch) {
|
|
785
|
+
jsonText = jsonMatch[1];
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
try {
|
|
789
|
+
visualAnalysis = JSON.parse(jsonText) as VisualAnalysis;
|
|
790
|
+
debugLog("Phase A: Visual problem analysis complete", visualAnalysis);
|
|
791
|
+
|
|
792
|
+
// If low confidence, return early with clarification request
|
|
793
|
+
if (visualAnalysis.confidence === "low") {
|
|
794
|
+
debugLog("Phase A: Low confidence - requesting clarification");
|
|
795
|
+
return NextResponse.json({
|
|
796
|
+
success: false,
|
|
797
|
+
needsClarification: true,
|
|
798
|
+
analysis: visualAnalysis,
|
|
799
|
+
message: `I can see "${visualAnalysis.element}" but I'm not certain about the problem: "${visualAnalysis.problem}". Can you be more specific about what needs to change?`,
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
} catch (parseError) {
|
|
803
|
+
debugLog("Phase A: Failed to parse analysis response", {
|
|
804
|
+
error: String(parseError),
|
|
805
|
+
response: jsonText.substring(0, 500)
|
|
806
|
+
});
|
|
807
|
+
// Continue without analysis if parsing fails
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
} catch (analysisError) {
|
|
811
|
+
debugLog("Phase A: Analysis call failed", { error: String(analysisError) });
|
|
812
|
+
// Continue without analysis - fall back to existing behavior
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
710
816
|
// ========== SMART CONTEXT BUDGETING ==========
|
|
711
817
|
// Claude can handle 200k tokens (~800k chars), so we can safely include large files
|
|
712
818
|
// Priority: Recommended file (NEVER truncate) > Page file (limited) > Other components (dynamic)
|
|
@@ -740,6 +846,24 @@ User Request: "${userPrompt}"
|
|
|
740
846
|
textContent += `FOCUSED ELEMENTS (user clicked on these):
|
|
741
847
|
${focusedElements.map((el) => `- ${el.name} (${el.type}) at (${el.coordinates.x}, ${el.coordinates.y})`).join("\n")}
|
|
742
848
|
|
|
849
|
+
`;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
// ========== VISUAL PROBLEM ANALYSIS (from Phase A) ==========
|
|
853
|
+
if (visualAnalysis) {
|
|
854
|
+
textContent += `═══════════════════════════════════════════════════════════════════════════════
|
|
855
|
+
🔍 VISUAL PROBLEM ANALYSIS (I analyzed the screenshot first)
|
|
856
|
+
═══════════════════════════════════════════════════════════════════════════════
|
|
857
|
+
|
|
858
|
+
**Element:** ${visualAnalysis.element}
|
|
859
|
+
**Problem:** ${visualAnalysis.problem}
|
|
860
|
+
**Current State:** ${visualAnalysis.currentState}
|
|
861
|
+
**Required Fix:** ${visualAnalysis.solution}
|
|
862
|
+
**Confidence:** ${visualAnalysis.confidence}
|
|
863
|
+
|
|
864
|
+
⚠️ IMPORTANT: Your patches MUST implement the fix described above for the element described above.
|
|
865
|
+
Find the code that renders "${visualAnalysis.element}" and apply "${visualAnalysis.solution}".
|
|
866
|
+
|
|
743
867
|
`;
|
|
744
868
|
}
|
|
745
869
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sonance-brand-mcp",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.56",
|
|
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",
|