# MCP Charts: Add Interactive Charts to Your MCP Server

> Source: <https://dev.to/maxbonnard/mcp-charts-add-interactive-charts-to-your-mcp-server-po1>
> Published: 2026-07-16 14:49:01+00:00

Your MCP server returns data. The agent reads it back as a wall of numbers, or it tries to draw a chart in HTML and gets it wrong. The visual, the part the user actually wanted, gets left to the model to improvise.

MCP charts fix that. You give your MCP server one `visualize`

tool: the agent calls it with a query, your database returns the rows, and an interactive chart renders right in Claude or ChatGPT. You write no frontend code. That is what [ @bonnard/mcp-charts](https://www.npmjs.com/package/@bonnard/mcp-charts) does, handling the tool, the chart, the cross-host widget, and the theming.

``` js
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { addCharts } from "@bonnard/mcp-charts";
import { postgresRunSql } from "@bonnard/mcp-charts/postgres";

const server = new McpServer({ name: "acme", version: "1.0.0" });

addCharts(server, {
  runSql: postgresRunSql(pool), // maps pg column types to chart field kinds
});
```

A chart in an MCP client is not an image. It is an interactive widget the host renders from a spec the tool returns.

`visualize`

with a query (SQL, a semantic query, or chart params).`runSql`

callback runs it against your warehouse or ORM and returns rows.`ui://`

widget.You connect the data. Bonnard never sees your database, only the rows your callback returns. Native adapters ship for Postgres, BigQuery, Snowflake, Databricks, and DuckDB, or pass your own `runSql`

.

`@bonnard/mcp-charts`

renders line, bar, area, pie, scatter, funnel, waterfall, and table, with bar variants for stacked, grouped, horizontal, and 100% stacked. Set `chartType`

or let the resolver pick from the shape of the data: a time dimension and a measure becomes a line; a category and a measure becomes a bar.

Without one, an agent that is asked for "revenue by region as a chart" has two bad options. It dumps a wall of numbers, or it generates HTML and hopes the host renders it. Both put the most important part of the answer, the visual, in the model's hands to improvise.

A dedicated tool fixes that:

The common pattern is two tools: one for the agent to learn your schema, one to chart the result.

```
// the agent discovers tables, writes SQL, then charts the rows
server.registerTool("explore_schema", { /* list tables + columns */ }, listSchema);
addCharts(server, { runSql });
```

Point any MCP client at the server. Ask "chart monthly revenue by plan." The agent writes the query, runs it through your callback, and the bar chart appears in the chat.

Most MCP chart servers take chart parameters from the agent and render a generic image. Bonnard takes your query result and infers the chart, so the visual is grounded in real data, not in parameters the model made up.

| Server | Input | Output | Grounded in your data | Agent experience |
|---|---|---|---|---|
AntV `mcp-server-chart`
|
chart params | static image | No | Basic |
| Highcharts MCP | chart params | static image | No | Basic |
| Mermaid Chart MCP | diagram spec | diagram | No | Basic |
`@bonnard/mcp-charts` |
your query result | interactive widget | Yes | Summaries, row caps, instructive errors |

Install `@bonnard/mcp-charts`

, call `addCharts(server, { runSql })`

, and pass a callback that runs SQL against your data. That registers a `visualize`

tool. The agent calls it; the chart renders in the client. No UI code.

If your MCP server returns data an agent will summarize, yes. A chart in the conversation is faster to read than a table, and a dedicated tool keeps the visual deterministic instead of letting the model draw HTML it might get wrong.

Hosts that support MCP apps render the interactive widget. Today that is Claude and ChatGPT. More clients are adding app/widget support.

Pick on where the chart comes from. If you want the agent to pass chart specs, a generic server like AntV works. If you want charts grounded in your own query results, with no frontend code and agent-tuned behavior, that is what `@bonnard/mcp-charts`

is built for.

No. You provide the `runSql`

callback. Bonnard renders the rows it returns and never connects to your database.

Add it to your server in a few lines: [ @bonnard/mcp-charts](https://github.com/bonnard-data/mcp-charts). For the design behind an agent-friendly chart tool, see
