@dotzero.ai/export-mcp 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +474 -0
  2. package/dist/chart-engine.d.ts +29 -0
  3. package/dist/chart-engine.js +1 -0
  4. package/dist/colors.d.ts +21 -0
  5. package/dist/colors.js +1 -0
  6. package/dist/export-engine.d.ts +17 -0
  7. package/dist/export-engine.js +1 -0
  8. package/dist/file-output.d.ts +10 -0
  9. package/dist/file-output.js +1 -0
  10. package/dist/index.d.ts +8 -0
  11. package/dist/index.js +2 -0
  12. package/dist/schemas.d.ts +126 -0
  13. package/dist/schemas.js +1 -0
  14. package/dist/tool-registry.d.ts +10 -0
  15. package/dist/tool-registry.js +1 -0
  16. package/dist/tools/charts/bar.d.ts +214 -0
  17. package/dist/tools/charts/bar.js +1 -0
  18. package/dist/tools/charts/control-chart.d.ts +109 -0
  19. package/dist/tools/charts/control-chart.js +1 -0
  20. package/dist/tools/charts/gauge.d.ts +120 -0
  21. package/dist/tools/charts/gauge.js +1 -0
  22. package/dist/tools/charts/index.d.ts +9 -0
  23. package/dist/tools/charts/index.js +1 -0
  24. package/dist/tools/charts/line.d.ts +226 -0
  25. package/dist/tools/charts/line.js +1 -0
  26. package/dist/tools/charts/multi.d.ts +466 -0
  27. package/dist/tools/charts/multi.js +1 -0
  28. package/dist/tools/charts/oee-breakdown.d.ts +156 -0
  29. package/dist/tools/charts/oee-breakdown.js +1 -0
  30. package/dist/tools/charts/pie.d.ts +90 -0
  31. package/dist/tools/charts/pie.js +1 -0
  32. package/dist/tools/charts/scatter.d.ts +250 -0
  33. package/dist/tools/charts/scatter.js +1 -0
  34. package/dist/tools/charts/timeline.d.ts +128 -0
  35. package/dist/tools/charts/timeline.js +1 -0
  36. package/dist/tools/exports/csv.d.ts +51 -0
  37. package/dist/tools/exports/csv.js +1 -0
  38. package/dist/tools/exports/index.d.ts +2 -0
  39. package/dist/tools/exports/index.js +1 -0
  40. package/dist/tools/exports/xlsx.d.ts +85 -0
  41. package/dist/tools/exports/xlsx.js +1 -0
  42. package/dist/tools/smart/chart-from-json.d.ts +84 -0
  43. package/dist/tools/smart/chart-from-json.js +1 -0
  44. package/dist/tools/smart/index.d.ts +2 -0
  45. package/dist/tools/smart/index.js +1 -0
  46. package/dist/tools/smart/table-from-json.d.ts +63 -0
  47. package/dist/tools/smart/table-from-json.js +1 -0
  48. package/dist/types.d.ts +75 -0
  49. package/dist/types.js +1 -0
  50. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,474 @@
