Skip to main content
Glama

generate_bar_chart

Create bar charts to visualize numerical comparisons across categories. Customize axes, group or stack data, and export as PNG, SVG, or ECharts options for clear insights into horizontal data trends.

Instructions

Generate a bar chart to show data for numerical comparisons among different categories, such as, comparing categorical data and for horizontal comparisons.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
axisXTitleNoSet the x-axis title of chart.
axisYTitleNoSet the y-axis title of chart.
dataYesData for bar chart, such as, [{ category: 'Category A', value: 10 }, { category: 'Category B', value: 20 }] or [{ category: 'Category A', value: 10, group: 'Group A' }].
groupNoWhether grouping is enabled. When enabled, bar charts require a 'group' field in the data. When `group` is true, `stack` should be false.
heightNoSet the height of the chart, default is 600px.
outputTypeNoThe 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
stackNoWhether stacking is enabled. When enabled, bar charts require a 'group' field in the data. When `stack` is true, `group` should be false.
themeNoSet the theme for the chart, optional, default is 'default'.default
titleNoSet the title of the chart.
widthNoSet the width of the chart, default is 800px.

Implementation Reference

  • The 'run' handler function that executes the tool logic: processes data for single or grouped/stacked bars, constructs ECharts configuration, and generates the chart image.
    run: async (params: {
      axisXTitle?: string;
      axisYTitle?: string;
      data: Array<{ category: string; value: number; group?: string }>;
      height: number;
      group?: boolean;
      stack?: boolean;
      theme?: "default" | "dark";
      title?: string;
      width: number;
      outputType?: "png" | "svg" | "option";
    }) => {
      const {
        axisXTitle,
        axisYTitle,
        data,
        height,
        group = false,
        stack = false,
        theme,
        title,
        width,
        outputType,
      } = params;
    
      // Check if data has group field for multiple series
      const hasGroups = data.some((item) => item.group);
    
      let series: Array<SeriesOption> = [];
      let categories: string[] = [];
    
      if (hasGroups && (group || stack)) {
        // Handle multiple series data (grouped or stacked)
        const groupMap = new Map<
          string,
          Array<{ category: string; value: number }>
        >();
        const categorySet = new Set<string>();
    
        // Group data by group field and collect all categories
        for (const item of data) {
          const groupName = item.group || "Default";
          if (!groupMap.has(groupName)) {
            groupMap.set(groupName, []);
          }
          const groupData = groupMap.get(groupName);
          if (groupData) {
            groupData.push({ category: item.category, value: item.value });
          }
          categorySet.add(item.category);
        }
    
        // Sort categories
        categories = Array.from(categorySet).sort();
    
        // Create series for each group
        groupMap.forEach((groupData, groupName) => {
          // Create a map for quick lookup
          const dataMap = new Map(groupData.map((d) => [d.category, d.value]));
    
          // Fill values for all categories (0 for missing data)
          const values = categories.map((category) => dataMap.get(category) ?? 0);
    
          series.push({
            data: values,
            name: groupName,
            stack: stack ? "Total" : undefined,
            type: "bar",
          });
        });
      } else {
        // Handle single series data
        categories = data.map((item) => item.category);
        const values = data.map((item) => item.value);
    
        series = [
          {
            data: values,
            type: "bar",
          },
        ];
      }
    
      const echartsOption: EChartsOption = {
        legend:
          hasGroups && (group || stack)
            ? {
                left: "center",
                orient: "horizontal",
                bottom: 10,
              }
            : undefined,
        series,
        title: {
          left: "center",
          text: title,
        },
        tooltip: {
          trigger: "axis",
        },
        xAxis: {
          data: categories,
          name: axisXTitle,
          type: "category",
        },
        yAxis: {
          name: axisYTitle,
          type: "value",
        },
      };
    
      return await generateChartImage(
        echartsOption,
        width,
        height,
        theme,
        outputType,
        "generate_bar_chart",
      );
    },
  • The Zod inputSchema defining the tool's parameters including data array, axes titles, dimensions, group/stack options, theme, title, and output type.
    inputSchema: z.object({
      axisXTitle: AxisXTitleSchema,
      axisYTitle: AxisYTitleSchema,
      data: z
        .array(data)
        .describe(
          "Data for bar chart, such as, [{ category: 'Category A', value: 10 }, { category: 'Category B', value: 20 }] or [{ category: 'Category A', value: 10, group: 'Group A' }].",
        )
        .nonempty({ message: "Bar chart data cannot be empty." }),
      height: HeightSchema,
      group: z
        .boolean()
        .optional()
        .default(false)
        .describe(
          "Whether grouping is enabled. When enabled, bar charts require a 'group' field in the data. When `group` is true, `stack` should be false.",
        ),
      stack: z
        .boolean()
        .optional()
        .default(false)
        .describe(
          "Whether stacking is enabled. When enabled, bar charts require a 'group' field in the data. When `stack` is true, `group` should be false.",
        ),
    
      theme: ThemeSchema,
      title: TitleSchema,
      width: WidthSchema,
      outputType: OutputTypeSchema,
    }),
  • The Zod schema for individual data points used in the bar chart data array.
    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("Group name for multiple series, used for grouping or stacking"),
    });
  • Registration of generateBarChartTool (line 22) in the exported tools array for MCP tool server.
    export const tools = [
      generateEChartsTool,
      generateLineChartTool,
      generateBarChartTool,
      generatePieChartTool,
      generateRadarChartTool,
      generateScatterChartTool,
      generateSankeyChartTool,
      generateFunnelChartTool,
      generateGaugeChartTool,
      generateTreemapChartTool,
      generateSunburstChartTool,
      generateHeatmapChartTool,
      generateCandlestickChartTool,
      generateBoxplotChartTool,
      generateGraphChartTool,
      generateParallelChartTool,
      generateTreeChartTool,
    ];
  • Re-export of generateBarChartTool for convenient use.
    generateBarChartTool,
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. The description only states what the tool does ('generate a bar chart') without detailing behavioral traits such as output format (e.g., returns an image, SVG, or configuration), performance characteristics, error handling, or any side effects. It lacks context on what the tool returns or how it behaves beyond the basic action, which is insufficient for a tool with 10 parameters and no output schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (one sentence) but could be more front-loaded with critical information. It efficiently states the purpose, but the phrasing ('such as, comparing categorical data and for horizontal comparisons') is slightly awkward and redundant. While not wasteful, it lacks structural clarity for quick scanning, such as separating use cases from core functionality.

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?

