#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
CallToolRequestSchema,
ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import Anthropic from "@anthropic-ai/sdk";
const anthropic = new Anthropic({
apiKey: process.env.ANTHROPIC_API_KEY,
});
const server = new Server(
{
name: "brandsnap-mcp",
version: "1.0.0",
},
{
capabilities: {
tools: {},
},
}
);
// Define the brand identity generation tool
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: "generate_brand_identity",
description:
"Generate a complete brand identity kit including colors, fonts, brand voice, logo direction, and social media guidelines for a business.",
inputSchema: {
type: "object" as const,
properties: {
business_name: {
type: "string",
description: "The name of the business",
},
industry: {
type: "string",
description:
"The industry or sector the business operates in (e.g., 'Technology', 'Healthcare', 'Food & Beverage')",
},
values: {
type: "string",
description:
"A description of the business, its values, mission, and what makes it unique",
},
tone: {
type: "string",
description:
"The desired style/tone for the brand (e.g., 'Modern', 'Classic', 'Playful', 'Professional', 'Minimalist')",
},
},
required: ["business_name", "values"],
},
},
],
};
});
// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
if (request.params.name !== "generate_brand_identity") {
throw new Error(`Unknown tool: ${request.params.name}`);
}
const args = request.params.arguments as {
business_name: string;
industry?: string;
values: string;
tone?: string;
};
const { business_name, industry, values, tone } = args;
if (!business_name || !values) {
return {
content: [
{
type: "text" as const,
text: JSON.stringify({
error: "business_name and values are required",
}),
},
],
isError: true,
};
}
const prompt = `You are a world-class brand identity designer. Generate a complete brand identity kit for the following business.
Business Name: ${business_name}
Industry: ${industry || "Not specified"}
Description: ${values}
Style Preference: ${tone || "Modern"}
Generate a comprehensive brand kit and respond ONLY with valid JSON (no markdown, no code blocks) in this exact structure:
{
"colors": [
{
"name": "Color name (e.g., 'Deep Ocean')",
"hex": "#HEXCODE",
"usage": "Brief usage description (e.g., 'Primary brand color for headers and CTAs')"
}
],
"fonts": {
"heading": {
"name": "Font name from Google Fonts",
"weight": "e.g., Bold (700)",
"style": "e.g., Sans-serif, modern and clean"
},
"body": {
"name": "Font name from Google Fonts",
"weight": "e.g., Regular (400)",
"style": "e.g., Sans-serif, highly readable"
},
"reasoning": "Why these fonts pair well together and suit this brand"
},
"brandVoice": {
"tone": "2-4 word tone description (e.g., 'Warm, Professional, Inviting')",
"taglines": ["tagline1", "tagline2", "tagline3"],
"description": "2-3 sentence description of the brand voice and how to use it"
},
"logoDirection": {
"concept": "Detailed description of the logo concept",
"style": "Description of the visual style (geometric, organic, typographic, etc.)",
"elements": ["element1", "element2", "element3", "element4"]
},
"socialMedia": {
"profileGuidelines": "How to apply the brand to profile images",
"coverGuidelines": "How to apply the brand to cover/banner images",
"colorApplications": [
"Specific color application tip 1",
"Specific color application tip 2",
"Specific color application tip 3"
],
"platforms": [
{ "name": "Instagram", "profileSize": "320x320px", "coverSize": "1080x1080px (feed)" },
{ "name": "Twitter/X", "profileSize": "400x400px", "coverSize": "1500x500px" },
{ "name": "LinkedIn", "profileSize": "400x400px", "coverSize": "1584x396px" },
{ "name": "Facebook", "profileSize": "170x170px", "coverSize": "820x312px" }
]
}
}
Requirements:
- Generate exactly 5 colors that work harmoniously together
- Include a primary, secondary, accent, background/neutral, and text color
- All hex codes must be valid 6-digit hex colors
- Font names must be real Google Fonts
- Taglines should be creative and memorable
- Logo direction should be detailed enough for a designer to work from
- Tailor everything to the specific business and industry`;
try {
const message = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 2048,
messages: [
{
role: "user",
content: prompt,
},
],
});
const textContent = message.content.find((block) => block.type === "text");
if (!textContent || textContent.type !== "text") {
throw new Error("No text response from AI");
}
// Parse the JSON response
let brandKit;
let jsonText = textContent.text.trim();
const jsonMatch = jsonText.match(/\{[\s\S]*\}/);
if (jsonMatch) {
jsonText = jsonMatch[0];
}
brandKit = JSON.parse(jsonText);
return {
content: [
{
type: "text" as const,
text: JSON.stringify(brandKit, null, 2),
},
],
};
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : "Unknown error";
return {
content: [
{
type: "text" as const,
text: JSON.stringify({
error: "Failed to generate brand identity",
details: errorMessage,
}),
},
],
isError: true,
};
}
});
// Start the server
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("BrandSnap MCP server running on stdio");
}
main().catch((error) => {
console.error("Fatal error:", error);
process.exit(1);
});