generate_boxplot_chart
Generate a boxplot chart to display statistical summaries across categories. Input data with categories and values, optionally grouped. Customize titles, dimensions, theme, and export as PNG, SVG, or ECharts option.
Instructions
Generate a boxplot chart to show data for statistical summaries among different categories, such as, comparing the distribution of data points across categories.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| axisXTitle | No | Set the x-axis title of chart. | |
| axisYTitle | No | Set the y-axis title of chart. | |
| data | Yes | Data for boxplot chart, such as, [{ category: 'Category A', value: 10 }, { category: 'Category B', value: 20, group: 'Group A' }]. | |
| height | No | Set the height of the chart, default is 600px. | |
| theme | No | Set the theme for the chart, optional, default is 'default'. | default |
| title | No | Set the title of the chart. | |
| width | No | Set the width of the chart, default is 800px. | |
| outputType | No | The output type of the diagram. Can be 'png', 'svg' or 'option'. Default is 'png', 'png' will return the rendered PNG image, 'svg' will return the rendered SVG string, and 'option' will return the valid ECharts option. | png |
Implementation Reference
- src/tools/boxplot.ts:28-204 (handler)The main tool definition and handler function for generate_boxplot_chart. Contains the `run` async function that processes input data, computes boxplot statistics (min, Q1, median, Q3, max) using the inline `calculateBoxplotStats` helper, builds ECharts boxplot series options, and calls `generateChartImage` to produce the output.
export const generateBoxplotChartTool = { name: "generate_boxplot_chart", description: "Generate a boxplot chart to show data for statistical summaries among different categories, such as, comparing the distribution of data points across categories.", inputSchema: z.object({ axisXTitle: AxisXTitleSchema, axisYTitle: AxisYTitleSchema, data: z .array(data) .describe( "Data for boxplot chart, such as, [{ category: 'Category A', value: 10 }, { category: 'Category B', value: 20, group: 'Group A' }].", ) .nonempty({ message: "Boxplot chart data cannot be empty." }), height: HeightSchema, theme: ThemeSchema, title: TitleSchema, width: WidthSchema, outputType: OutputTypeSchema, }), run: async (params: { axisXTitle?: string; axisYTitle?: string; data: Array<{ category: string; value: number; group?: string }>; height: number; theme?: "default" | "dark"; title?: string; width: number; outputType?: "png" | "svg" | "option"; }) => { const { axisXTitle, axisYTitle, data, height, theme, title, width, outputType, } = params; // Group data by category and optional group const hasGroups = data.some((item) => item.group); let categories: string[] = []; const boxplotData: { name: string; value: number[] }[] = []; if (hasGroups) { // Group by category and group const groupMap = new Map< string, Array<{ category: string; value: number }> >(); const categorySet = new Set<string>(); for (const item of data) { const groupName = item.group || "Default"; const key = `${item.category}_${groupName}`; if (!groupMap.has(key)) { groupMap.set(key, []); } groupMap.get(key)?.push(item); categorySet.add(item.category); } categories = Array.from(categorySet).sort(); // Calculate boxplot statistics for each group groupMap.forEach((values, key) => { const [category, group] = key.split("_"); const sortedValues = values.map((v) => v.value).sort((a, b) => a - b); const boxplotStats = calculateBoxplotStats(sortedValues); boxplotData.push({ name: `${category}-${group}`, value: boxplotStats, }); }); } else { // Group by category only const categoryMap = new Map<string, number[]>(); for (const item of data) { if (!categoryMap.has(item.category)) { categoryMap.set(item.category, []); } categoryMap.get(item.category)?.push(item.value); } categories = Array.from(categoryMap.keys()).sort(); // Calculate boxplot statistics for each category for (const category of categories) { const values = categoryMap.get(category)?.sort((a, b) => a - b) || []; const boxplotStats = calculateBoxplotStats(values); boxplotData.push({ name: category, value: boxplotStats, }); } } const series: Array<SeriesOption> = [ { type: "boxplot", data: boxplotData, itemStyle: { borderWidth: 2, }, emphasis: { itemStyle: { borderWidth: 3, shadowBlur: 5, shadowColor: "rgba(0, 0, 0, 0.3)", }, }, }, ]; const echartsOption: EChartsOption = { series, title: { left: "center", text: title, }, tooltip: { trigger: "item", }, xAxis: { type: "category", data: categories, name: axisXTitle, boundaryGap: true, nameGap: 30, splitArea: { show: false, }, splitLine: { show: false, }, }, yAxis: { type: "value", name: axisYTitle, splitArea: { show: true, }, }, }; // Helper function to calculate boxplot statistics function calculateBoxplotStats(values: number[]): number[] { const len = values.length; const min = values[0]; const max = values[len - 1]; const median = len % 2 === 0 ? (values[len / 2 - 1] + values[len / 2]) / 2 : values[Math.floor(len / 2)]; const q1Index = Math.floor(len / 4); const q3Index = Math.floor((3 * len) / 4); const Q1 = values[q1Index]; const Q3 = values[q3Index]; return [min, Q1, median, Q3, max]; } return await generateChartImage( echartsOption, width, height, theme, outputType, "generate_boxplot_chart", ); }, }; - src/tools/boxplot.ts:15-26 (schema)Zod schema for boxplot input data items: `category` (string), `value` (number), and optional `group` (string). Used within the tool's inputSchema.
const data = z.object({ category: z .string() .describe("Category of the data point, such as 'Category A'."), value: z.number().describe("Value of the data point, such as 10."), group: z .string() .optional() .describe( "Optional group for the data point, used for grouping in the boxplot.", ), }); - src/tools/boxplot.ts:32-46 (schema)The full input schema for the tool: arrays of data items, axis titles, dimensions, theme, title, and output type.
inputSchema: z.object({ axisXTitle: AxisXTitleSchema, axisYTitle: AxisYTitleSchema, data: z .array(data) .describe( "Data for boxplot chart, such as, [{ category: 'Category A', value: 10 }, { category: 'Category B', value: 20, group: 'Group A' }].", ) .nonempty({ message: "Boxplot chart data cannot be empty." }), height: HeightSchema, theme: ThemeSchema, title: TitleSchema, width: WidthSchema, outputType: OutputTypeSchema, }), - src/tools/index.ts:3-3 (registration)Import of generateBoxplotChartTool from the boxplot module.
import { generateBoxplotChartTool } from "./boxplot"; - src/tools/index.ts:35-35 (registration)Registration of generateBoxplotChartTool in the `tools` array, making it available as an MCP tool.
generateBoxplotChartTool,