Given the complexity (10 parameters, no annotations, no output schema), the description is incomplete. It doesn't address what the tool returns (e.g., image data, file path, or configuration), how to handle errors, or any behavioral nuances. For a data visualization tool with multiple output types and grouping/stacking options, more context is needed to guide effective use, especially without annotations or output schema.

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?

Schema description coverage is 100%, so the schema already documents all parameters thoroughly. The description adds no specific parameter information beyond implying data structure through examples like 'categorical data.' It doesn't explain parameter interactions, defaults, or usage beyond what's in the schema. With high schema coverage, the baseline is 3, as the description doesn't compensate but doesn't detract either.

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 purpose: 'Generate a bar chart to show data for numerical comparisons among different categories.' It specifies the verb ('generate') and resource ('bar chart'), and mentions the use case ('numerical comparisons among different categories'). However, it doesn't explicitly differentiate from sibling tools like 'generate_line_chart' or 'generate_pie_chart' beyond mentioning 'categorical data' and 'horizontal comparisons,' which are inherent to bar charts but not unique compared to other chart types.

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. It mentions 'categorical data' and 'horizontal comparisons,' which are typical for bar charts, but doesn't explain when to choose a bar chart over other chart types like line charts or pie charts from the sibling list. There are no explicit when-to-use or when-not-to-use statements, nor any mention of prerequisites or alternatives.

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

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

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