Skip to main content
Glama

generate_radial_gradient

Create radial gradients with mathematical precision for CSS styling, offering control over colors, shapes, sizes, and interpolation methods to enhance visual designs.

Instructions

Generate radial gradients with precise mathematical control and CSS output

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
colorsYesArray of color strings for the gradient
positionsNoStop positions (0-100). If not provided, colors are evenly distributed
centerNoCenter point [x, y] as percentages (0-100, default: [50, 50])
shapeNoGradient shapecircle
sizeNoGradient size methodfarthest_corner
dimensionsNo[width, height] dimensions when size is explicit
interpolationNoInterpolation method for color transitionslinear
color_spaceNoColor space for interpolationrgb
stepsNoNumber of steps for stepped gradients (creates discrete color bands)

Implementation Reference

  • Core handler function that executes the tool logic: validates parameters using Joi, processes colors and positions, applies interpolation, generates CSS via helper, builds detailed response data with recommendations.
    async function generateRadialGradient(
      params: RadialGradientParams
    ): Promise<ToolResponse | ErrorResponse> {
      const startTime = Date.now();
    
      try {
        // Validate parameters
        const { error, value } = radialGradientSchema.validate(params);
        if (error) {
          return createErrorResponse(
            'generate_radial_gradient',
            'INVALID_PARAMETERS',
            `Invalid parameters: ${error.details.map(d => d.message).join(', ')}`,
            startTime,
            {
              details: error.details,
              suggestions: [
                'Ensure colors array has 2-20 valid color strings',
                'Check that positions (if provided) match color count and are in ascending order',
                'Verify center coordinates are between 0-100',
                'Use supported shape: circle or ellipse',
                'Provide dimensions when size is explicit',
              ],
            }
          );
        }
    
        const validatedParams = value as RadialGradientParams;
    
        // Validate colors
        const validatedColors = validateColors(validatedParams.colors);
    
        // Calculate positions
        const positions = calculatePositions(
          validatedColors.length,
          validatedParams.positions
        );
    
        // Apply interpolation
        const interpolatedPositions = applyInterpolation(
          positions,
          validatedParams.interpolation || 'linear'
        );
    
        // Generate CSS
        const css = generateRadialGradientCSS(
          validatedColors,
          interpolatedPositions,
          validatedParams.center || [50, 50],
          validatedParams.shape || 'circle',
          validatedParams.size || 'farthest_corner',
          validatedParams.dimensions,
          validatedParams.steps
        );
    
        // Prepare response data
        const colorData = validatedColors.map((colorObj, index) => ({
          color: colorObj.original,
          position: interpolatedPositions[index] || 0,
          hex: colorObj.color.toHex(),
          rgb: colorObj.color.toRgbString(),
          hsl: colorObj.color.toHslString(),
        }));
    
        const data: RadialGradientData = {
          css,
          type: 'radial',
          center: validatedParams.center || [50, 50],
          shape: validatedParams.shape || 'circle',
          size: validatedParams.size || 'farthest_corner',
          colors: colorData,
          interpolation: validatedParams.interpolation || 'linear',
          color_space: validatedParams.color_space || 'rgb',
          total_stops: validatedParams.steps || validatedColors.length,
        };
    
        const executionTime = Date.now() - startTime;
    
        // Generate recommendations
        const recommendations: string[] = [];
        if (validatedColors.length > 5) {
          recommendations.push(
            'Consider using fewer colors for better performance'
          );
        }
        if (
          validatedParams.center &&
          (validatedParams.center[0] !== 50 || validatedParams.center[1] !== 50)
        ) {
          recommendations.push(
            'Off-center gradients can create interesting visual effects'
          );
        }
        if (validatedParams.steps && validatedParams.steps > 20) {
          recommendations.push(
            'High step counts may impact performance on older devices'
          );
        }
        if (
          validatedParams.shape === 'ellipse' &&
          validatedParams.size === 'explicit'
        ) {
          recommendations.push(
            'Elliptical gradients with explicit dimensions work well for specific aspect ratios'
          );
        }
    
        return createSuccessResponse(
          'generate_radial_gradient',
          data,
          executionTime,
          {
            colorSpaceUsed: validatedParams.color_space || 'rgb',
            accessibilityNotes: [
              'Ensure sufficient contrast between gradient colors and any overlaid text',
              'Test gradient visibility with color vision deficiency simulators',
              'Radial gradients can create focus points - use carefully for accessibility',
            ],
            recommendations,
            exportFormats: {
              css: css,
              scss: `$gradient: ${css};`,
              json: {
                type: 'radial',
                center: validatedParams.center || [50, 50],
                shape: validatedParams.shape || 'circle',
                size: validatedParams.size || 'farthest_corner',
                colors: colorData,
                css: css,
              },
            },
          }
        );
      } catch (error) {
        logger.error('Error generating radial gradient', { error: error as Error });
        const errorMessage =
          error instanceof Error ? error.message : 'Unknown error occurred';
    
        return createErrorResponse(
          'generate_radial_gradient',
          'GRADIENT_GENERATION_ERROR',
          errorMessage,
          startTime,
          {
            details: { error: errorMessage },
            suggestions: [
              'Check that all colors are in valid formats (hex, rgb, hsl, named)',
              'Ensure positions array matches color count if provided',
              'Verify all parameters are within valid ranges',
              'Provide dimensions when using explicit size',
            ],
          }
        );
      }
    }
  • JSON Schema in ToolHandler defining the input parameters for the MCP 'generate_radial_gradient' tool, including types, constraints, defaults, and descriptions for all fields.
    parameters: {
      type: 'object',
      properties: {
        colors: {
          type: 'array',
          items: { type: 'string' },
          minItems: 2,
          maxItems: 20,
          description: 'Array of color strings for the gradient',
        },
        positions: {
          type: 'array',
          items: { type: 'number', minimum: 0, maximum: 100 },
          description:
            'Stop positions (0-100). If not provided, colors are evenly distributed',
        },
        center: {
          type: 'array',
          items: { type: 'number', minimum: 0, maximum: 100 },
          minItems: 2,
          maxItems: 2,
          default: [50, 50],
          description:
            'Center point [x, y] as percentages (0-100, default: [50, 50])',
        },
        shape: {
          type: 'string',
          enum: ['circle', 'ellipse'],
          default: 'circle',
          description: 'Gradient shape',
        },
        size: {
          type: 'string',
          enum: [
            'closest_side',
            'closest_corner',
            'farthest_side',
            'farthest_corner',
            'explicit',
          ],
          default: 'farthest_corner',
          description: 'Gradient size method',
        },
        dimensions: {
          type: 'array',
          items: { type: 'number', minimum: 1, maximum: 10000 },
          minItems: 2,
          maxItems: 2,
          description: '[width, height] dimensions when size is explicit',
        },
        interpolation: {
          type: 'string',
          enum: ['linear', 'ease', 'ease_in', 'ease_out', 'bezier'],
          default: 'linear',
          description: 'Interpolation method for color transitions',
        },
        color_space: {
          type: 'string',
          enum: ['rgb', 'hsl', 'lab', 'lch'],
          default: 'rgb',
          description: 'Color space for interpolation',
        },
        steps: {
          type: 'number',
          minimum: 2,
          maximum: 100,
          description:
            'Number of steps for stepped gradients (creates discrete color bands)',
        },
      },
      required: ['colors'],
    },
  • Registration of the generateRadialGradientTool with the central ToolRegistry singleton.
    toolRegistry.registerTool(generateRadialGradientTool);
  • Key helper function that constructs the final CSS radial-gradient syntax from validated colors, positions, shape, size, etc.
    function generateRadialGradientCSS(
      colors: Array<{ color: Colord; original: string }>,
      positions: number[],
      center: [number, number],
      shape: string,
      size: string,
      dimensions?: [number, number],
      steps?: number
    ): string {
      let cssStops: string[];
    
      if (steps) {
        // Generate stepped gradient
        const steppedColors = generateSteppedPositions(
          colors.map(c => c.color.toHex()),
          steps
        );
        cssStops = steppedColors.map(
          ({ color, position }) => `${color} ${position}%`
        );
      } else {
        // Generate smooth gradient
        cssStops = colors.map((colorObj, index) => {
          const color = colorObj.color.toHex();
          const position = positions[index];
          return `${color} ${position}%`;
        });
      }
    
      // Build gradient specification
      const sizeSpec = generateSizeSpec(size, shape, dimensions);
      const centerSpec = `${center[0]}% ${center[1]}%`;
    
      let gradientSpec = '';
    
      if (shape === 'circle') {
        if (size === 'explicit') {
          gradientSpec = `circle ${sizeSpec} at ${centerSpec}`;
        } else {
          gradientSpec = `circle ${sizeSpec} at ${centerSpec}`;
        }
      } else {
        if (size === 'explicit') {
          gradientSpec = `ellipse ${sizeSpec} at ${centerSpec}`;
        } else {
          gradientSpec = `ellipse ${sizeSpec} at ${centerSpec}`;
        }
      }
    
      return `radial-gradient(${gradientSpec}, ${cssStops.join(', ')})`;
    }
  • Joi object schema used internally for runtime parameter validation in the handler.
    const radialGradientSchema = Joi.object({
      colors: Joi.array()
        .items(Joi.string())
        .min(2)
        .max(20)
        .required()
        .description('Array of color strings for the gradient'),
    
      positions: Joi.array()
        .items(Joi.number().min(0).max(100))
        .optional()
        .description(
          'Stop positions (0-100). If not provided, colors are evenly distributed'
        ),
    
      center: Joi.array()
        .items(Joi.number().min(0).max(100))
        .length(2)
        .default([50, 50])
        .description(
          'Center point [x, y] as percentages (0-100, default: [50, 50])'
        ),
    
      shape: Joi.string()
        .valid('circle', 'ellipse')
        .default('circle')
        .description('Gradient shape'),
    
      size: Joi.string()
        .valid(
          'closest_side',
          'closest_corner',
          'farthest_side',
          'farthest_corner',
          'explicit'
        )
        .default('farthest_corner')
        .description('Gradient size method'),
    
      dimensions: Joi.array()
        .items(Joi.number().min(1).max(10000))
        .length(2)
        .when('size', {
          is: 'explicit',
          then: Joi.required(),
          otherwise: Joi.optional(),
        })
        .description('[width, height] dimensions when size is explicit'),
    
      interpolation: Joi.string()
        .valid('linear', 'ease', 'ease_in', 'ease_out', 'bezier')
        .default('linear')
        .description('Interpolation method for color transitions'),
    
      color_space: Joi.string()
        .valid('rgb', 'hsl', 'lab', 'lch')
        .default('rgb')
        .description('Color space for interpolation'),
    
      steps: Joi.number()
        .integer()
        .min(2)
        .max(100)
        .optional()
        .description(
          'Number of steps for stepped gradients (creates discrete color bands)'
        ),
    });
