AI agents
Let an AI assistant draft charts while chartlet validates and compiles them, through the MCP server @casoon/chartlet-mcp.
An assistant is good at reading a request and drafting a specification; it is not reliable at
drawing a correct chart or describing data exactly. @casoon/chartlet-mcp splits the work: the
assistant proposes, chartlet validates and compiles deterministically. The server runs no
language model, never changes the data, and reports only facts it can compute.
In practice
- A chart from a data file: “Make a chart from
data/revenue-2026.csvfor the Q3 report and save it tosrc/charts/.”chartlet_inspect_datasuggests grouped bars;chartlet_validate_specrejects the first draft withseries_length_mismatchand the hint to usenullfor the missing Q4 value;chartlet_renderwrites the figure tosrc/charts/revenue-q3.html. - A diagram from a description: “Draw our checkout flow as a sequence diagram: browser, API,
payment provider, database.”
chartlet_diagram_startergives a valid sequence specification to start from; the assistant fills in participants and messages, and chartlet lays the diagram out. - Fixing an existing chart: “The labels in the plans chart get cut off – fix it.”
chartlet_validate_specreportstext_truncatedfor all five labels; with"orientation": "horizontal"the warnings are gone. - Text for a report: “Write two sentences about the revenue chart.”
chartlet_explainreturns first, last, minimum, maximum and missing values; the sentences use only those. - A timeline: “Show the relaunch phases with the launch milestone as a timeline.”
chartlet_validate_specwarns withfollows_overlapthat the build phase starts before the design phase ends; the assistant moves the start and renders the timeline.
Setup
The server speaks the Model Context Protocol over stdio. In Claude Code:
claude mcp add --env CHARTLET_MCP_ROOT="$PWD" chartlet -- npx -y @casoon/chartlet-mcp
For Claude Desktop and project configuration, see the package README.
Tools
-
chartlet_inspect_datareads CSV or row objects and returns the row count, per column the inferred type, missing values and range, and which chart types fit, each with the columns to use and a reason. The rules are fixed: a category and numbers suggest a bar chart, a time column and numbers a time chart, open/high/low/close anohlclayer, low/high a range bar, years and one value warming stripes, dates of one year and one value a calendar. Tables of other shapes get the types with a block of their own: two numbers a scatter plot, a repeating category and numbers a box plot (or violin), unique labels with positive numbers a treemap, with values of both signs a waterfall,from/tocolumns a Sankey diagram, a time column and a 0/1 event column survival curves, unique labels with two dates a timeline. -
chartlet_validate_specrenders the specification and discards the output. It returnsok, the error withcode, JSON Pointerpathandmessage, and every warning, for the desktop and themobilelayout. An invalid specification is a regular result, so the assistant can fix the field the path points to and try again. -
chartlet_renderreturns the SVG or HTML with warnings, CSPstyleHashesand the provenance manifest. WithoutputPathit writes the file below the directory named byCHARTLET_MCP_ROOTinstead and returns the path and size. -
chartlet_explainreturns the description chartlet generates for the chart and, per series or layer, count, missing values, minimum, maximum, first and last value with their labels or times. The result says that it is computed, not interpreted; conclusions about causes or trends stay with the reader. -
chartlet_diagram_starterreturns, forsequence,flow,state,architecture,treeorclasses, a valid starting specification, the kinds every element can take with the shape each is drawn in, and notes on ids, layout and orientation. For a diagram,chartlet_explainadds its structure: the counts of its elements and every row of its data table. Withtype: "architecture",templatepicks a starter at one level of abstraction —context,containersordeployment— and the result adds thequestionit answers and itslevel; see Context, containers and deployment for what each level shows and where it stops short of a complete architecture model. -
chartlet_chart_starterreturns a valid starting specification and notes for the charts that are drawn from a block of their own:waterfall,waffle,parliament,treemap,sankey,survival,scatter,timeline,forest(a range bar chart),violin(a box plot) and the flow presetsprismaandinstances.
The resource chartlet://schema holds the specification
schema.
In the chat
In a client that supports MCP Apps,
chartlet_render also shows the chart in the conversation through the view
ui://chartlet/figure: the HTML profile as the compiler renders it, with
caption, source and the data table. The view draws nothing itself; its one script talks to the
client. It follows the client’s light or dark theme when the specification sets no theme,
switches to a mobile layout when it is narrow, and offers “Download SVG”, “Download HTML” and
“Copy specification” as keyboard-reachable buttons. Styles come from the shared stylesheet
(styles: "external"), which the view resource carries once; it loads nothing from the network.
Clients without MCP Apps support get the same text result as before.
With opengrid
chartlet_inspect_data takes the row objects of an opengrid selection or of opengrid’s JSON
export unchanged; decimals written as strings are read as numbers. The servers are not coupled:
the chart is static, and a click in it does not filter the grid.
What the server refuses
- To guess:
1,234is a string, not a number, and an unsorted time column is reported, not sorted. Suggestions name what has to change first, such as aggregating repeated categories. - To write anywhere unless the client configuration names a directory in
CHARTLET_MCP_ROOT. Inside it, absolute paths,.., and symbolic links that lead out are refused.
With the npm package
The tools are a thin layer over renderChartDetailed from @casoon/chartlet, which returns the
compiler’s diagnostics as data instead of throwing; see
JavaScript runtimes.