Skip to main content
Glama

analyze_color_collection

Analyze color collections for diversity, harmony, contrast, temperature distribution, and accessibility metrics to evaluate design quality and compliance.

Instructions

Analyze a collection of colors for diversity, harmony, contrast range, temperature distribution, and accessibility metrics.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
colorsYesArray of colors to analyze (2-50 colors)
metricsNoMetrics to calculate for the color collection

Implementation Reference

  • Core execution logic of the 'analyze_color_collection' tool. Validates input parameters using Joi schema, parses color strings into UnifiedColor objects, computes various metrics (diversity, harmony, contrast range, temperature distribution, accessibility), generates summary and recommendations, and returns structured response.
    async function analyzeCollectionHandler(
      params: unknown
    ): Promise<ToolResponse | ErrorResponse> {
      const startTime = Date.now();
    
      try {
        // Validate parameters
        const { error, value } = analyzeCollectionSchema.validate(params);
        if (error) {
          return createErrorResponse(
            'analyze_color_collection',
            'INVALID_PARAMETERS',
            `Invalid parameters: ${error.details.map(d => d.message).join(', ')}`,
            Date.now() - startTime,
            {
              details: error.details,
            }
          );
        }
    
        const { colors: colorStrings, metrics } = value as AnalyzeCollectionParams;
    
        // Parse colors and create analyses
        const analyses: ColorAnalysis[] = [];
    
        for (let i = 0; i < colorStrings.length; i++) {
          const colorString = colorStrings[i];
          if (!colorString) continue;
    
          try {
            const color = new UnifiedColor(colorString);
            const hsl = color.hsl;
            const rgb = color.rgb;
            const metadata = color.metadata;
    
            // Calculate brightness using perceived brightness formula
            const brightness = 0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b;
    
            analyses.push({
              color,
              hue: hsl.h,
              saturation: hsl.s,
              lightness: hsl.l,
              brightness,
              temperature: metadata?.temperature || 'neutral',
              contrastWithWhite: color.getContrastRatio('#ffffff'),
              contrastWithBlack: color.getContrastRatio('#000000'),
            });
          } catch (error) {
            return createErrorResponse(
              'analyze_color_collection',
              'INVALID_COLOR',
              `Invalid color at index ${i}: ${colorString}`,
              Date.now() - startTime,
              {
                details: {
                  colorIndex: i,
                  providedColor: colorString,
                  error: error instanceof Error ? error.message : 'Unknown error',
                },
                suggestions: [
                  'Ensure all colors are in valid format (hex, rgb, hsl, etc.)',
                  'Check color syntax and values',
                ],
              }
            );
          }
        }
    
        // Calculate requested metrics
        const results: AnalysisResults = {
          total_colors: colorStrings.length,
          color_summary: analyses.map(a => ({
            hex: a.color.hex,
            hue: Math.round(a.hue * 10) / 10,
            saturation: Math.round(a.saturation * 10) / 10,
            lightness: Math.round(a.lightness * 10) / 10,
            temperature: a.temperature,
          })),
          overall_assessment: {
            score: 0,
            interpretation: '',
          },
        };
    
        if (metrics.includes('diversity')) {
          results.diversity = calculateColorDiversity(analyses);
        }
    
        if (metrics.includes('harmony')) {
          results.harmony = calculateHarmonyScore(analyses);
        }
    
        if (metrics.includes('contrast_range')) {
          results.contrast_range = calculateContrastRange(analyses);
        }
    
        if (metrics.includes('temperature_distribution')) {
          results.temperature_distribution =
            calculateTemperatureDistribution(analyses);
        }
    
        if (metrics.includes('accessibility_score')) {
          results.accessibility_score = calculateAccessibilityScore(analyses);
        }
    
        const executionTime = Date.now() - startTime;
    
        // Generate overall assessment
        const overallScore = Math.round(
          [
            results.diversity?.score || 0,
            results.harmony?.score || 0,
            results.accessibility_score?.score || 0,
          ].reduce((sum, score) => sum + score, 0) / 3
        );
    
        results.overall_assessment = {
          score: overallScore,
          interpretation: getOverallInterpretation(overallScore),
        };
    
        // Generate accessibility notes
        const accessibilityNotes: string[] = [];
        if (results.accessibility_score) {
          accessibilityNotes.push(
            `Accessibility score: ${results.accessibility_score.score}/100`
          );
          if (
            'recommendations' in results.accessibility_score &&
            results.accessibility_score.recommendations
          ) {
            accessibilityNotes.push(...results.accessibility_score.recommendations);
          }
        }
    
        // Generate recommendations
        const recommendations: string[] = [];
        if (results.diversity && results.diversity.score < 50) {
          recommendations.push(
            'Consider adding more diverse colors to improve visual interest'
          );
        }
        if (results.harmony && results.harmony.score < 50) {
          recommendations.push('Adjust color relationships to improve harmony');
        }
        if (
          results.contrast_range &&
          'accessibility_percentage' in results.contrast_range &&
          results.contrast_range.accessibility_percentage < 70
        ) {
          recommendations.push('Improve contrast ratios for better accessibility');
        }
    
        return createSuccessResponse(
          'analyze_color_collection',
          results,
          executionTime,
          {
            colorSpaceUsed: 'hsl',
            accessibilityNotes: accessibilityNotes,
            recommendations,
          }
        );
      } catch (error) {
        const executionTime = Date.now() - startTime;
        logger.error('Error in analyze_color_collection tool', {
          error: error as Error,
        });
    
        return createErrorResponse(
          'analyze_color_collection',
          'PROCESSING_ERROR',
          'An error occurred while analyzing the color collection',
          executionTime,
          {
            details: {
              error: error instanceof Error ? error.message : 'Unknown error',
            },
            suggestions: [
              'Check that all input colors are valid',
              'Verify metrics parameter contains valid values',
              'Try with fewer colors if processing large collections',
            ],
          }
        );
      }
    }
  • Joi validation schema for tool input parameters: requires 2-50 colors array, optional metrics array with specific valid values.
    const analyzeCollectionSchema = Joi.object({
      colors: Joi.array()
        .items(Joi.string().required())
        .min(2)
        .max(50)
        .required()
        .messages({
          'array.min': 'At least 2 colors are required for analysis',
          'array.max': 'Maximum 50 colors can be analyzed at once',
        }),
      metrics: Joi.array()
        .items(
          Joi.string().valid(
            'diversity',
            'harmony',
            'contrast_range',
            'temperature_distribution',
            'accessibility_score'
          )
        )
        .default([
          'diversity',
          'harmony',
          'contrast_range',
          'temperature_distribution',
          'accessibility_score',
        ])
        .messages({
          'any.only':
            'Metrics must be one of: diversity, harmony, contrast_range, temperature_distribution, accessibility_score',
        }),
    });
  • ToolHandler object definition exporting the tool with name, description, JSON schema for parameters, and reference to the handler function.
    export const analyzeColorCollectionTool: ToolHandler = {
      name: 'analyze_color_collection',
      description:
        'Analyze a collection of colors for diversity, harmony, contrast range, temperature distribution, and accessibility metrics.',
      parameters: {
        type: 'object',
        properties: {
          colors: {
            type: 'array',
            items: { type: 'string' },
            minItems: 2,
            maxItems: 50,
            description: 'Array of colors to analyze (2-50 colors)',
          },
          metrics: {
            type: 'array',
            items: {
              type: 'string',
              enum: [
                'diversity',
                'harmony',
                'contrast_range',
                'temperature_distribution',
                'accessibility_score',
              ],
            },
            default: [
              'diversity',
              'harmony',
              'contrast_range',
              'temperature_distribution',
              'accessibility_score',
            ],
            description: 'Metrics to calculate for the color collection',
          },
        },
        required: ['colors'],
      },
      handler: analyzeCollectionHandler,
    };
  • Registers the analyzeColorCollectionTool instance to the central toolRegistry singleton.
    toolRegistry.registerTool(analyzeColorCollectionTool);
  • Imports the analyzeColorCollectionTool from its implementation file prior to registration.
    import { analyzeColorCollectionTool } from './analyze-color-collection';