1
+ # @dotzero.ai/export-mcp
2
+
3
+ MCP server for chart generation and data export — PNG/JPG charts, CSV/XLSX files.
4
+
5
+ ## Overview
6
+
7
+ 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.
8
+
9
+ **Architecture**: `User → AI Agent → 1. Fetch data (existing MCP tools) → 2. Render/Export (export-mcp)`
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npx @dotzero.ai/setup
15
+ ```
16
+
17
+ Or manually:
18
+
19
+ ```bash
20
+ claude mcp add dotzero-export --command "npx" --args "@dotzero.ai/export-mcp"
21
+ ```
22
+
23
+ ## Tools (14)
24
+
25
+ ### Generic Charts (5)
26
+
27
+ | Tool | Description | Key Parameters |
28
+ |------|-------------|----------------|
29
+ | `chart_bar` | Bar chart (vertical/horizontal/stacked) | `title`, `labels[]`, `datasets[]`, `options?` |
30
+ | `chart_line` | Line chart (multi-series, area fill) | `title`, `labels[]`, `datasets[]`, `options?` |
31
+ | `chart_pie` | Pie or doughnut chart | `title`, `labels[]`, `values[]`, `chart_type?` |
32
+ | `chart_scatter` | Scatter plot | `title`, `datasets[{data: [{x,y}]}]` |
33
+ | `chart_gauge` | Gauge/dial for single KPI | `value`, `label?`, `min?`, `max?`, `thresholds?` |
34
+
35
+ ### DotZero-Specific Charts (4)
36
+
37
+ | Tool | Description | Data Source |
38
+ |------|-------------|-------------|
39
+ | `chart_oee_breakdown` | OEE A/Q/P breakdown chart | `oee_device`, `oee_devices`, `oee_line`, `oee_factory` |
40
+ | `chart_control` | SPC control chart (UCL/CL/LCL) | `spc_measure_history_*` + `spc_statistics_capability` |
41
+ | `chart_timeline` | Device state timeline | `equip_machine_status_history` |
42
+ | `chart_multi` | Multi-chart dashboard (max 9) | Multiple chart configs |
43
+
44
+ ### Export (2)
45
+
46
+ | Tool | Description | Key Parameters |
47
+ |------|-------------|----------------|
48
+ | `export_csv` | Export to CSV file | `headers[]`, `rows[][]`, `filename?` |
49
+ | `export_xlsx` | Export to Excel XLSX (multi-sheet) | `sheets[{name, headers, rows}]`, `filename?` |
50
+
51
+ ### Smart Tools (2)
52
+
53
+ | Tool | Description |
54
+ |------|-------------|
55
+ | `chart_from_json` | Auto-detect JSON data shape and pick best chart type |
56
+ | `export_table_from_json` | Auto-convert JSON to CSV/XLSX (extracts headers from keys) |
57
+
58
+ ## Shared Parameters
59
+
60
+ All chart tools share these base parameters:
61
+
62
+ | Parameter | Type | Default | Description |
63
+ |-----------|------|---------|-------------|
64
+ | `output_path` | string | auto | Custom output file path |
65
+ | `width` | int | 800 | Image width in pixels (200-3000) |
66
+ | `height` | int | 500 | Image height in pixels (200-3000) |
67
+ | `format` | enum | `"png"` | `"png"` or `"jpg"` |
68
+
69
+ All export tools share:
70
+
71
+ | Parameter | Type | Default | Description |
72
+ |-----------|------|---------|-------------|
73
+ | `output_path` | string | auto | Custom output file path |
74
+ | `filename` | string | auto | Output filename (without extension) |
75
+
76
+ ## Chart Options
77
+
78
+ Bar, line, and scatter charts accept an `options` object:
79
+
80
+ | Option | Type | Default | Description |
81
+ |--------|------|---------|-------------|
82
+ | `stacked` | boolean | false | Enable stacking |
83
+ | `horizontal` | boolean | false | Horizontal orientation (bar charts only) |
84
+ | `show_legend` | boolean | true | Show legend |
85
+ | `show_grid` | boolean | true | Show grid lines |
86
+ | `x_label` | string | - | X-axis label |
87
+ | `y_label` | string | - | Y-axis label |
88
+ | `min_y` | number | - | Y-axis minimum |
89
+ | `max_y` | number | - | Y-axis maximum |
90
+
91
+ ## Tool Reference
92
+
93
+ ### chart_bar
94
+
95
+ ```
96
+ chart_bar(
97
+ title: "Production by Line",
98
+ labels: ["Line A", "Line B", "Line C"],
99
+ datasets: [
100
+ { label: "Good", data: [1200, 980, 1150] },
101
+ { label: "Defect", data: [23, 15, 31] }
102
+ ],
103
+ options: { stacked: true, y_label: "Quantity" }
104
+ )
105
+ ```
106
+
107
+ ### chart_line
108
+
109
+ ```
110
+ chart_line(
111
+ title: "Weekly Production Trend",
112
+ labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
113
+ datasets: [
114
+ { label: "Output", data: [450, 520, 480, 510, 530], fill: true }
115
+ ],
116
+ options: { y_label: "Units" }
117
+ )
118
+ ```
119
+
120
+ ### chart_pie
121
+
122
+ ```
123
+ chart_pie(
124
+ title: "Defect Distribution",
125
+ labels: ["Scratch", "Dent", "Crack", "Other"],
126
+ values: [45, 28, 15, 12],
127
+ chart_type: "doughnut"
128
+ )
129
+ ```
130
+
131
+ ### chart_scatter
132
+
133
+ ```
134
+ chart_scatter(
135
+ title: "Cycle Time vs Output",
136
+ datasets: [{
137
+ label: "Devices",
138
+ data: [
139
+ { x: 30, y: 120 },
140
+ { x: 45, y: 95 },
141
+ { x: 25, y: 140 }
142
+ ]
143
+ }],
144
+ options: { x_label: "Cycle Time (s)", y_label: "Output" }
145
+ )
146
+ ```
147
+
148
+ ### chart_gauge
149
+
150
+ ```
151
+ chart_gauge(
152
+ value: 85.2,
153
+ label: "OEE",
154
+ min: 0,
155
+ max: 100,
156
+ thresholds: [
157
+ { value: 60, color: "#F44336" },
158
+ { value: 80, color: "#FFC107" },
159
+ { value: 100, color: "#4CAF50" }
160
+ ]
161
+ )
162
+ ```
163
+
164
+ ### chart_oee_breakdown
165
+
166
+ Single device:
167
+ ```
168
+ chart_oee_breakdown(
169
+ title: "CNC-001 OEE",
170
+ availability: 92.5,
171
+ quality: 98.1,
172
+ performance: 87.3
173
+ )
174
+ ```
175
+
176
+ Multi-device comparison:
177
+ ```
178
+ chart_oee_breakdown(
179
+ title: "Line A OEE Comparison",
180
+ availability: 0, quality: 0, performance: 0,
181
+ devices: [
182
+ { name: "CNC-001", availability: 92.5, quality: 98.1, performance: 87.3 },
183
+ { name: "CNC-002", availability: 88.0, quality: 96.5, performance: 91.2 },
184
+ { name: "CNC-003", availability: 95.1, quality: 97.8, performance: 84.6 }
185
+ ]
186
+ )
187
+ ```
188
+
189
+ ### chart_control
190
+
191
+ ```
192
+ chart_control(
193
+ title: "Diameter Control Chart",
194
+ values: [10.02, 10.05, 9.98, 10.01, 10.12, 9.95, 10.03, 10.08],
195
+ labels: ["S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8"],
196
+ ucl: 10.10,
197
+ cl: 10.00,
198
+ lcl: 9.90,
199
+ usl: 10.15,
200
+ lsl: 9.85
201
+ )
202
+ ```
203
+
204
+ Points exceeding UCL/LCL are highlighted in red. USL/LSL specification limits are shown as orange dashed lines.
205
+
206
+ ### chart_timeline
207
+
208
+ ```
209
+ chart_timeline(
210
+ title: "CNC-001 State History",
211
+ device_name: "CNC-001",
212
+ segments: [
213
+ { start: "2026-02-08T08:00:00Z", end: "2026-02-08T10:30:00Z", state: "running" },
214
+ { start: "2026-02-08T10:30:00Z", end: "2026-02-08T11:00:00Z", state: "idle" },
215
+ { start: "2026-02-08T11:00:00Z", end: "2026-02-08T11:45:00Z", state: "down" },
216
+ { start: "2026-02-08T11:45:00Z", end: "2026-02-08T17:00:00Z", state: "running" }
217
+ ]
218
+ )
219
+ ```
220
+
221
+ Default state colors: running=green, idle=yellow, down=red, off=grey. Override with the `color` field per segment.
222
+
223
+ ### chart_multi
224
+
225
+ ```
226
+ chart_multi(
227
+ title: "Production Dashboard",
228
+ layout: "grid",
229
+ charts: [
230
+ {
231
+ type: "bar",
232
+ title: "Output by Line",
233
+ labels: ["Line A", "Line B"],
234
+ datasets: [{ label: "Output", data: [1200, 980] }]
235
+ },
236
+ {
237
+ type: "gauge",
238
+ title: "OEE",
239
+ value: 85.2,
240
+ label: "OEE"
241
+ },
242
+ {
243
+ type: "pie",
244
+ title: "Defects",
245
+ labels: ["Scratch", "Dent"],
246
+ values: [65, 35]
247
+ }
248
+ ]
249
+ )
250
+ ```
251
+
252
+ Layout options: `grid` (auto rows/cols), `vertical` (1 column), `horizontal` (1 row). Max 9 sub-charts.
253
+
254
+ ### export_csv
255
+
256
+ ```
257
+ export_csv(
258
+ headers: ["Work Order", "Product", "Qty", "Status"],
259
+ rows: [
260
+ ["WO-001", "Widget A", 100, "Completed"],
261
+ ["WO-002", "Widget B", 250, "In Progress"],
262
+ ["WO-003", "Widget A", 75, "Not Started"]
263
+ ],
264
+ filename: "work-orders"
265
+ )
266
+ ```
267
+
268
+ ### export_xlsx
269
+
270
+ ```
271
+ export_xlsx(
272
+ sheets: [
273
+ {
274
+ name: "Work Orders",
275
+ headers: ["ID", "Product", "Qty", "Status"],
276
+ rows: [
277
+ ["WO-001", "Widget A", 100, "Completed"],
278
+ ["WO-002", "Widget B", 250, "In Progress"]
279
+ ]
280
+ },
281
+ {
282
+ name: "Summary",
283
+ headers: ["Metric", "Value"],
284
+ rows: [
285
+ ["Total Orders", 2],
286
+ ["Total Qty", 350]
287
+ ]
288
+ }
289
+ ],
290
+ filename: "production-report"
291
+ )
292
+ ```
293
+
294
+ Headers are bold, column widths are auto-fit.
295
+
296
+ ### chart_from_json
297
+
298
+ ```
299
+ chart_from_json(
300
+ title: "Auto Chart",
301
+ data: <raw JSON from any DotZero tool>,
302
+ chart_type: "auto"
303
+ )
304
+ ```
305
+
306
+ Auto-detection rules:
307
+ - Objects with `availability`/`quality`/`performance` fields → OEE breakdown chart
308
+ - Array of OEE objects → Multi-device OEE comparison
309
+ - Single number → Gauge chart
310
+ - Array of objects with name + numeric fields → Bar chart
311
+ - Force `chart_type` to override: `"bar"`, `"line"`, `"pie"`, `"gauge"`, `"oee"`
312
+
313
+ ### export_table_from_json
314
+
315
+ ```
316
+ export_table_from_json(
317
+ data: <raw JSON from any DotZero tool>,
318
+ format: "xlsx",
319
+ filename: "export",
320
+ sheet_name: "Data"
321
+ )
322
+ ```
323
+
324
+ Accepts arrays of objects, single objects, or paginated responses (`{ data: [...] }`). Automatically extracts column headers from object keys.
325
+
326
+ ## Workflow Examples
327
+
328
+ ### 1. OEE Breakdown Chart (OEE 分解圖)
329
+
330
+ ```
331
+ Step 1: oee_device(device_uuid: "...", start_time: "...", end_time: "...", response_format: "json")
332
+ Step 2: chart_oee_breakdown(title: "CNC-001 OEE", availability: 92.5, quality: 98.1, performance: 87.3)
333
+ ```
334
+
335
+ Or use the smart tool:
336
+ ```
337
+ Step 1: oee_devices(line_uuid: "...", response_format: "json")
338
+ Step 2: chart_from_json(title: "Line A OEE", data: <result from step 1>)
339
+ ```
340
+
341
+ ### 2. SPC Control Chart (SPC 管制圖)
342
+
343
+ ```
344
+ Step 1: spc_measure_history_manufacture(config_uuid: "...", response_format: "json")
345
+ Step 2: spc_statistics_capability(config_uuid: "...", response_format: "json")
346
+ Step 3: chart_control(
347
+ title: "Diameter Control",
348
+ values: [extracted from step 1],
349
+ ucl: [from step 2],
350
+ cl: [from step 2],
351
+ lcl: [from step 2]
352
+ )
353
+ ```
354
+
355
+ ### 3. Production Report Excel Export (生產報表匯出)
356
+
357
+ ```
358
+ Step 1: workorder_list(status: 3, response_format: "json")
359
+ Step 2: export_table_from_json(data: <result>, format: "xlsx", filename: "completed-orders")
360
+ ```
361
+
362
+ Or with custom formatting:
363
+ ```
364
+ Step 1: production_summary(response_format: "json")
365
+ Step 2: export_xlsx(
366
+ sheets: [
367
+ { name: "Summary", headers: [...], rows: [...] },
368
+ { name: "Details", headers: [...], rows: [...] }
369
+ ],
370
+ filename: "production-report"
371
+ )
372
+ ```
373
+
374
+ ### 4. Worker Efficiency Ranking (作業員效率排名)
375
+
376
+ ```
377
+ Step 1: worker_efficiency_ranking(response_format: "json")
378
+ Step 2: chart_bar(
379
+ title: "Worker Efficiency",
380
+ labels: [worker names],
381
+ datasets: [{ label: "Efficiency %", data: [values] }],
382
+ options: { horizontal: true, y_label: "Worker" }
383
+ )
384
+ ```
385
+
386
+ ### 5. Device State Distribution (設備狀態分佈)
387
+
388
+ ```
389
+ Step 1: equip_state_counts_factory(factory_uuid: "...", response_format: "json")
390
+ Step 2: chart_pie(
391
+ title: "Device States",
392
+ labels: ["Running", "Idle", "Down", "Off"],
393
+ values: [running_count, idle_count, down_count, off_count],
394
+ colors: ["#4CAF50", "#FFC107", "#F44336", "#9E9E9E"]
395
+ )
396
+ ```
397
+
398
+ ### 6. Multi-Chart Dashboard (多圖表儀表板)
399
+
400
+ ```
401
+ Step 1: Fetch OEE, production summary, and defect data
402
+ Step 2: chart_multi(
403
+ title: "Daily Dashboard",
404
+ layout: "grid",
405
+ charts: [
406
+ { type: "gauge", title: "OEE", value: 85.2, label: "OEE" },
407
+ { type: "bar", title: "Output", labels: [...], datasets: [...] },
408
+ { type: "pie", title: "Defects", labels: [...], values: [...] },
409
+ { type: "line", title: "Trend", labels: [...], datasets: [...] }
410
+ ]
411
+ )
412
+ ```
413
+
414
+ ## File Output
415
+
416
+ - Default path: `.dotzero/exports/<type>-<name>-<timestamp>.<ext>`
417
+ - `.dotzero/` is in `.gitignore` — files won't be committed
418
+ - Override with `output_path` parameter on any tool
419
+
420
+ ## Output Format
421
+
422
+ Chart tools return:
423
+ ```json
424
+ {
425
+ "content": [
426
+ { "type": "text", "text": "Chart saved to: .dotzero/exports/chart-bar-2026-02-08T14-30-00.png (800x500)" },
427
+ { "type": "image", "data": "<base64>", "mimeType": "image/png" }
428
+ ]
429
+ }
430
+ ```
431
+
432
+ Export tools return:
433
+ ```json
434
+ {
435
+ "content": [
436
+ { "type": "text", "text": "Exported 42 rows to: .dotzero/exports/export-2026-02-08.csv\n\nPreview (first 5 rows):\n| Col1 | Col2 |\n|---|---|\n| ... | ... |" }
437
+ ]
438
+ }
439
+ ```
440
+
441
+ ## DotZero Color Palette
442
+
443
+ | Name | Color | Hex | Usage |
444
+ |------|-------|-----|-------|
445
+ | availability | Green | `#4CAF50` | OEE Availability |
446
+ | quality | Blue | `#2196F3` | OEE Quality |
447
+ | performance | Orange | `#FF9800` | OEE Performance |
448
+ | oee | Purple | `#9C27B0` | Combined OEE |
449
+ | good/running | Green | `#4CAF50` | Good parts, running state |
450
+ | defect/down | Red | `#F44336` | Defects, down state |
451
+ | idle | Yellow | `#FFC107` | Idle state |
452
+ | off | Grey | `#9E9E9E` | Off state |
453
+
454
+ ## Dependencies
455
+
456
+ | Library | Purpose |
457
+ |---------|---------|
458
+ | `chartjs-node-canvas` + `chart.js` v4 | Server-side chart rendering |
459
+ | `@napi-rs/canvas` | Native canvas backend (no cairo/pango) |
460
+ | `chartjs-plugin-annotation` | UCL/CL/LCL horizontal lines |
461
+ | `exceljs` | Excel XLSX generation |
462
+ | `zod` | Input schema validation |
463
+
464
+ ## Build
465
+
466
+ ```bash
467
+ cd packages/export-mcp
468
+ pnpm install
469
+ pnpm build
470
+ ```
471
+
472
+ ## License
473
+
474
+ MIT
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Chart rendering engine using chartjs-node-canvas.
3
+ * Manages canvas instances cached by dimension.
4
+ */
5
+ import type { ChartConfiguration } from "chart.js";
6
+ import type { ChartResult } from "./types.js";
7
+ export interface RenderOptions {
8
+ width: number;
9
+ height: number;
10
+ format: "png" | "jpg";
11
+ outputPath?: string;
12
+ title: string;
13
+ }
14
+ /** Render a Chart.js configuration to an image file */
15
+ export declare function renderChart(config: ChartConfiguration, opts: RenderOptions): Promise<ChartResult>;
16
+ /** Build MCP content blocks from a ChartResult */
17
+ export declare function chartResultToContent(result: ChartResult): {
18
+ content: ({
19
+ type: "text";
20
+ text: string;
21
+ data?: undefined;
22
+ mimeType?: undefined;
23
+ } | {
24
+ type: "image";
25
+ data: string;
26
+ mimeType: "image/png" | "image/jpeg";
27
+ text?: undefined;
28
+ })[];
29
+ };
@@ -0,0 +1 @@
1
+ import{ChartJSNodeCanvas}from"chartjs-node-canvas";import{resolveOutputPath,writeBinary}from"./file-output.js";const canvasCache=new Map;function getCanvas(t,e){const a=`${t}x${e}`;let n=canvasCache.get(a);return n||(n=new ChartJSNodeCanvas({width:t,height:e,backgroundColour:"white",plugins:{modern:["chartjs-plugin-annotation"]}}),canvasCache.set(a,n)),n}export async function renderChart(t,e){const a=getCanvas(e.width,e.height);let n;n="jpg"===e.format?await a.renderToBuffer(t,"image/jpeg"):await a.renderToBuffer(t,"image/png");const r="jpg"===e.format?"jpg":"png",i="jpg"===e.format?"image/jpeg":"image/png",o=resolveOutputPath(e.outputPath,"chart",e.title,r);return writeBinary(o,n),{filePath:o,width:e.width,height:e.height,base64:n.toString("base64"),mimeType:i}}export function chartResultToContent(t){return{content:[{type:"text",text:`Chart saved to: ${t.filePath} (${t.width}x${t.height})`},{type:"image",data:t.base64,mimeType:t.mimeType}]}}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * DotZero color palette for charts
3
+ */
4
+ export declare const DOTZERO_COLORS: {
5
+ readonly availability: "#4CAF50";
6
+ readonly quality: "#2196F3";
7
+ readonly performance: "#FF9800";
8
+ readonly oee: "#9C27B0";
9
+ readonly good: "#4CAF50";
10
+ readonly defect: "#F44336";
11
+ readonly running: "#4CAF50";
12
+ readonly idle: "#FFC107";
13
+ readonly down: "#F44336";
14
+ readonly off: "#9E9E9E";
15
+ };
16
+ /** Default series colors for multi-dataset charts */
17
+ export declare const SERIES_COLORS: readonly ["#2196F3", "#4CAF50", "#FF9800", "#F44336", "#9C27B0", "#00BCD4", "#FF5722", "#795548", "#607D8B", "#E91E63", "#3F51B5", "#009688", "#CDDC39", "#FFC107", "#8BC34A"];
18
+ /** Get a color for a series index (cycles through palette) */
19
+ export declare function getSeriesColor(index: number): string;
20
+ /** Add alpha transparency to a hex color */
21
+ export declare function withAlpha(hex: string, alpha: number): string;
package/dist/colors.js ADDED
@@ -0,0 +1 @@
1
+ export const DOTZERO_COLORS={availability:"#4CAF50",quality:"#2196F3",performance:"#FF9800",oee:"#9C27B0",good:"#4CAF50",defect:"#F44336",running:"#4CAF50",idle:"#FFC107",down:"#F44336",off:"#9E9E9E"};export const SERIES_COLORS=["#2196F3","#4CAF50","#FF9800","#F44336","#9C27B0","#00BCD4","#FF5722","#795548","#607D8B","#E91E63","#3F51B5","#009688","#CDDC39","#FFC107","#8BC34A"];export function getSeriesColor(e){return SERIES_COLORS[e%SERIES_COLORS.length]}export function withAlpha(e,F){return`rgba(${parseInt(e.slice(1,3),16)}, ${parseInt(e.slice(3,5),16)}, ${parseInt(e.slice(5,7),16)}, ${F})`}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Data export engine — CSV and XLSX generation.
3
+ */
4
+ import type { ExportResult, ExportSheet } from "./types.js";
5
+ /** Generate a CSV string from headers and rows */
6
+ export declare function generateCsvString(headers: string[], rows: (string | number | boolean | null)[][]): string;
7
+ /** Generate CSV file and return result */
8
+ export declare function generateCsv(headers: string[], rows: (string | number | boolean | null)[][], filename?: string, outputPath?: string): ExportResult;
9
+ /** Generate XLSX file and return result */
10
+ export declare function generateXlsx(sheets: ExportSheet[], filename?: string, outputPath?: string): Promise<ExportResult>;
11
+ /** Build MCP content blocks from an ExportResult */
12
+ export declare function exportResultToContent(result: ExportResult): {
13
+ content: {
14
+ type: "text";
15
+ text: string;
16
+ }[];
17
+ };
@@ -0,0 +1 @@
1
+ import ExcelJS from"exceljs";import{resolveOutputPath,writeText}from"./file-output.js";function csvEscape(e){if(null==e)return"";const t=String(e);return t.includes(",")||t.includes('"')||t.includes("\n")?`"${t.replace(/"/g,'""')}"`:t}export function generateCsvString(e,t){const n=[e.map(csvEscape).join(",")];for(const e of t)n.push(e.map(csvEscape).join(","));return n.join("\n")+"\n"}export function generateCsv(e,t,n,o){const r=generateCsvString(e,t),s=resolveOutputPath(o,"export",n||"export","csv");return writeText(s,r),{filePath:s,rowCount:t.length,preview:buildPreview(e,t,5)}}export async function generateXlsx(e,t,n){const o=new ExcelJS.Workbook;let r=0;for(const t of e){const e=o.addWorksheet(t.name);e.addRow(t.headers).font={bold:!0};for(const n of t.rows)e.addRow(n.map(e=>null===e?"":e));e.columns.forEach((e,n)=>{let o=(t.headers[n]||"").length;for(const e of t.rows){const t=String(e[n]??"").length;t>o&&(o=t)}e.width=Math.min(Math.max(o+2,8),50)}),r+=t.rows.length}const s=resolveOutputPath(n,"export",t||"export","xlsx");await o.xlsx.writeFile(s);const i=e[0];return{filePath:s,rowCount:r,preview:i?buildPreview(i.headers,i.rows,5):"(empty)"}}function buildPreview(e,t,n){const o=["| "+e.join(" | ")+" |","| "+e.map(()=>"---").join(" | ")+" |",...t.slice(0,n).map(e=>"| "+e.map(e=>null===e?"":String(e)).join(" | ")+" |")];return t.length>n&&o.push(`| ... (${t.length-n} more rows) | ${e.slice(1).map(()=>"").join(" | ")} |`),o.join("\n")}export function exportResultToContent(e){return{content:[{type:"text",text:`Exported ${e.rowCount} rows to: ${e.filePath}\n\nPreview (first 5 rows):\n${e.preview}`}]}}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * File output utilities for export-mcp.
3
+ * Default output directory: .dotzero/exports/
4
+ */
5
+ /** Resolve output path — use custom path or generate default */
6
+ export declare function resolveOutputPath(customPath: string | undefined, prefix: string, name: string, ext: string): string;
7
+ /** Write binary data (PNG/JPG) */
8
+ export declare function writeBinary(filePath: string, data: Buffer): void;
9
+ /** Write text data (CSV) */
10
+ export declare function writeText(filePath: string, data: string): void;
@@ -0,0 +1 @@
1
+ import{existsSync,mkdirSync,writeFileSync}from"node:fs";import{dirname,join,resolve}from"node:path";const DEFAULT_DIR=".dotzero/exports";function ensureDir(e){existsSync(e)||mkdirSync(e,{recursive:!0})}function timestamp(){return(new Date).toISOString().replace(/[:.]/g,"-").slice(0,19)}export function resolveOutputPath(e,r,t,i){if(e){const r=resolve(e),t=process.cwd(),i=resolve(DEFAULT_DIR);if(!r.startsWith(t+"/")&&r!==t&&!r.startsWith(i+"/")&&r!==i)throw new Error(`Output path must be within the project directory. Got: "${e}"`);return ensureDir(dirname(r)),r}const n=resolve(DEFAULT_DIR);ensureDir(n);const o=t.replace(/[^a-zA-Z0-9_-]/g,"-").toLowerCase();return join(n,`${r}-${o}-${timestamp()}.${i}`)}export function writeBinary(e,r){ensureDir(dirname(e)),writeFileSync(e,r)}export function writeText(e,r){ensureDir(dirname(e)),writeFileSync(e,r,"utf-8")}
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP Server for Chart Generation & Data Export
4
+ *
5
+ * Provides tools for generating PNG/JPG charts and CSV/XLSX exports.
6
+ * No authentication required — this is a pure rendering engine.
7
+ */
8
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{McpServer}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import express from"express";import{registerAllTools}from"./tool-registry.js";const server=new McpServer({name:"export-mcp-server",version:"1.0.0"});async function runStdio(){const r=new StdioServerTransport;await server.connect(r),console.error("Export MCP Server running via stdio")}async function runHTTP(){const r=express();r.use(express.json()),r.post("/mcp",async(r,e)=>{const o=new StreamableHTTPServerTransport({sessionIdGenerator:void 0,enableJsonResponse:!0});e.on("close",()=>o.close()),await server.connect(o),await o.handleRequest(r,e,r.body)}),r.get("/health",(r,e)=>{e.json({status:"ok",name:"export-mcp-server",version:"1.0.0"})});const e=parseInt(process.env.PORT||"3001");r.listen(e,()=>{console.error(`Export MCP Server running on http://localhost:${e}/mcp`)})}registerAllTools(server);const transport=process.env.TRANSPORT||"stdio";"http"===transport?runHTTP().catch(r=>{console.error("Server error:",r),process.exit(1)}):runStdio().catch(r=>{console.error("Server error:",r),process.exit(1)});