Skip to main content
Glama

ECharts MCP Server

by w2xi
generateImage.jsβ€’4.97 kB
const echarts = require('echarts') const { createCanvas } = require('canvas') const fs = require('fs') const path = require('path') const { v4: uuid } = require('uuid') const { HOME_DIR, DOWNLOAD_DIR } = require('../constants/path') const { isDirectoryWritable } = require('./writable') const { deepMerge } = require('./general') let baseDir = HOME_DIR const defaultEchartsConfig = { backgroundColor: '#fff', // Add default chart container configuration to prevent content overflow grid: { left: '10%', right: '10%', top: '15%', bottom: '15%', containLabel: true, // Ensure labels are not clipped }, // Default title configuration to prevent folding and overflow title: { top: '2%', left: 'center', textStyle: { fontSize: 16, fontWeight: 'bold', }, // Auto wrap text if title is too long textWrap: 'break', textOverflow: 'breakAll', }, // Default legend configuration to prevent folding and overflow legend: { top: '8%', left: 'center', type: 'scroll', // Show scrollbar when too many legend items pageButtonItemGap: 5, pageIconSize: 10, itemGap: 10, textStyle: { fontSize: 12, }, // Limit maximum width of legend width: '80%', }, // Default tooltip configuration tooltip: { trigger: 'axis', axisPointer: { type: 'cross', label: { backgroundColor: '#6a7985', }, }, // Prevent tooltip from exceeding boundaries confine: true, textStyle: { fontSize: 12, }, }, // Default X-axis configuration xAxis: { type: 'category', axisLabel: { interval: 0, // Show all labels rotate: 0, // Default no rotation, will be handled automatically if labels are too long fontSize: 11, // Handle long labels formatter: function (value) { if (value && value.length > 8) { return value.substring(0, 8) + '...' } return value }, }, axisTick: { alignWithLabel: true, }, }, // Default Y-axis configuration yAxis: { type: 'value', axisLabel: { fontSize: 11, // Format numbers to prevent displaying too long values formatter: function (value) { if (Math.abs(value) >= 1000000) { return (value / 1000000).toFixed(1) + 'M' } else if (Math.abs(value) >= 1000) { return (value / 1000).toFixed(1) + 'K' } return value }, }, // Ensure Y-axis has appropriate margins scale: true, }, // Default series configuration series: [], } async function generateImage({ echartsConfig, width = 800, height = 600 }) { try { const { writable } = await isDirectoryWritable(DOWNLOAD_DIR) if (writable) { baseDir = DOWNLOAD_DIR } const canvas = createCanvas(width, height) const chart = echarts.init(canvas) // Deep merge configurations to ensure default configs are properly applied const finalConfig = deepMerge(defaultEchartsConfig, echartsConfig) // Dynamically adjust configuration to fit canvas dimensions adjustConfigForDimensions(finalConfig, width, height) chart.setOption(finalConfig) const buffer = canvas.toBuffer('image/png') const fileName = `${uuid()}.png` const filePath = path.join(baseDir, fileName) fs.writeFileSync(filePath, buffer) return { url: filePath, } } catch (error) { return { error: error.message, } } } // Dynamically adjust configuration based on canvas dimensions function adjustConfigForDimensions(config, width, height) { // Adjust font sizes based on canvas size const scaleFactor = Math.min(width / 1000, height / 800) // Adjust title font size if (config.title && config.title.textStyle) { config.title.textStyle.fontSize = Math.max(12, Math.floor(16 * scaleFactor)) } // Adjust legend font size if (config.legend && config.legend.textStyle) { config.legend.textStyle.fontSize = Math.max(10, Math.floor(12 * scaleFactor)) } // Adjust axis label font sizes if (config.xAxis && config.xAxis.axisLabel) { config.xAxis.axisLabel.fontSize = Math.max(9, Math.floor(11 * scaleFactor)) } if (config.yAxis && config.yAxis.axisLabel) { config.yAxis.axisLabel.fontSize = Math.max(9, Math.floor(11 * scaleFactor)) } // Handle array form of axes as well if (Array.isArray(config.xAxis)) { config.xAxis.forEach(axis => { if (axis.axisLabel) { axis.axisLabel.fontSize = Math.max(9, Math.floor(11 * scaleFactor)) } }) } if (Array.isArray(config.yAxis)) { config.yAxis.forEach(axis => { if (axis.axisLabel) { axis.axisLabel.fontSize = Math.max(9, Math.floor(11 * scaleFactor)) } }) } // Auto rotate X-axis labels for small charts if (width < 600 && config.xAxis && config.xAxis.axisLabel) { config.xAxis.axisLabel.rotate = 45 } } module.exports = { generateImage }

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/w2xi/echarts-mcp'

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