API Reference
The full @bonnard/mcp-charts export surface, including addCharts, the dashboard and views authoring API, widget hosting, the embed-mode contract, and the adapter building blocks.
The package root exports two registration entry points plus the authoring, widget-hosting, embed, and adapter helpers:
| Export | Registers / does |
|---|---|
addCharts | The ad-hoc visualize tool (agent writes SQL). |
addViews | explore_views + render_view over a set of named views. |
chart, chartCell, explain | Build specs / cells; diagnose an encoding. |
| Widget hosting | WIDGET_HTML, WIDGET_META, registerChartWidget, the resource URI. |
| Embed mode | The postMessage contract for driving the widget in your own layout. |
| Adapter kit | buildChartData, defaultNormalizeCell, assertReadOnlySql. |
addCharts(server, options)
Registers the visualize tool and the ui://bonnard/chart widget resource on an existing MCP
server.
import { addCharts } from "@bonnard/mcp-charts";
addCharts(server, options);AddChartsOptions
| Option | Type | Description |
|---|---|---|
runSql | (sql, ctx: ChartContext) => Promise<ChartData> | Required. Runs the agent's SQL and returns rows (and optionally typed fields). ctx carries tenant/roles/signal. |
discovery | { toolName: string } | Optional. Names your schema-discovery tool so the visualize description can point the agent to it. |
allow | ChartType[] | Optional. Restricts the chartType enum exposed to the agent (default: all eight). |
toolName | string | Optional. Override the tool name (default "visualize"). |
ChartData
interface ChartData {
rows: Record<string, unknown>[];
fields?: FieldMeta[]; // optional typed columns; inferred from the rows when omitted
}When fields are omitted, column roles (dimension, measure, time) and formats are inferred from the
data and column names.
The visualize tool
Once registered, the agent calls visualize with:
sql: the query to run (required)chartType: one of the supported chart types (optional; auto-detected when omitted)title: a chart title (optional)stacking:"stacked","grouped", or"stacked100"(optional). Bar and area only.stacked100normalises each x position to 100%.horizontal: boolean (optional). Bar only. Runs bars horizontally with categories on the y-axis. Bars are vertical unless you set this, except that the widget auto-flips when a category label runs past 12 characters.reference:{ target?: number, average?: boolean }(optional). Draws horizontal lines on the value axis:targetat a fixed value,averageat the mean of the primary series.encode: explicit column mapping (optional). Acceptsx,y,series,y2(measures on a secondary right axis, drawn as a line),line(measures drawn as a line on the same axis), andsize(scatter only, a third numeric column mapped to point size).
The result returns a ChartSpec in structuredContent for the widget, plus a text fallback for
non-widget clients.
addViews(server, options)
Registers two tools over a registry of named views: explore_views (list) and render_view (render
one by view_id). Each view returns a ChartSpec or a DashboardSpec. This is the one authored
entrypoint for both single charts and dashboards.
import { addViews, chart } from "@bonnard/mcp-charts";
addViews(server, {
views: [
{
id: "revenue_trend",
title: "Revenue trend",
description: "Monthly revenue",
render: () => chart(rows, { chartType: "line" }),
},
],
});| Option | Type | Description |
|---|---|---|
views | ViewDef[] | Required, non-empty. Duplicate ids throw. |
exploreToolName | string | Rename the discovery tool (default "explore_views"). |
renderToolName | string | Rename the execute tool (default "render_view"). |
renderDescription | string | Extra text appended to render_view's description. |
render_view inputs
render_view takes:
view_id(required): the view to render, an enum of the registered ids.params(optional): the chosen view's declared params, validated per view (strict).item_id(optional): for adashboard-kind view, theidof one chart cell to render alone.paramsapply to the whole view first, then the named cell is projected out and returned as aChartSpec. AChartCellgets itsidfromchartCell(rows, { id }). See Rendering one cell.
See Named views for the ViewDef shape and per-view params.
Authoring helpers
Build specs and cells directly, or diagnose an encoding:
| Export | Signature | Purpose |
|---|---|---|
chart | (rows | ChartData, opts?) => ChartSpec | Build a single chart spec. Inference sniffs raw rows; a typed ChartData is trusted. |
chartCell | (rows | ChartData, opts) => ChartCell | Like chart, wrapped as a dashboard cell (adds span and an optional id for item_id selection). |
explain | (rows | ChartData, opts?) => ChartExplanation | The inferred typing and resolved encoding, no render payload, for tests. See Connecting a Database. |
resolve | (ChartData, opts?) => ChartSpec | The pure encoding brain chart is built on. |
dashboardResult | (DashboardSpec, opts?) => result | Build the widget-linked result envelope by hand. |
summarizeDashboard | (DashboardSpec) => string | The default text summary (chart lines carry the cell id when set). |
DASHBOARD_OUTPUT_SCHEMA | zod raw shape | The permissive outputSchema for a hand-registered DashboardSpec-returning tool. |
isChartSpec / isDashboardSpec | (spec) => boolean | Runtime guards discriminating the two spec shapes. |
inferFields | (ChartData) => FieldMeta[] | The typing pass on its own: the resolved FieldMeta for each column, unioning declared fields with the returned columns. |
opts on chart / chartCell / explain is ResolveOptions (chartType, title, stacking,
horizontal, reference, strict) plus the fields and encode escape hatches. See
Connecting a Database for typed fields and strict.
Widget hosting
addCharts and addViews register the widget for you. These exports let you serve the same
renderer yourself, or register the resource without a tool.
| Export | Type | Purpose |
|---|---|---|
WIDGET_HTML | string | The self-contained widget HTML, the same file the MCP resource serves. Serve it from your own route for embed mode. |
WIDGET_META | { ui, "openai/..." } | The _meta that links a tool result to the widget: ui.resourceUri plus the openai/outputTemplate alias for ChatGPT. |
VIEW_OUTPUT_SCHEMA | zod object | The permissive outputSchema for a hand-registered view tool, so hosts that gate structuredContent on a schema forward it. |
registerChartWidget | (server) => void | Registers the ui://bonnard/chart resource alone, with no tool. Idempotent. |
CHART_RESOURCE_URI | "ui://bonnard/chart" | The resource URI the widget is registered under. |
Embed mode
Render one chart, KPI, or table with no chrome of its own inside a layout you own, driven over
postMessage. Serve WIDGET_HTML from your own route with a #embed fragment, then send it a
render message. The package root exports the wire contract:
| Export | Type | Purpose |
|---|---|---|
EMBED_PROTOCOL_VERSION | number | The protocol version the installed widget speaks. Carried on bonnard:ready. |
EMBED_LIMITS | object | The bounds the widget enforces on a payload (maxRows, maxItems, maxSeries, and others). Exceeding one is refused whole with a payload-too-large error, not truncated. The values are not part of the stable surface. |
EmbedPayload | type | What you send to render: the spec plus sizing and theme tokens. |
EmbedTokens | type | Theme tokens the parent passes so the widget matches its surface. |
EmbedSizing | "fill" | "content" | How the payload is sized: fill takes the container, content measures itself. |
BonnardRenderMessage | type | The parent-to-widget render message. |
BonnardParentMessage | type | Union of every message the parent sends. |
BonnardWidgetMessage | type | Union of every message the widget sends back. |
BonnardReadyMessage | type | Sent once the widget is ready to receive a render. |
BonnardSizeMessage | type | Sent when the widget reports its size. |
BonnardContentSizeMessage / BonnardFillSizeMessage | types | The two sizing replies, for content-sized and fill-sized modes. |
BonnardErrorMessage / BonnardErrorCode | types | The error reply and its code enum, for a payload the widget refuses. |
See Embed mode for the fragment flags, the message sequence, sizing, theme precedence, and the security model.
Building blocks for custom adapters
If you are writing your own adapter, these are exported from the package root:
| Export | Purpose |
|---|---|
buildChartData | Turns driver rows + columns into ChartData using a kind mapper. |
defaultNormalizeCell | Default per-cell normalisation (dates, numerics, etc.). |
assertReadOnlySql | Lightweight SELECT-only guardrail for SQL strings. |
Supporting types: SourceColumn, KindMapper, CellNormalizer, BuildChartDataOptions.
The bundled warehouse adapters are built on exactly these primitives. Read their source for worked examples.