ADR-006: Matplotlib + Agg Backend for Visualization
September 5, 2026 ยท View on GitHub
Status
Accepted
Context
The server runs on FastMCP Cloud (AWS Lambda). Lambda provides no display server, no GPU, and no GUI toolkit. Visualization tools must produce self-contained output that an MCP client can render without a live connection back to the server.
Alternatives considered:
- Plotly / Altair: produce interactive HTML/JavaScript. Requires a browser runtime on the client; MCP tools return structured data, not HTML pages. Not suitable.
- Seaborn: a Matplotlib wrapper. Adds a dependency without adding capability relevant here.
- Matplotlib + Agg: Agg (Anti-Grain Geometry) is a pure-software raster renderer. No display server required. Renders to an in-memory PNG buffer; output is base64-encoded and returned as a string, a self-contained artifact any MCP client can handle.
Decision
Use Matplotlib with the Agg backend, explicitly set before any other import:
# visualization.py
import matplotlib
matplotlib.use("Agg") # Must precede pyplot import; no display server on Lambda
import matplotlib.pyplot as plt
Charts are rendered to a BytesIO buffer and returned as base64-encoded PNG strings. The client
is responsible for decoding and displaying; the server has no display dependency.
Consequences
Gained:
- Runs headless on Lambda and any serverless runtime with no configuration
- Output is a plain string; no streaming, no file I/O, no client-side JavaScript required
- Matplotlib is the de facto standard for scientific Python visualization; well-documented, stable API, no additional dependencies beyond what the project already uses
Accepted:
- Static PNG only; no interactivity (zoom, hover, pan)
- Agg must be set before
pyplotis imported; order-sensitive import is a known footgun, mitigated by the explicit comment invisualization.py