Back to AI guides

Flint: Microsoft Research's Visualization Language for AI Agents

Stanley Ulili
Updated on August 3, 2026

Asking an AI agent to generate a chart in Vega-Lite tends to produce one of two outcomes: a technically valid specification that looks mediocre, or a verbose JSON blob that renders nothing at all. The problem isn't that the model lacks chart knowledge; it's that Vega-Lite was designed for humans who can reason precisely about pixels, axis domains, and color gradients. LLMs can't.

Flint is a visualization intermediate language from Microsoft Research and Renmin University of China's IDEAS Lab that addresses this by separating what the chart means from how it should be rendered. The AI describes meaning in a concise semantic specification; a deterministic compiler handles all the geometric and aesthetic decisions. The output is a correct, polished chart in Vega-Lite, ECharts, Chart.js, Plotly, or Excel-native format. This article covers the design, how to set it up with Claude Code, and where the current limitations are.

The problem with direct chart generation

A typical Vega-Lite specification for a moderately complex chart can run to 100+ lines of JSON. It requires explicit values for axis domains, scale types, padding, color ramps, label formatting, and dozens of other parameters. These are precise, interdependent geometric decisions. A small error in an axis domain or a misplaced bracket breaks the entire spec.

LLMs are probabilistic token predictors. They're well-suited for semantic understanding and pattern recognition, but not for the kind of exact interdependent arithmetic that low-level chart specifications require. This is why AI chart generation success rates hover around 80%, which sounds reasonable until you realize that one in five charts failing is unusable for any real workflow.

The deeper issue is that chart generation is actually two jobs conflated into one:

The meaning job: Looking at a table with columns for Month, Revenue, and Percentage Change and understanding what each column represents. LLMs do this well.

The math job: Translating that understanding into exact axis scales, color palettes, tick formats, and padding. LLMs do this poorly.

Flint separates them.

How Flint works

A split-screen graphic elegantly showing "Meaning" on one side (representing the LLM's task) and "Math" on the other (representing the compiler's task).

Step 1: The LLM writes a short Flint spec

Instead of generating a full Vega-Lite specification, the model produces a concise Flint spec, typically around 10 lines of JSON. The spec has two main parts:

semantic_types: The model analyzes the data and assigns a semantic type to each relevant column. Flint ships with over 70 built-in types including QUARTER, PRICE, RANK, PERCENTAGE_CHANGE, PROFIT, YEAR_MONTH, and many others.

chart_spec: The high-level structure of the chart: chartType (e.g., Heatmap, Bar), encodings (which fields map to x, y, and color), and general chartProperties like desired colorScheme.

An animation showing the structured extraction of semantic types from data, with a list of over 70 types like Quarter, Price, and Rank.

There are no pixels, no axis domains, no color hex codes. The model's job ends when it has described what the chart means, not how to render it.

Step 2: The Flint compiler generates the full spec

The compiler is a deterministic piece of software that reads the semantic description and makes all the low-level decisions based on data visualization best practices.

When it sees PERCENTAGE_CHANGE, it knows to use a diverging color palette centered on zero with red for negative and blue for positive values. When it sees a PROFIT column, it calculates a sensible axis scale with clean tick marks. When it sees Heatmap, it generates the correct rect marks and encodings.

A diagram illustrating the Flint compiler taking a single input and branching out to produce compiled specs for Vega-Lite, ECharts, and Chart.js.

The output is a complete, correct specification for whichever rendering backend you're using.

Setting up Flint with Claude Code

Flint is a TypeScript library. The MCP server (flint-chart-mcp) makes it available to any agent that supports MCP, including Claude Code.

In your project directory, add Flint as an MCP tool:

 
claude mcp add flint --scope project -- npx -y flint-chart-mcp

This creates a configuration file in your project that makes the render_chart and create_chart_view tools available whenever you're working in that directory.

Place your data file (in this example, signup_data.csv with columns for month, game, and new_users) in the same directory. Then prompt the agent:

Output
Call render_chart with a heatmap of new_users by month and game on the csv I have. I need the actual PNG to appear in the chat. Also show the short Flint spec.

The agent identifies the file, generates a ~10-line Flint spec with appropriate semantic types and encodings, calls render_chart, and returns a PNG image directly in the chat.

The beautiful and clear heatmap of new user signups, generated as a PNG file by the Flint process.

To make the chart interactive, follow up with:

Output
Now call create_chart_view on that same heatmap.

This opens an interactive panel where you can change the color scheme, adjust sorting, and inspect individual data points by hovering. The agent does the initial work; you handle the fine-tuning.

The interactive chart view panel, demonstrating the ability to change the heatmap's color scheme on the fly from the default blue to a vibrant "Plasma" theme.

The semantic layer in action

The real power of the semantic layer is visible when you change a single type annotation. Suppose new_users is actually a month-over-month percentage change rather than an absolute count.

With semantic type Quantity, the compiler produces a sequential color scale (light to dark blue) starting from the data minimum, which is correct for an absolute count.

Change the semantic type to PercentageChange and the compiler makes a completely different set of decisions: it switches to a diverging color scheme (red-white-blue), centers the midpoint on zero, and formats labels and tooltips with a % symbol. The entire visual logic of the chart changes from one word in the spec.

A clear flow diagram showing the Flint Spec on the left, being compiled into a much more verbose Vega-Lite spec in the middle, which then renders the final visualization on the right.

This is the core value of the semantic layer: the model doesn't need to know how to implement a diverging color scale. It only needs to know that the data is a percentage change. The compiler handles the rest.

Flint vs. Vega-Lite

Flint doesn't replace Vega-Lite. It compiles to it. The relationship is similar to a high-level programming language compiling to assembly: Vega-Lite is powerful and explicit but verbose and brittle for machine generation. Flint is concise, focused on intent, and relies on the compiler to handle the details that LLMs should never have been trusted to improvise.

Current limitations

Flint is a Microsoft Research project published in July 2026 and is still in early development.

The chart type coverage is solid for common visualizations but doesn't yet include maps, 3D charts, network graphs, or complex chart layering. Accessibility features are on the roadmap but not yet implemented. The core library is TypeScript/JavaScript only, though a Python port (flint-py) is in preview in the repository and a PyPI package is expected. The compiler also doesn't yet handle all edge cases around high-cardinality data or highly customized layouts that require manual parameter overrides.

That said, the project is already being used internally at Microsoft in their Data Formulator analytics tool, and the pattern it introduces, using a semantic intermediate representation as the contract between LLM and deterministic compiler, is a generalizable approach that's likely to show up across other AI tooling categories as well.

The GitHub repository includes the core flint-chart library, the flint-chart-mcp server, an interactive gallery, and documentation for both the agent workflow and direct library usage. The Microsoft Research blog post covers the design rationale in more depth.

Got an article suggestion? Let us know
Licensed under CC-BY-NC-SA

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.