Skip to main content
Glama

analyze_colors

Extract dominant colors from images or specific regions using K-Means clustering, returning color names and frequencies for visual analysis.

Instructions

Extract dominant colors from an image region using K-Means clustering in LAB color space. Returns colors sorted by frequency with human-readable names from color.pizza.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
imageYesPath to the image file
bboxNoOptional bounding box as [ymin, xmin, ymax, xmax] normalized 0-1000. Defaults to full image.
topNoNumber of dominant colors to return (default: 5)

Implementation Reference

  • The primary handler function that executes the analyze_colors tool logic: loads image or region pixels, applies K-Means clustering for dominant colors in LAB space, computes average color, color names, percentages, confidence, and formats response as JSON.
    export async function handleAnalyzeColors(args: Record<string, unknown>) {
      const image = args.image as string;
      const bbox = args.bbox as [number, number, number, number] | undefined;
      const top = (args.top as number) || 5;
    
      let pixels: Uint8Array;
      let width: number;
      let height: number;
    
      if (bbox) {
        // Analyze specific region
        const region = await getRegionPixels(image, bbox);
        pixels = region.pixels;
        width = region.width;
        height = region.height;
      } else {
        // Analyze full image
        const { image: img, metadata } = await loadImage(image);
        const { data } = await img.raw().toBuffer({ resolveWithObject: true });
        pixels = new Uint8Array(data);
        width = metadata.width;
        height = metadata.height;
      }
    
      const totalPixels = pixels.length / 3;
    
      // Run K-Means clustering
      const result = kmeansCluster(pixels, top);
    
      // Calculate average color
      let avgR = 0,
        avgG = 0,
        avgB = 0;
      for (let i = 0; i < pixels.length; i += 3) {
        avgR += pixels[i];
        avgG += pixels[i + 1];
        avgB += pixels[i + 2];
      }
      avgR = Math.round(avgR / totalPixels);
      avgG = Math.round(avgG / totalPixels);
      avgB = Math.round(avgB / totalPixels);
    
      // Build dominant colors array sorted by count
      const sortedIndices = result.counts
        .map((count, idx) => ({ count, idx }))
        .sort((a, b) => b.count - a.count)
        .map((item) => item.idx);
    
      const dominant = await Promise.all(
        sortedIndices.map(async (idx) => {
          const [r, g, b] = result.centroids[idx];
          const percentage = (result.counts[idx] / result.labels.length) * 100;
          const name = await getColorName(r, g, b);
    
          return {
            hex: rgbToHex(r, g, b),
            rgb: [r, g, b],
            hsl: rgbToHsl(r, g, b),
            name,
            percentage: Math.round(percentage * 100) / 100,
          };
        })
      );
    
      // Determine confidence based on variance
      // Low variance = flat colors (UI), high variance = photo/gradient
      const confidence =
        result.variance < 50 ? "high" : result.variance < 200 ? "medium" : "low";
    
      const average = {
        hex: rgbToHex(avgR, avgG, avgB),
        rgb: [avgR, avgG, avgB],
        name: await getColorName(avgR, avgG, avgB),
      };
    
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(
              {
                dominant,
                average,
                confidence,
                region: bbox
                  ? {
                      bbox,
                      size: [width, height],
                      totalPixels,
                    }
                  : {
                      fullImage: true,
                      size: [width, height],
                      totalPixels,
                    },
              },
              null,
              2
            ),
          },
        ],
      };
    }
  • Tool definition including name, description, and inputSchema for validation (image required, optional bbox and top_k).
    export const analyzeColorsTool: Tool = {
      name: "analyze_colors",
      description:
        "Extract dominant colors from an image region using K-Means clustering in LAB color space. Returns colors sorted by frequency with human-readable names from color.pizza.",
      inputSchema: {
        type: "object",
        properties: {
          image: {
            type: "string",
            description: "Path to the image file or URL (http/https)",
          },
          bbox: {
            type: "array",
            items: { type: "number" },
            minItems: 4,
            maxItems: 4,
            description:
              "Optional bounding box as [ymin, xmin, ymax, xmax] normalized 0-1000. Defaults to full image.",
          },
          top: {
            type: "number",
            description: "Number of dominant colors to return (default: 5)",
          },
        },
        required: ["image"],
      },
    };
  • src/index.ts:37-46 (registration)
    Registers analyzeColorsTool in the listToolsRequestHandler response.
    server.setRequestHandler(ListToolsRequestSchema, async () => {
      return {
        tools: [
          describeTool,
          detectTool,
          describeRegionTool,
          analyzeColorsTool,
        ],
      };
    });
  • src/index.ts:53-67 (registration)
    Dispatches to handleAnalyzeColors in the CallToolRequestHandler switch statement for 'analyze_colors'.
    switch (name) {
      case "describe":
        return await handleDescribe(args);
      case "detect":
        return await handleDetect(args);
      case "describe_region":
        return await handleDescribeRegion(args);
      case "analyze_colors":
        return await handleAnalyzeColors(args);
      default:
        return {
          content: [{ type: "text", text: `Unknown tool: ${name}` }],
          isError: true,
        };
    }
  • src/index.ts:22-22 (registration)
    Import of analyzeColorsTool and handleAnalyzeColors from the implementation file.
    import { analyzeColorsTool, handleAnalyzeColors } from "./tools/analyze-colors.js";
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/simen/mcp-see'

If you have feedback or need assistance with the MCP directory API, please join our Discord server