Flint MCP: Complete Guide (2026)
Flint is Microsoft Research’s answer to a problem every chart-generating agent hits: simple specs render badly, and specs detailed enough to look right are too verbose for a model to write reliably. It ships as two things — a compact intermediate language that compiles to Vega-Lite, ECharts, or Chart.js, and flint-chart-mcp, a real MCP server that lets an agent create, validate, and render charts from inside Claude Code, Cursor, VS Code, or any MCP-capable client. This guide covers what the language does, the five tools the server exposes, how to install it, and — since one of those tools is a working MCP App — exactly where Flint sits next to the MCP Apps spec.

On this page · 16 sections▾
TL;DR + what you need
- What Flint is: a semantics-driven intermediate language (IL) — a compact format between a raw idea and a finished spec — for chart specs. You label what each data field means (a
Country, aRank, aYearMonth) and name a chart type; Flint’s compiler derives the scales, spacing, and layout that used to require hand-tuning. - What flint-chart-mcp is: an MCP server, published on npm, that puts five tools in front of an agent —
render_chart,compile_chart,validate_chart,list_chart_types, andcreate_chart_view. - One command:
npx -y flint-chart-mcp— no API key, no OAuth, nothing to sign up for. - Its MCP Apps connection:
create_chart_viewis registered as an MCP App (theui://interactive-UI mechanism) withrender_chartas the static-image fallback for hosts that don’t support it — see the section below. - How new this is: the repo shipped July 8, 2026 and hit the Hacker News front page the same day. Everything in this guide is traced to the source, the official docs, or the launch thread — treat the API surface as early and likely to move.
Why Flint exists
Ask an agent for “a chart of monthly signups” and you get one of two failure modes. Keep the spec simple and you get a chart leaning on library defaults — cramped labels, an arbitrary color scale, bars in whatever order the data happened to arrive. Make the spec thorough and you get a wall of low-level Vega-Lite or ECharts JSON: explicit scales, explicit axis rotation, explicit spacing, verbose enough that adding one field means rewriting half the spec.
Microsoft Research’s framing, from the project launch post: building a polished chart normally forces a choice between a spec simple enough to generate reliably and a spec detailed enough to look right. Declarative grammars make this worse in one specific way — they work well when a field’s storage type matches its meaning, and get brittle the moment it doesn’t. The integer 202001 is a date, not a magnitude. A percentage-change column isn’t safe to stack. A sequential color ramp is the wrong choice for data that diverges around a midpoint. A human expert routes around these by hand; an agent either doesn’t know to, or burns its context budget trying.
Flint’s bet: separate what the data means from what picture you want, and let a compiler own the judgment calls that used to require a human expert. That is the whole idea in one sentence — everything else in this guide is the mechanics of it.
Mental model: three named pieces
The docs describe Flint’s compiler as a three-phase pipeline sitting between your annotated data and a backend-native spec:
data + semantic_types chart_spec
("what it means") ("what to draw")
\ /
\ /
ChartAssemblyInput (one object)
|
┌───────────────┼────────────────┐
▼ ▼ ▼
Frontend Optimizer Code Generator
(resolve (physics- (instantiate the
encoding type, based layout backend-specific
scale, color, sizing) template)
sort from
semantics)
|
┌───────────────┼────────────────┐
▼ ▼ ▼
Vega-Lite ECharts Chart.js- DataSpec — the
dataandsemantic_typesfields together. This is where the table lives and where each column gets a meaning; author it once per dataset and reuse it across charts. - ChartSpec — the
chart_specfield: which template (“Bar Chart”,“Scatter Plot”,“Heatmap”) and which field goes on which channel. During exploration, this is usually the only part that changes. - Compiler — three phases per the project’s architecture docs: a Frontend that resolves encoding type, format, aggregation, scale, domain, and color from the semantic annotations; an Optimizer that does physics-based layout sizing (axis spans, band widths, aspect ratio); and a Code Generator that instantiates the Vega-Lite, ECharts, or Chart.js template.
Our read: the useful boundary here isn’t “simple vs. detailed,” it’s meaning vs. rendering. Once you accept that split, most of Flint’s design decisions follow from it directly.
Smallest end-to-end example
Every field name below is taken directly from the server’s Zod input schema, not paraphrased. A minimal validate_chart call for a three-row bar chart:
{
"name": "validate_chart",
"arguments": {
"data": {
"values": [
{ "region": "North", "revenue": 120 },
{ "region": "South", "revenue": 90 },
{ "region": "East", "revenue": 150 }
]
},
"semantic_types": {
"region": "Category",
"revenue": "Quantity"
},
"chart_spec": {
"chartType": "Bar Chart",
"encodings": {
"x": { "field": "region" },
"y": { "field": "revenue" }
},
"baseSize": { "width": 360, "height": 240 }
},
"backend": "vegalite"
}
}validate_chart returns whether the spec is valid, the resolved chart type, the computed layout size, and any warnings or errors — the same shape create_chart_view reads internally before it opens a preview:
{
"valid": true,
"chartType": "Bar Chart",
"computedSize": { "width": 360, "height": 240 },
"warnings": []
}Swap the tool name to render_chart with the same arguments and you get a PNG or SVG back inline. Swap it to compile_chart and you get the raw Vega-Lite spec instead — useful when you want to hand-edit the output or feed it to a different renderer.
flint-chart-mcp: the five tools
The MCP server is Flint’s execution counterpart: the agent writes one ChartAssemblyInput, and the server compiles, validates, renders, or opens it locally. Here is the full tool surface, described exactly as the source registers them:
| Tool | What it does |
|---|---|
create_chart_view | Preferred default when the host supports MCP Apps: opens an interactive chart view with a live SVG preview and a customization panel (chart type, channel bindings, sort). Registered as an MCP App, not a plain tool. |
render_chart | Renders a static PNG or SVG inline. The Chart.js backend supports PNG only. Use this when the host has no App UI support, or the user explicitly wants a static image. |
compile_chart | Returns the backend-native spec — Vega-Lite JSON, an ECharts option object, or a Chart.js config — without rendering anything. |
validate_chart | Checks a spec against a backend and reports validity, warnings, errors, and the computed layout size — no rendering. |
list_chart_types | Lists supported chart types and their encoding channels, for one backend or all three. |
Beyond the five tools, the server also registers two resources and a prompt: flint://chart-types (a browsable JSON catalog), flint://agent-skill (a bundled markdown authoring guide the agent can load before it writes a spec), and an author_flint_chart prompt that injects that skill automatically. That is Tools, Resources, and Prompts — three of MCP’s core primitives, plus the Apps extension — from one server. See our MCP primer if those terms are new.
Install (every client)
The server is stdio-only today — your MCP client launches npx -y flint-chart-mcp as a local subprocess. No account, no token, no env block required for the default setup.
Claude Desktop / Cursor
Add this to your MCP client config (Claude Desktop: claude_desktop_config.json; Cursor: ~/.cursor/mcp.json, see /clients/cursor):
{
"mcpServers": {
"flint": {
"command": "npx",
"args": ["-y", "flint-chart-mcp"]
}
}
}Claude Code
One line, via /clients/claude-code’s claude mcp add:
claude mcp add flint -- npx -y flint-chart-mcpVS Code
VS Code’s workspace format uses a servers key and an explicit type. Add this to .vscode/mcp.json (see /clients/vscode):
{
"servers": {
"flint": {
"type": "stdio",
"command": "npx",
"args": ["-y", "flint-chart-mcp"]
}
}
}By default the server can read local .csv, .tsv, and .json files the agent references by path in data.url. For an untrusted or hosted deployment, append --disable-file-reference to the args array — the agent must then pass every dataset inline via data.values, and local file reads are rejected outright.
After restarting your client, a good smoke test is asking the agent to call list_chart_types: if you get a catalog back, auth (or in this case, the absence of it) isn’t the problem for anything that fails later.
Flint vs. the MCP Apps spec
Short version: they compose, they don’t compete. Our MCP Apps spec deep dive covers the general mechanism: a tool result can point at a ui:// resource via _meta.ui.resourceUri, and a supporting host renders that resource as a sandboxed, interactive HTML UI instead of plain text. Flint doesn’t propose an alternative to that — create_chart_view is a working implementation of it.
The source is explicit about this. It imports registerAppTool and registerAppResource straight from @modelcontextprotocol/ext-apps/server (the Apps spec’s own SDK), points create_chart_view at a ui://flint-chart/chart-view.html resource, and hands the server these literal instructions:
Flint compiles one semantic chart spec (ChartAssemblyInput) into
Vega-Lite, ECharts, or Chart.js. By DEFAULT, prefer create_chart_view
to return an interactive, customizable chart whenever the host
supports MCP App UIs — it renders the chart live and lets the user
tweak it. Fall back to render_chart for a static PNG/SVG artifact only
when the host has no App UI support or the user explicitly wants a
static image. Use compile_chart for the backend spec JSON,
validate_chart to check a spec, and list_chart_types to discover chart
types and their channels.That is capability detection, not a design choice made once and hardcoded. The same server offers the Apps-native path (create_chart_view, an interactive live preview with a tweak panel) and the plain-content fallback (render_chart, a static image) side by side, and lets the host’s declared support decide which one an agent should reach for. That is exactly the graceful-degradation pattern our Apps guide argues every UI-capable server should ship — “always ship a text fallback” is the line from that post, and Flint’s fallback happens to be a rendered image instead of text, which is a reasonable variant for a tool whose whole output is visual.
Our Apps deep dive names ECharts, VChart, and AntV’s MCP Server Chart as early UI-shaped chart servers. flint-chart-mcp is the newest entry, and arguably the clearest single-server illustration of the produce/render duality — both paths sit behind one shared spec instead of being two different servers with two different input shapes.
Recipes
Recipe 1 — From a query result to a live chart
“Chart this quarter’s revenue by region as a bar chart, and let me tweak it.” The agent maps the query result into data.values, annotates semantic_types (region as Category, revenue as Quantity), calls validate_chart to catch mistakes early, then create_chart_view to open the interactive preview. In a host without App support, the same prompt should fall back to render_chart for a static image — worth testing both paths if you support more than one client.
Recipe 2 — A static PNG for a report or CI artifact
“Generate a PNG of weekly signups for the changelog.” Same ChartAssemblyInput, but the agent calls render_chart directly with format: "png" and a fixed backend. Because rendering runs in-process on the machine hosting the MCP server, this drops cleanly into a script or CI step with no browser and no external rendering service in the loop.
What we got wrong
Three assumptions we made before reading the source, and what the code actually showed:
- We assumed “Flint vs. MCP Apps” was an either/or framing. It isn’t.
create_chart_viewis built directly on the Apps spec’s server SDK, withrender_chartas the documented fallback. That’s composition, not competition — we had to readserver.tsto find that out; it isn’t obvious from the README alone. - We assumed “70+ semantic types” was loose marketing language for a label list. The schema says otherwise: a semantic type can carry an
intrinsicDomain(e.g. a 1–5 rating scale), aunit, and a customsortOrder, all of which change what the compiler emits. It behaves closer to a small type system than a tag. - We assumed a same-week research repo would ship a thin, single-tool demo. Instead it registers five tools, two resources, and a prompt, with a Dockerfile and a real test suite in the same package. That is more MCP surface than several production servers we’ve covered on this site.
Gotchas & limits
- No remote transport yet. The server runs stdio-only via
npx. An HTTP--transportflag was requested in issue #47 the day after launch and was still open as of this writing — a remote-hosted MCP setup needs your own wrapper today. - Chart.js output is PNG-only. The tool descriptions say so explicitly: ask for SVG on the
chartjsbackend and you won’t get one. Usevegaliteorechartswhen you need vector output. - Python isn’t installable yet. The repo includes a
flint-pypackage, but the docs call it “a source preview” with PyPI publishing “planned for a later release.” Python-only agent stacks can’tpip installthis today. - Local file reads are on by default. Unless you pass
--disable-file-reference, the server will read any local CSV, TSV, or JSON file the agent references by path. Fine for a personal coding session; worth locking down for anything multi-tenant. - Wide-format, multi-series data needs reshaping first. A real early user hit this in issue #10: a table with one column per series (e.g.
Sales AmountandSales Amount by Due Dateas separate columns) can’t be mapped onto one Line Chart encoding directly. Melt the table into one row per series-value first.
Who this is for
Good fit
- Agents that already emit Vega-Lite/ECharts/Chart.js and produce inconsistent-looking charts
- Coding hosts (Claude Code, Cursor, VS Code) where an agent should show, not just describe, a chart
- Teams that want a validate-before-render loop instead of trial-and-error prompting
- Agent-skill authors who want a bundled authoring contract instead of hand-written chart instructions
Not (yet) a fit
- Chart types outside Flint’s template catalog — you’re back to hand-written backend specs
- Python-only agent stacks wanting a
pip installtoday - Remote or multi-tenant MCP deployments needing built-in HTTP transport
- Anyone wanting pixel-level control over every visual property — the compiler owns those decisions by design
Community signal
The Show HN thread split cleanly between practitioners excited about the pattern and commenters skeptical of the “for AI agents” framing itself. Four voices, verbatim:
“There's an emerging pattern in agentic systems and this project is a great example. A deterministic layer like a compiler or generator of code with some kind of IR that the LLM generates and feeds it with. I feel we will be seeing this more and more in the near future.”
cpard · Hacker News
The framing take — Flint as an instance of a broader compiler-in-the-loop pattern for agentic systems.
“Isnt graphviz there for the same reason? Edit: I see it is using JSON as the declaration language, I am OK with llms being 'good at json' but a syntax also consumable by humans it is not!”
theK · Hacker News
The skeptical take — questioning whether JSON-as-spec is actually more human-editable than the alternative.
“This is cool to see from a research team. A few weeks ago I was exploring a similar idea with ntcharts... But Flint goes much deeper with semantic layers and settings optimizations.”
neomantra · Hacker News
A builder of a similar Go/TUI charting project — praised the semantic-type layer specifically, then filed a GitHub issue proposing ntcharts as an additional backend.
“Higher level implies information loss. So it can only be better if it is doing so by assuming some better defaults. But then you have to ask if it lost expressiveness.”
zmmmmm · Hacker News
The contrarian close — every abstraction layer trades expressiveness for defaults; the question is whether Flint's trade is the right one.
The thread also produced a real, fast community artifact: within a day of launch, a third-party developer published flint-chart-skill, an independent agent skill wrapping Flint, and posted it back into the HN thread as “tested.” That kind of same-day derivative is a better adoption signal than any comment count.
The verdict
Our take
Install flint-chart-mcp if your agent already produces charts and the results look inconsistent — the semantic-type model removes a real class of mistakes (wrong scale type, bad stacking, mismatched color ramps) that prompting an agent to write raw Vega-Lite or ECharts doesn’t catch. It is also the cleanest single-server example available right now of the MCP Apps produce/render duality: one spec, an interactive path and a static fallback, chosen automatically. Skip it, or wait, if you need chart types outside its template catalog, a Python-native pipeline, or a remote/HTTP deployment — and go in expecting a one-day-old API surface to keep moving.
FAQ
What is Microsoft Flint?
Flint is Microsoft Research's semantics-driven intermediate language for chart specs. Instead of low-level Vega-Lite or ECharts parameters, you label each field's meaning (Country, Rank, YearMonth) and pick a chart type; a compiler derives the visual details. It shipped July 8, 2026 as MIT-licensed open source at github.com/microsoft/flint-chart, alongside the flint-chart-mcp server.
Is flint-chart-mcp a real MCP server?
Yes. It's a published npm package (npx -y flint-chart-mcp) registering five real tools — render_chart, compile_chart, validate_chart, list_chart_types, create_chart_view — plus two resources and a prompt, backed by a test suite and Dockerfile in the same repo as the flint-chart library. It is not a demo stub.
How do agents generate charts with Flint's MCP server?
The agent writes one ChartAssemblyInput object: a data block, a semantic_types map, and a chart_spec naming the chart type and channel encodings. It calls validate_chart to check the spec, then create_chart_view for a live interactive preview (when the host supports MCP Apps) or render_chart for a static PNG/SVG.
Why not have the agent write Vega-Lite or ECharts JSON directly?
Both are already common in LLM training data, and Hacker News commenters raised exactly this objection. Flint's answer: raw specs force the model to hand-pick scales, color ramps, and spacing. Flint's compiler derives those from semantic type plus chart type, so the agent writes a shorter, less brittle spec.
How does Flint relate to the MCP Apps spec?
They compose, not compete. create_chart_view is registered as an MCP App — the ui:// resource mechanism our MCP Apps spec guide covers — so hosts with App support get a live preview. Hosts without it get render_chart's plain PNG/SVG instead, from the same server, same spec.
What chart types and libraries does Flint support?
Three backends — Vega-Lite, Apache ECharts, and Chart.js (Chart.js is PNG-only, no SVG) — covering 30+ chart types from one shared spec via 70+ semantic types like Rank, Temperature, Price, or Country. Call list_chart_types on the MCP server for the live catalog per backend.
Is Flint free and open source?
Yes. Both flint-chart (the library) and flint-chart-mcp (the server) are MIT-licensed and free on npm. Rendering happens in-process on whatever machine runs the MCP server — nothing is uploaded to a hosted rendering service unless you build that yourself.
Glossary
- Flint — the semantics-driven intermediate language (IL) for chart specs; the project name for the whole effort.
- flint-chart — the npm package with the core compiler/library (JS/TS), importable directly into an app.
- flint-chart-mcp — the npm package that wraps the compiler in an MCP server for agents.
- Semantic type — a label like
Country,Rank, orYearMonththat tells the compiler what a column means, not just its storage type. - ChartAssemblyInput — the one object an agent authors:
data+semantic_types+chart_spec(plus optionaloptionsandfield_display_names). - DataSpec — the
data+semantic_typeshalf of the input: what the table contains and what each column means. - ChartSpec — the
chart_spechalf: which chart template and which field goes on which channel. - Backend — one of Flint’s three compile targets:
vegalite,echarts, orchartjs. - MCP Tool — a named function an MCP server exposes that a model can call, like
render_chart. - MCP Resource — read-only content an MCP server exposes by URI; Flint uses
flint://chart-typesandflint://agent-skill. - MCP App / ui:// resource — the MCP Apps extension mechanism for a tool to return a live, interactive HTML UI in a sandboxed iframe; Flint’s
create_chart_viewis one. - Agent skill — a bundled instructions file (here
flint-chart-author.SKILL.md) an agent loads before authoring specs, exposed as both an MCP resource and a prompt. - stdio server — an MCP server launched as a local subprocess that talks JSON-RPC over stdin/stdout; how
flint-chart-mcpruns today.
Sources
Primary
- github.com/microsoft/flint-chart — repo, README, source (MIT license, TypeScript)
- npmjs.com/package/flint-chart-mcp — the MCP server package
- npmjs.com/package/flint-chart — the core compiler/library package
- Microsoft Research — “Flint: A Visualization Language for the AI Era” (Chenglong Wang, Alper Sarikaya, Scott Tsukamaki, Michel Galley, Jianfeng Gao)
- microsoft.github.io/flint-chart — documentation site (overview, tutorials, API reference)
Community
- Show HN: Microsoft releases Flint, a visualization language for AI agents — posted by chenglong-hn (the project’s own lead researcher), July 8, 2026
- github.com/tcsenpai/flint-chart-skill — independent agent skill built on Flint, shipped within a day of launch
- GitHub issues referenced above: #10 (multi-series spec), #47 (HTTP transport)
Internal — read next
- /blog/mcp-apps-spec-2026-when-should-your-server-render-ui — the general framework behind
create_chart_view - /blog/best-mcp-servers-for-design-2026 — the wider roundup of design- and UI-adjacent MCP servers
- /blog/what-is-mcp — Tools, Resources, and Prompts, defined from scratch
- mcp.directory/servers — browse the full MCP server catalog
Spec deep dive
MCP Apps Spec — when should your server render UI?
ReadRoundup
Best MCP Servers for Design in 2026
ReadPrimer
What is the Model Context Protocol?
ReadFound an issue?
Flint shipped a day before this guide was written, so details will move — new tools, an HTTP transport, Python on PyPI. If something here is out of date, email [email protected] or see our about page. We keep these guides current.