Behavior2/5

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

With no annotations provided, the description carries full burden for behavioral disclosure. While it lists what metrics are calculated, it doesn't describe what the analysis returns, whether it's computationally intensive, what format the results come in, or any limitations beyond the 2-50 color range mentioned in the schema. This is inadequate for a tool with no annotation coverage.

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

Conciseness4/5

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

The description is a single, efficient sentence that clearly states the tool's purpose. It's appropriately sized and front-loaded with the core functionality. However, it could potentially benefit from slightly more structure given the complexity of the analysis being performed.

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

Completeness2/5

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

For a tool with no annotations and no output schema, the description is insufficiently complete. It doesn't explain what the analysis returns, the format of results, or how to interpret the metrics. Given the tool's complexity (analyzing multiple color metrics) and lack of structured output documentation, the description should provide more context about the tool's behavior and results.

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%, providing good documentation for both parameters. The description adds minimal value beyond the schema - it mentions the same metrics listed in the schema's enum but doesn't explain what these metrics mean or how they're calculated. Baseline 3 is appropriate when the schema does the heavy lifting.

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: analyzing a collection of colors for specific metrics (diversity, harmony, contrast range, temperature distribution, accessibility metrics). It uses a specific verb ('analyze') and resource ('collection of colors'), but doesn't explicitly differentiate from sibling tools like 'analyze_color' or 'check_contrast'.

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

Usage Guidelines2/5

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

The description provides no guidance on when to use this tool versus alternatives. With many sibling tools available (like analyze_color, check_contrast, optimize_for_accessibility), there's no indication of when this comprehensive analysis tool is preferred over more specialized alternatives.

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

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/keyurgolani/ColorMcp'

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