Skip to main content
Glama

create_line_chart

Generate ASCII line charts to visualize temporal data trends in terminal environments using numeric arrays and optional labels.

Instructions

Generate ASCII line charts for temporal data visualization

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
dataYesArray of numeric values to plot
labelsNoOptional labels for x-axis (must match data length)
titleNoOptional chart title
widthNoChart width (10-200, default: 60)
heightNoChart height (5-50, default: 15)
colorNoANSI color name (red, green, blue, yellow, etc.)

Implementation Reference

  • Core handler function that implements the ASCII line chart generation. Handles data validation, grid setup, axis drawing, point plotting, line interpolation using a custom drawLine function, coloring, and formatting.
    export function createLineChart(data: ChartData): ChartResult { const { data: values, labels, title, width = 60, height = 15, color = 'white' } = data; if (values.length === 0) { throw new Error('Data array cannot be empty'); } const chartWidth = width - 10; // Reserve space for y-axis labels const chartHeight = height - 2; // Reserve space for x-axis const minValue = Math.min(...values); const maxValue = Math.max(...values); const valueRange = maxValue - minValue; // Create the chart grid const grid = createGrid(width, height); // Draw y-axis labels and grid lines for (let y = 0; y < chartHeight; y++) { const value = maxValue - (y / (chartHeight - 1)) * valueRange; const label = value.toFixed(1); const labelStr = padLeft(label, 8); // Place y-axis label for (let i = 0; i < Math.min(labelStr.length, 8); i++) { if (8 - i < width) { grid[y][8 - i] = labelStr[i]; } } // Draw y-axis line if (9 < width) { grid[y][9] = y === chartHeight - 1 ? ASCII_CHARS.bottomLeft : y === 0 ? ASCII_CHARS.topLeft : ASCII_CHARS.teeRight; } // Draw horizontal grid lines (optional light lines) for (let x = 10; x < width; x++) { if (y === chartHeight - 1) { grid[y][x] = ASCII_CHARS.horizontal; } else if (y % 2 === 0) { grid[y][x] = '·'; // Light grid dots } } } // Draw x-axis labels if (labels && labels.length === values.length) { // const labelSpacing = Math.max(1, Math.floor(chartWidth / Math.min(labels.length, 8))); for (let i = 0; i < labels.length && i < 8; i++) { const x = 10 + Math.floor((i / (labels.length - 1)) * (chartWidth - 1)); const label = labels[i].substring(0, 6); // Truncate long labels if (x + label.length <= width && height - 1 >= 0) { for (let j = 0; j < label.length && x + j < width; j++) { grid[height - 1][x + j] = label[j]; } } } } // Plot the line const plotPoints: { x: number; y: number }[] = []; for (let i = 0; i < values.length; i++) { const x = values.length === 1 ? 10 + Math.floor(chartWidth / 2) : 10 + Math.floor((i / (values.length - 1)) * (chartWidth - 1)); const normalizedValue = valueRange === 0 ? 0.5 : normalize(values[i], minValue, maxValue); const y = Math.floor((1 - normalizedValue) * (chartHeight - 1)); plotPoints.push({ x: clamp(x, 10, width - 1), y: clamp(y, 0, chartHeight - 1) }); } // Draw line segments between points for (let i = 0; i < plotPoints.length; i++) { const point = plotPoints[i]; // Draw the point if (point.x < width && point.y < chartHeight) { grid[point.y][point.x] = '●'; } // Draw line to next point if (i < plotPoints.length - 1) { const nextPoint = plotPoints[i + 1]; drawLine(grid, point.x, point.y, nextPoint.x, nextPoint.y, chartWidth, chartHeight); } } // Convert grid to string and apply coloring let chart = gridToString(grid); if (color !== 'white') { chart = colorize(chart, color); } // Add title if provided if (title) { const titleLine = center(title, width); chart = titleLine + '\n' + chart; } return { chart, title, dimensions: { width, height } }; }
  • src/index.ts:339-346 (registration)
    Tool dispatch/registration in the generateChart switch statement, calling the createLineChart handler with validated chartData.
    case 'create_line_chart': { progress.nextStep('Generating line chart'); result = await withRequestTracking( () => Promise.resolve(createLineChart(chartData)), 'create_line_chart' )(); break; }
  • MCP tool input schema definition for 'create_line_chart', specifying parameters, types, descriptions, constraints, and examples.
    type: 'object', properties: { data: { type: 'array', items: { type: 'number' }, description: 'Array of numeric values to plot' }, labels: { type: 'array', items: { type: 'string' }, description: 'Optional labels for x-axis (must match data length)', optional: true }, title: { type: 'string', description: 'Optional chart title', optional: true }, width: { type: 'number', description: 'Chart width (10-200, default: 60)', minimum: 10, maximum: 200, optional: true }, height: { type: 'number', description: 'Chart height (5-50, default: 15)', minimum: 5, maximum: 50, optional: true }, color: { type: 'string', description: 'ANSI color name (red, green, blue, yellow, etc.)', optional: true } }, required: ['data'], examples: getToolExamples('create_line_chart')
  • TypeScript interface defining the ChartData input structure used by the handler and validation.
    export interface ChartData { data: number[]; labels?: string[]; title?: string; width?: number; height?: number; color?: string; }
  • Helper function implementing line drawing algorithm for connecting data points in the chart.
    function drawLine( grid: string[][], x1: number, y1: number, x2: number, y2: number, maxWidth: number, maxHeight: number ): void { const dx = Math.abs(x2 - x1); const dy = Math.abs(y2 - y1); const sx = x1 < x2 ? 1 : -1; const sy = y1 < y2 ? 1 : -1; let err = dx - dy; let x = x1; let y = y1; // eslint-disable-next-line no-constant-condition while (true) { // Draw line character based on direction if (x >= 10 && x < maxWidth + 10 && y >= 0 && y < maxHeight) { if (grid[y][x] === ' ' || grid[y][x] === '·') { if (dx > dy) { grid[y][x] = ASCII_CHARS.horizontal; } else if (dy > dx) { grid[y][x] = ASCII_CHARS.vertical; } else { grid[y][x] = x < x2 ? ASCII_CHARS.curveUpRight : ASCII_CHARS.curveUpLeft; } } } if (x === x2 && y === y2) break; const e2 = 2 * err; if (e2 > -dy) { err -= dy; x += sx; } if (e2 < dx) { err += dx; y += sy; } } }

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/gianlucamazza/mcp-ascii-charts'

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