Skip to main content
Glama
YonasValentin

Design Inspiration MCP Server

Search design styles

design_search_styles
Read-onlyIdempotent

Search for design inspiration by style, including color palettes, typography, layouts, or animation references. Combines image and web search results to provide visual references.

Instructions

Search for a specific aesthetic direction — color palettes, typography, layouts, or animation references. Runs image and web search in parallel and returns combined results.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
styleYesDesign style to search for. Examples: "minimalist dark theme", "brutalist web design", "glassmorphism"
typeNoType of style inspiration to search forgeneral
numNoNumber of results (1-20, default: 10)

Implementation Reference

  • The registration and handler implementation for the 'design_search_styles' tool, which performs parallel image and web searches using the Serper API based on the user's style and type preferences.
    server.registerTool("design_search_styles", {
      title: "Search design styles",
      description: `Search for a specific aesthetic direction — color palettes, typography, layouts, or animation references. Runs image and web search in parallel and returns combined results.`,
      inputSchema: SearchStyleInputSchema,
      annotations: {
        readOnlyHint: true,
        destructiveHint: false,
        idempotentHint: true,
        openWorldHint: true,
      },
    }, async (params: SearchStyleInput) => {
      try {
        const typeKeywords: Record<string, string> = {
          "color-palette": "color palette scheme",
          typography: "typography fonts",
          layout: "layout grid structure",
          animation: "animation motion design",
          general: "",
        };
    
        const query = `${params.style} ${typeKeywords[params.type]} UI design inspiration`;
        const allSites = Object.values(DESIGN_SITES);
        const siteFilter = allSites.map((s) => `site:${s}`).join(" OR ");
        const fullQuery = `${query} (${siteFilter})`;
    
        const [imageData, searchData] = await Promise.all([
          serperRequest<SerperImagesResponse>("/images", { q: fullQuery, num: params.num }),
          serperRequest<SerperSearchResponse>("/search", { q: fullQuery, num: params.num }),
        ]);
    
        const images = imageData.images || [];
        const results = searchData.organic || [];
    
        const lines = [`# Style Inspiration: "${params.style}" (${params.type})`, ""];
    
        if (images.length) {
          lines.push("## Images", "");
          for (const img of images.slice(0, 5)) {
            lines.push(`- **${img.title}**: ${img.imageUrl}`);
            lines.push(`  Source: ${img.source} | [View](${img.link})`);
          }
          lines.push("");
        }
    
        if (results.length) {
          lines.push("## References", "");
          for (const r of results) {
            lines.push(`- **${r.title}**`);
            lines.push(`  ${r.snippet}`);
            lines.push(`  [View](${r.link})`);
            lines.push("");
          }
        }
    
        let text = lines.join("\n");
        if (text.length > CHARACTER_LIMIT) {
          text = text.slice(0, CHARACTER_LIMIT) + "\n\n...(truncated)";
        }
    
        return {
          content: [{ type: "text" as const, text }],
          structuredContent: {
            style: params.style,
            type: params.type,
            images: images.slice(0, 5).map((img) => ({
              title: img.title,
              imageUrl: img.imageUrl,
              source: img.source,
              link: img.link,
            })),
            references: results.map((r) => ({
              title: r.title,
              link: r.link,
              snippet: r.snippet,
            })),
          },
        };
      } catch (error) {
        return {
          content: [
            {
              type: "text" as const,
              text: error instanceof Error ? error.message : `Error: ${String(error)}`,
            },
          ],
        };
      }
  • The Zod input schema definition for 'design_search_styles', validating style, type, and number of results.
        ),
      type: z
        .enum(["color-palette", "typography", "layout", "animation", "general"])
        .default("general")
        .describe("Type of style inspiration to search for"),
      num: z
        .number()
        .int()
        .min(1)
        .max(20)
        .default(10)
        .describe("Number of results (1-20, default: 10)"),
    })
    .strict();

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv1.0.0

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations (read-only, idempotent, open-world), the description discloses that it runs image and web searches in parallel and merges results — genuinely useful operational knowledge an agent wouldn't get from the schema alone. This tells the agent to expect combined, multi-source output from a single call. The annotations already cover the safety profile, so the description earns credit for adding the execution model on top.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences: the first front-loads the purpose with concrete examples, the second covers the single non-obvious behavioral trait (parallel execution). Not a single wasted word.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only search tool with three well-documented parameters, the description covers purpose, scope, and combined-result behavior. The main gaps are an unspecified return format (no output schema exists) and no disambiguation from the similarly named sibling tools — minor for a low-risk, read-only operation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all parameters (style, type, num) are already documented. The description's style examples map naturally onto the type enum values ('color-palette', 'typography', 'layout', 'animation'), which provides a slight bridge between intent and schema. But it adds no format, syntax, or behavior details that the schema doesn't already state, landing at a solid baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: searching for a specific aesthetic direction with concrete examples like color palettes, typography, layouts, and animation references. The parallel image/web search detail adds specificity beyond a generic search. However, it doesn't explicitly distinguish itself from the closely related siblings design_search_images or design_search_references, which an agent would need to infer on its own.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The opening 'Search for a specific aesthetic direction' conveys when to use the tool, and the style examples give useful intent context. But there's no explicit when-not-to-use guidance or any mention of alternatives, which is a real gap given sibling tools like design_search_images and design_search_references are topically adjacent. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.