Skip to main content
Glama

create_line_chart

Generate text-based line charts for visualizing temporal data directly in terminal environments. Configure data points, axis labels, chart dimensions, and colors for clear, ASCII-based data representation.

Instructions

Generate ASCII line charts for temporal data visualization

Input Schema

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

Implementation Reference

  • The primary handler function that executes the create_line_chart tool logic. It processes ChartData, generates an ASCII art line chart using grid-based rendering, Bresenham line drawing, and returns a ChartResult.
    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 } }; }
  • TypeScript interface defining the input structure (ChartData) for the create_line_chart tool, used for type safety and validation.
    export interface ChartData { data: number[]; labels?: string[]; title?: string; width?: number; height?: number; color?: string; }
  • src/index.ts:58-102 (registration)
    MCP tool registration in the ListTools response, defining the tool name, description, and JSON schema for inputs.
    { name: 'create_line_chart', description: 'Generate ASCII line charts for temporal data visualization', inputSchema: { 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') }
  • Dispatch handler in the MCP CallToolRequest that invokes the createLineChart function after validation.
    case 'create_line_chart': { progress.nextStep('Generating line chart'); result = await withRequestTracking( () => Promise.resolve(createLineChart(chartData)), 'create_line_chart' )(); break; }
  • Supporting helper function that draws line segments between plotted points using an efficient line rasterization algorithm.
    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; } } }

Other Tools

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

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