logo_search
Search and retrieve company logos in JSX, TSX, or SVG format using natural language queries. Filter by categories and themes, generate React components, and integrate logos into projects with ease.
Instructions
Search and return logos in specified format (JSX, TSX, SVG). Supports single and multiple logo searches with category filtering. Can return logos in different themes (light/dark) if available.
When to use this tool:
When user types "/logo" command (e.g., "/logo GitHub")
When user asks to add a company logo that's not in the local project
Example queries:
Single company: ["discord"]
Multiple companies: ["discord", "github", "slack"]
Specific brand: ["microsoft office"]
Command style: "/logo GitHub" -> ["github"]
Request style: "Add Discord logo to the project" -> ["discord"]
Format options:
TSX: Returns TypeScript React component
JSX: Returns JavaScript React component
SVG: Returns raw SVG markup
Each result includes:
Component name (e.g., DiscordIcon)
Component code
Import instructions
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| format | Yes | Output format | |
| queries | Yes | List of company names to search for logos |
Input Schema (JSON Schema)
Implementation Reference
- src/tools/logo-search.ts:196-345 (handler)The main handler method that executes the logo_search tool: fetches logos from SVGL API, converts SVG to requested format (JSX/TSX/SVG), handles multiple queries, saves test results, and returns structured JSON response with icons and setup instructions.async execute({ queries, format }: z.infer<typeof this.schema>) { console.log( `[${LOGO_TOOL_NAME}] Starting logo search for: ${queries.join( ", " )} in ${format} format` ); try { // Process all queries const results = await Promise.all( queries.map(async (query) => { try { console.log(`[${LOGO_TOOL_NAME}] Fetching logos for ${query}...`); const logos = await this.fetchLogos(query); if (logos.length === 0) { console.log(`[${LOGO_TOOL_NAME}] No logo found for ${query}`); return { query, success: false, message: `No logo found for: "${query}"`, }; } const logo = logos[0]; console.log( `[${LOGO_TOOL_NAME}] Processing logo for: ${logo.title}` ); const svgUrl = typeof logo.route === "string" ? logo.route : logo.route.light; console.log(`[${LOGO_TOOL_NAME}] Fetching SVG from: ${svgUrl}`); const svgContent = await this.fetchSVGContent(svgUrl); console.log(`[${LOGO_TOOL_NAME}] Converting to ${format} format`); const formattedContent = await this.convertToFormat( svgContent, format, logo.title + "Icon" ); console.log(`[${LOGO_TOOL_NAME}] Successfully processed ${query}`); return { query, success: true, content: `// ${logo.title} (${logo.url})\n${formattedContent}`, }; } catch (error) { console.error( `[${LOGO_TOOL_NAME}] Error processing ${query}:`, error ); return { query, success: false, message: error instanceof Error ? error.message : "Unknown error", }; } }) ); // Prepare summary const successful = results.filter((r) => r.success); const failed = results.filter((r) => !r.success); console.log(`[${LOGO_TOOL_NAME}] Results summary:`); console.log( `[${LOGO_TOOL_NAME}] Successfully processed: ${successful.length}` ); console.log(`[${LOGO_TOOL_NAME}] Failed to process: ${failed.length}`); // Save test results await this.saveTestResult({ queries, format, successful: successful .filter( (r): r is typeof r & { content: string } => r.content !== undefined ) .map((r) => ({ query: r.query, content: r.content, })), failed: failed .filter( (r): r is typeof r & { message: string } => r.message !== undefined ) .map((r) => ({ query: r.query, message: r.message, })), }); // Format response as component structure const foundIcons = successful.map((r) => { const title = r.content?.split("\n")[0].replace("// ", "").split(" (")[0] || ""; const componentName = title .split(" ") .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) .join("") .replace(/[^a-zA-Z0-9]/g, "") + "Icon"; return { icon: componentName, code: r.content?.split("\n").slice(1).join("\n") || "", }; }); const missingIcons = failed.map((f) => ({ icon: f.query, alternatives: [ "Search for SVG version on the official website", "Check other icon libraries (e.g., heroicons, lucide)", "Request SVG file from the user", ], })); const response = { icons: foundIcons, notFound: missingIcons, setup: [ "1. Add these icons to your project:", foundIcons .map((c) => ` ${c.icon}.${format.toLowerCase()}`) .join("\n"), "2. Import and use like this:", "```tsx", "import { " + foundIcons.map((c) => c.icon).join(", ") + " } from '@/icons';", "```", ].join("\n"), }; // Log results return { content: [ { type: "text" as const, text: JSON.stringify(response, null, 2), }, ], }; } catch (error) { // Log error console.error(`[${LOGO_TOOL_NAME}] Error:`, error); throw error; } }
- src/tools/logo-search.ts:53-58 (schema)Zod schema defining the input parameters: array of company name queries and output format (JSX, TSX, or SVG). Includes tool name 'logo_search' and detailed description.schema = z.object({ queries: z .array(z.string()) .describe("List of company names to search for logos"), format: z.enum(["JSX", "TSX", "SVG"]).describe("Output format"), });
- src/index.ts:15-15 (registration)Registration of the LogoSearchTool instance with the MCP server.new LogoSearchTool().register(server);