MCP server for chart generation and data export - PNG/JPG charts, CSV/XLSX exports
MCP server for chart generation and data export — PNG/JPG charts, CSV/XLSX files.
A pure rendering engine that generates charts and exports data files. No authentication required, no external API calls. Designed to work alongside other DotZero MCP servers: fetch data with existing tools, then visualize or export with this package.
Architecture: User → AI Agent → 1. Fetch data (existing MCP tools) → 2. Render/Export (export-mcp)
``bash`
npx @dotzero.ai/setup
Or manually:
`bash`
claude mcp add dotzero-export --command "npx" --args "@dotzero.ai/export-mcp"
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| chart_bar | Bar chart (vertical/horizontal/stacked) | title, labels[], datasets[], options? |chart_line
| | Line chart (multi-series, area fill) | title, labels[], datasets[], options? |chart_pie
| | Pie or doughnut chart | title, labels[], values[], chart_type? |chart_scatter
| | Scatter plot | title, datasets[{data: [{x,y}]}] |chart_gauge
| | Gauge/dial for single KPI | value, label?, min?, max?, thresholds? |
| Tool | Description | Data Source |
|------|-------------|-------------|
| chart_oee_breakdown | OEE A/Q/P breakdown chart | oee_device, oee_devices, oee_line, oee_factory |chart_control
| | SPC control chart (UCL/CL/LCL) | spc_measure_history_* + spc_statistics_capability |chart_timeline
| | Device state timeline | equip_machine_status_history |chart_multi
| | Multi-chart dashboard (max 9) | Multiple chart configs |
| Tool | Description | Key Parameters |
|------|-------------|----------------|
| export_csv | Export to CSV file | headers[], rows[][], filename? |export_xlsx
| | Export to Excel XLSX (multi-sheet) | sheets[{name, headers, rows}], filename? |
| Tool | Description |
|------|-------------|
| chart_from_json | Auto-detect JSON data shape and pick best chart type |export_table_from_json
| | Auto-convert JSON to CSV/XLSX (extracts headers from keys) |
All chart tools share these base parameters:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| output_path | string | auto | Custom output file path |width
| | int | 800 | Image width in pixels (200-3000) |height
| | int | 500 | Image height in pixels (200-3000) |format
| | enum | "png" | "png" or "jpg" |
All export tools share:
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| output_path | string | auto | Custom output file path |filename
| | string | auto | Output filename (without extension) |
Bar, line, and scatter charts accept an options object:
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| stacked | boolean | false | Enable stacking |horizontal
| | boolean | false | Horizontal orientation (bar charts only) |show_legend
| | boolean | true | Show legend |show_grid
| | boolean | true | Show grid lines |x_label
| | string | - | X-axis label |y_label
| | string | - | Y-axis label |min_y
| | number | - | Y-axis minimum |max_y
| | number | - | Y-axis maximum |
``
chart_bar(
title: "Production by Line",
labels: ["Line A", "Line B", "Line C"],
datasets: [
{ label: "Good", data: [1200, 980, 1150] },
{ label: "Defect", data: [23, 15, 31] }
],
options: { stacked: true, y_label: "Quantity" }
)
``
chart_line(
title: "Weekly Production Trend",
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
datasets: [
{ label: "Output", data: [450, 520, 480, 510, 530], fill: true }
],
options: { y_label: "Units" }
)
``
chart_pie(
title: "Defect Distribution",
labels: ["Scratch", "Dent", "Crack", "Other"],
values: [45, 28, 15, 12],
chart_type: "doughnut"
)
``
chart_scatter(
title: "Cycle Time vs Output",
datasets: [{
label: "Devices",
data: [
{ x: 30, y: 120 },
{ x: 45, y: 95 },
{ x: 25, y: 140 }
]
}],
options: { x_label: "Cycle Time (s)", y_label: "Output" }
)
``
chart_gauge(
value: 85.2,
label: "OEE",
min: 0,
max: 100,
thresholds: [
{ value: 60, color: "#F44336" },
{ value: 80, color: "#FFC107" },
{ value: 100, color: "#4CAF50" }
]
)
Single device:
``
chart_oee_breakdown(
title: "CNC-001 OEE",
availability: 92.5,
quality: 98.1,
performance: 87.3
)
Multi-device comparison:
``
chart_oee_breakdown(
title: "Line A OEE Comparison",
availability: 0, quality: 0, performance: 0,
devices: [
{ name: "CNC-001", availability: 92.5, quality: 98.1, performance: 87.3 },
{ name: "CNC-002", availability: 88.0, quality: 96.5, performance: 91.2 },
{ name: "CNC-003", availability: 95.1, quality: 97.8, performance: 84.6 }
]
)
``
chart_control(
title: "Diameter Control Chart",
values: [10.02, 10.05, 9.98, 10.01, 10.12, 9.95, 10.03, 10.08],
labels: ["S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8"],
ucl: 10.10,
cl: 10.00,
lcl: 9.90,
usl: 10.15,
lsl: 9.85
)
Points exceeding UCL/LCL are highlighted in red. USL/LSL specification limits are shown as orange dashed lines.
``
chart_timeline(
title: "CNC-001 State History",
device_name: "CNC-001",
segments: [
{ start: "2026-02-08T08:00:00Z", end: "2026-02-08T10:30:00Z", state: "running" },
{ start: "2026-02-08T10:30:00Z", end: "2026-02-08T11:00:00Z", state: "idle" },
{ start: "2026-02-08T11:00:00Z", end: "2026-02-08T11:45:00Z", state: "down" },
{ start: "2026-02-08T11:45:00Z", end: "2026-02-08T17:00:00Z", state: "running" }
]
)
Default state colors: running=green, idle=yellow, down=red, off=grey. Override with the color field per segment.
``
chart_multi(
title: "Production Dashboard",
layout: "grid",
charts: [
{
type: "bar",
title: "Output by Line",
labels: ["Line A", "Line B"],
datasets: [{ label: "Output", data: [1200, 980] }]
},
{
type: "gauge",
title: "OEE",
value: 85.2,
label: "OEE"
},
{
type: "pie",
title: "Defects",
labels: ["Scratch", "Dent"],
values: [65, 35]
}
]
)
Layout options: grid (auto rows/cols), vertical (1 column), horizontal (1 row). Max 9 sub-charts.
``
export_csv(
headers: ["Work Order", "Product", "Qty", "Status"],
rows: [
["WO-001", "Widget A", 100, "Completed"],
["WO-002", "Widget B", 250, "In Progress"],
["WO-003", "Widget A", 75, "Not Started"]
],
filename: "work-orders"
)
``
export_xlsx(
sheets: [
{
name: "Work Orders",
headers: ["ID", "Product", "Qty", "Status"],
rows: [
["WO-001", "Widget A", 100, "Completed"],
["WO-002", "Widget B", 250, "In Progress"]
]
},
{
name: "Summary",
headers: ["Metric", "Value"],
rows: [
["Total Orders", 2],
["Total Qty", 350]
]
}
],
filename: "production-report"
)
Headers are bold, column widths are auto-fit.
``
chart_from_json(
title: "Auto Chart",
data:
chart_type: "auto"
)
Auto-detection rules:
- Objects with availability/quality/performance fields → OEE breakdown chartchart_type
- Array of OEE objects → Multi-device OEE comparison
- Single number → Gauge chart
- Array of objects with name + numeric fields → Bar chart
- Force to override: "bar", "line", "pie", "gauge", "oee"
``
export_table_from_json(
data:
format: "xlsx",
filename: "export",
sheet_name: "Data"
)
Accepts arrays of objects, single objects, or paginated responses ({ data: [...] }). Automatically extracts column headers from object keys.
``
Step 1: oee_device(device_uuid: "...", start_time: "...", end_time: "...", response_format: "json")
Step 2: chart_oee_breakdown(title: "CNC-001 OEE", availability: 92.5, quality: 98.1, performance: 87.3)
Or use the smart tool:
``
Step 1: oee_devices(line_uuid: "...", response_format: "json")
Step 2: chart_from_json(title: "Line A OEE", data:
``
Step 1: spc_measure_history_manufacture(config_uuid: "...", response_format: "json")
Step 2: spc_statistics_capability(config_uuid: "...", response_format: "json")
Step 3: chart_control(
title: "Diameter Control",
values: [extracted from step 1],
ucl: [from step 2],
cl: [from step 2],
lcl: [from step 2]
)
``
Step 1: workorder_list(status: 3, response_format: "json")
Step 2: export_table_from_json(data:
Or with custom formatting:
``
Step 1: production_summary(response_format: "json")
Step 2: export_xlsx(
sheets: [
{ name: "Summary", headers: [...], rows: [...] },
{ name: "Details", headers: [...], rows: [...] }
],
filename: "production-report"
)
``
Step 1: worker_efficiency_ranking(response_format: "json")
Step 2: chart_bar(
title: "Worker Efficiency",
labels: [worker names],
datasets: [{ label: "Efficiency %", data: [values] }],
options: { horizontal: true, y_label: "Worker" }
)
``
Step 1: equip_state_counts_factory(factory_uuid: "...", response_format: "json")
Step 2: chart_pie(
title: "Device States",
labels: ["Running", "Idle", "Down", "Off"],
values: [running_count, idle_count, down_count, off_count],
colors: ["#4CAF50", "#FFC107", "#F44336", "#9E9E9E"]
)
``
Step 1: Fetch OEE, production summary, and defect data
Step 2: chart_multi(
title: "Daily Dashboard",
layout: "grid",
charts: [
{ type: "gauge", title: "OEE", value: 85.2, label: "OEE" },
{ type: "bar", title: "Output", labels: [...], datasets: [...] },
{ type: "pie", title: "Defects", labels: [...], values: [...] },
{ type: "line", title: "Trend", labels: [...], datasets: [...] }
]
)
- Default path: .dotzero/exports/.dotzero/
- is in .gitignore — files won't be committedoutput_path
- Override with parameter on any tool
Chart tools return:
`json`
{
"content": [
{ "type": "text", "text": "Chart saved to: .dotzero/exports/chart-bar-2026-02-08T14-30-00.png (800x500)" },
{ "type": "image", "data": "
]
}
Export tools return:
`json`
{
"content": [
{ "type": "text", "text": "Exported 42 rows to: .dotzero/exports/export-2026-02-08.csv\n\nPreview (first 5 rows):\n| Col1 | Col2 |\n|---|---|\n| ... | ... |" }
]
}
| Name | Color | Hex | Usage |
|------|-------|-----|-------|
| availability | Green | #4CAF50 | OEE Availability |#2196F3
| quality | Blue | | OEE Quality |#FF9800
| performance | Orange | | OEE Performance |#9C27B0
| oee | Purple | | Combined OEE |#4CAF50
| good/running | Green | | Good parts, running state |#F44336
| defect/down | Red | | Defects, down state |#FFC107
| idle | Yellow | | Idle state |#9E9E9E
| off | Grey | | Off state |
| Library | Purpose |
|---------|---------|
| chartjs-node-canvas + chart.js v4 | Server-side chart rendering |@napi-rs/canvas
| | Native canvas backend (no cairo/pango) |chartjs-plugin-annotation
| | UCL/CL/LCL horizontal lines |exceljs
| | Excel XLSX generation |zod
| | Input schema validation |
`bash``
cd packages/export-mcp
pnpm install
pnpm build
MIT