Skip to content
H.P. Gansevoort edited this page Sep 23, 2026 · 84 revisions

MatPlotLibNet Wiki

Matplotlib-inspired charting for .NET. MatPlotLibNet renders charts on the server as SVG, PNG, PDF or animated GIF. It ships an MCP server, so an AI agent can render charts with it. It has 83 series types, 13 map projections with embedded Natural Earth data, 30 themes, LaTeX-style MathText, O(1) streaming with 58 technical indicators, a control room (Plt.OpsDashboard(): KPI tiles, state timelines, a service-topology panel and one shared trend window), and native controls for Blazor, WPF, MAUI, Avalonia, Uno and ASP.NET Core. The API is fluent and works with dependency injection. There is no JavaScript framework, no WebView and no SaaS.

1.18.0 is the current release. Charts now draw inside a Verso notebook cell. Verso is the open-source notebook built to replace Polyglot Notebooks, and MatPlotLibNet.Verso is an extension you install from its Extensions panel: after that, a cell that ends on a figure — or on the builder that makes one, without .Build() — shows the chart instead of a line of type names. A chart fills the width of the cell, and one taller than the cell can show gets a scroll box rather than being squeezed into a size nobody chose. The package carries the extension and nothing else, because a notebook loads an extension in its own context and a second copy of the charting library there would be a different Figure from the cell's. MatPlotLibNet.Notebooks stands still at the version it reached — the runtime under Polyglot Notebooks has ended — and notebook work belongs in Verso now.

1.17.1 was a patch on top of it. A clicked data point now reaches your own code: the WPF, Avalonia and Uno controls and the SignalR route all hand it over with the series it belongs to, its value and where it was, so you can open a detail panel or select the matching row beside the chart. The control room gained a service-topology panel, GroupedBar draws several bars per category in one call, and DensityScatter colours a scatter by how crowded each part of it is. Three accessible colour sequences arrived — petroff6, petroff8 and petroff10 — whose colours stay apart for colour-blind readers and in grayscale. All fourteen packages now carry an icon and release notes, and the documentation has a page that translates matplotlib into C#, call by call.

1.17 draws text in any script. Arabic and Hebrew labels draw correctly with the bundled font: the letters join, the words read right to left, and a number or a Latin word inside them stays where a reader expects it. The Unicode bidi algorithm is implemented in full and checked against Unicode's own 861,948 test cases; HarfBuzz shapes each run. SkiaFonts.Register(path) adds a font file for Devanagari, Thai, Chinese and other scripts, and the MCP server reads font files from MATPLOTLIBNET_FONTS. Latin text is now kerned, so text widths changed by up to 2 px per letter pair. See International Text.

1.16 added a data table beside every chart, for readers who cannot see the picture. figure.ToDataTables() returns the figure's data as tables with typed columns. Each table can write itself out as HTML, Markdown or CSV, and every host serves it. The same release fixed the streaming series, so a snapshot can no longer show a point or a candle that never existed. See Accessibility.

1.15, the release before it, made the library usable by AI agents. It added MatPlotLibNet.Mcp, a Model Context Protocol server that a host starts over stdio, so Claude or VS Code can render any of these chart types from a JSON spec and look at the result. It is listed in the official MCP Registry as io.github.xkqg/matplotlibnet. See MCP Server.

1.14, before that, was control-room work. It added the control-room pack itself, plus the fixes and extensions the pack needed. A secondary Y axis is fully supported, streaming series render in SVG, and 3-D axis titles no longer overlap their own labels. Every tile in a row uses the same layout. A hidden axis reserves no room, so a row of tiles is as wide as it looks. · NuGet · Changelog · License: MIT

dotnet add package MatPlotLibNet
Plt.Create()
   .AddSubPlot(1, 1, 1, ax => ax.Plot(x, y, s => s.Label = "signal"))
   .SaveSvg("chart.svg");

Start here

Page For
Getting Started install, first chart, output formats, subplots
Fluent Cheatsheet one page: Plt · FigureBuilder · AxesBuilder
Chart Types all 83 series with code — including the control room
Package Map which of the 14 NuGet + 3 npm packages you need
Styling · MatplotlibThemes themes, colours, fonts, layout
Advanced animation, geo projections, MathText, DI
Streaming live data, O(1) ring buffers, indicators
Bidirectional SignalR push charts to Blazor / Angular / React / Vue
Interactive Controls · Keyboard Shortcuts pan, zoom, brush-select, hotkeys
Notebooks Polyglot / Jupyter
Accessibility The data table beside the chart, ARIA, contrast, screen readers
Benchmarks render and export timings
Roadmap · Contributing where it is going, how to help

Also: Playground · From matplotlib to C# · Cookbook · API Reference.

Who it is for

You are… You get…
Blazor / ASP.NET Core <MplChart> and <MplLiveChart>, SignalR push, a REST endpoint — wired with standard DI
WPF / MAUI / Avalonia / Uno native controls (SkiaSharp or Microsoft.Maui.Graphics), pan / zoom / brush-select, no WebView
Data scientist inline SVG in notebooks, plotting straight from Microsoft.Data.Analysis.DataFrame
Trading / finance candlestick, OHLC, 58 indicators, drawing tools, backtest panels, RRG
Ops / control room Plt.OpsDashboard() — KPI tiles, state timelines, a service-topology panel, one shared trend window
Backend / headless render SVG, PNG, PDF or GIF server-side with zero UI dependencies
Angular / React / Vue TypeScript clients on the same hub and the same chart definitions

What it is not

MatPlotLibNet is not a JavaScript wrapper, not a WebView host and not a hosted service. Charts are built and rendered in .NET. Only a picture or a chart definition leaves the process.

Quality bar

Every class passes a strict per-class coverage gate of at least 90 % line and branch coverage. That is currently 706 classes at 99.6 % line and 97.5 % branch coverage, across 11,757 tests. Rendering is verified against matplotlib pixel-fidelity fixtures.

If you have a question or something is missing, open a Discussion or an Issue. Releases follow what people actually need.

Clone this wiki locally