Behavior2/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. While it mentions 'CSS output' and 'precise mathematical control', it doesn't describe what the tool actually returns (CSS string? full CSS rule?), error conditions, performance characteristics, or any limitations. The phrase 'precise mathematical control' is vague and doesn't provide actionable behavioral information.

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 efficiently phrased in a single sentence with no wasted words. It's appropriately front-loaded with the core functionality. However, for a tool with 9 parameters and complex behavior, this extreme brevity might be insufficient rather than optimally concise.

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 complex gradient generation tool with 9 parameters, no annotations, and no output schema, the description is inadequate. It doesn't explain what the output looks like (CSS rule format), doesn't mention error handling, and provides no examples or typical use cases. The lack of output schema means the description should compensate by explaining return values, which it doesn't do.

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?

The description adds no parameter-specific information beyond what's already comprehensively documented in the schema (100% coverage). While the schema thoroughly describes all 9 parameters with constraints, defaults, and enums, the description doesn't provide any additional context about parameter interactions, typical usage patterns, or practical examples.

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 function ('Generate radial gradients') and output format ('CSS output'), which distinguishes it from linear gradient tools. However, it doesn't explicitly differentiate from sibling tools like 'create_gradient_html' or 'create_gradient_png' that might also produce gradient outputs in different formats.

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 sibling tools like 'generate_linear_gradient', 'create_gradient_html', and 'create_gradient_png' available, there's no indication of when radial gradients are preferable or when CSS output is needed versus other formats.

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