@vint.tri/report_gen_mcp 1.0.0

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.
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.barSchema = void 0;
4
+ exports.renderBarChart = renderBarChart;
5
+ const zod_1 = require("zod");
6
+ const chartjs_node_canvas_1 = require("chartjs-node-canvas");
7
+ exports.barSchema = zod_1.z.object({
8
+ labels: zod_1.z.array(zod_1.z.string()),
9
+ datasets: zod_1.z.array(zod_1.z.object({
10
+ label: zod_1.z.string(),
11
+ data: zod_1.z.array(zod_1.z.number()),
12
+ backgroundColor: zod_1.z.array(zod_1.z.string()).optional(),
13
+ })),
14
+ options: zod_1.z.object({
15
+ title: zod_1.z.string().optional(),
16
+ // Add more Chart.js options as needed
17
+ }).optional(),
18
+ });
19
+ async function renderBarChart(config) {
20
+ const chartConfig = {
21
+ type: 'bar',
22
+ data: {
23
+ labels: config.labels,
24
+ datasets: config.datasets,
25
+ },
26
+ options: {
27
+ ...config.options,
28
+ plugins: {
29
+ title: config.options?.title ? {
30
+ display: true,
31
+ text: config.options.title
32
+ } : undefined
33
+ }
34
+ },
35
+ };
36
+ const width = 800;
37
+ const height = 600;
38
+ const chartJSNodeCanvas = new chartjs_node_canvas_1.ChartJSNodeCanvas({ width, height });
39
+ const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
40
+ const base64Image = buffer.toString('base64');
41
+ return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
42
+ }
@@ -0,0 +1,42 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lineSchema = void 0;
4
+ exports.renderLineChart = renderLineChart;
5
+ const zod_1 = require("zod");
6
+ const chartjs_node_canvas_1 = require("chartjs-node-canvas");
7
+ exports.lineSchema = zod_1.z.object({
8
+ labels: zod_1.z.array(zod_1.z.string()),
9
+ datasets: zod_1.z.array(zod_1.z.object({
10
+ label: zod_1.z.string(),
11
+ data: zod_1.z.array(zod_1.z.number()),
12
+ borderColor: zod_1.z.string().optional(),
13
+ })),
14
+ options: zod_1.z.object({
15
+ title: zod_1.z.string().optional(),
16
+ // Add more Chart.js options as needed
17
+ }).optional(),
18
+ });
19
+ async function renderLineChart(config) {
20
+ const chartConfig = {
21
+ type: 'line',
22
+ data: {
23
+ labels: config.labels,
24
+ datasets: config.datasets,
25
+ },
26
+ options: {
27
+ ...config.options,
28
+ plugins: {
29
+ title: config.options?.title ? {
30
+ display: true,
31
+ text: config.options.title
32
+ } : undefined
33
+ }
34
+ },
35
+ };
36
+ const width = 800;
37
+ const height = 600;
38
+ const chartJSNodeCanvas = new chartjs_node_canvas_1.ChartJSNodeCanvas({ width, height });
39
+ const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
40
+ const base64Image = buffer.toString('base64');
41
+ return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
42
+ }
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pieSchema = void 0;
4
+ exports.renderPieChart = renderPieChart;
5
+ const zod_1 = require("zod");
6
+ const chartjs_node_canvas_1 = require("chartjs-node-canvas");
7
+ exports.pieSchema = zod_1.z.object({
8
+ labels: zod_1.z.array(zod_1.z.string()),
9
+ datasets: zod_1.z.array(zod_1.z.object({
10
+ data: zod_1.z.array(zod_1.z.number()),
11
+ backgroundColor: zod_1.z.array(zod_1.z.string()).optional(),
12
+ })),
13
+ options: zod_1.z.object({
14
+ title: zod_1.z.string().optional(),
15
+ // Add more Chart.js options as needed
16
+ }).optional(),
17
+ });
18
+ async function renderPieChart(config) {
19
+ const chartConfig = {
20
+ type: 'pie',
21
+ data: {
22
+ labels: config.labels,
23
+ datasets: config.datasets,
24
+ },
25
+ options: {
26
+ ...config.options,
27
+ plugins: {
28
+ title: config.options?.title ? {
29
+ display: true,
30
+ text: config.options.title
31
+ } : undefined
32
+ }
33
+ },
34
+ };
35
+ const width = 800;
36
+ const height = 600;
37
+ const chartJSNodeCanvas = new chartjs_node_canvas_1.ChartJSNodeCanvas({ width, height });
38
+ const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
39
+ const base64Image = buffer.toString('base64');
40
+ return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
41
+ }
package/dist/index.js ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const express_1 = __importDefault(require("express"));
8
+ const commander_1 = require("commander");
9
+ const reportGenerator_1 = require("./utils/reportGenerator");
10
+ const path_1 = __importDefault(require("path"));
11
+ const app = (0, express_1.default)();
12
+ const port = 3000;
13
+ app.use(express_1.default.json());
14
+ app.post('/generate-report', async (req, res) => {
15
+ const { document, charts, outputFile = 'report.html' } = req.body;
16
+ try {
17
+ const result = await (0, reportGenerator_1.generateReport)(document, charts, path_1.default.resolve(outputFile));
18
+ res.json(result);
19
+ }
20
+ catch (error) {
21
+ res.status(500).json({ error: error.message });
22
+ }
23
+ });
24
+ commander_1.program
25
+ .command('start-server')
26
+ .description('Start the MCP report generation server')
27
+ .action(() => {
28
+ app.listen(port, () => {
29
+ console.log(`Server running at http://localhost:${port}`);
30
+ });
31
+ });
32
+ commander_1.program
33
+ .command('generate')
34
+ .option('--document <md>', 'Markdown document with placeholders [[chart:id]]')
35
+ .option('--charts <json>', 'JSON string of charts {id: {type: "bar", config: {...}}}')
36
+ .option('--output <file>', 'Output HTML file', 'report.html')
37
+ .action(async (opts) => {
38
+ const charts = JSON.parse(opts.charts);
39
+ const result = await (0, reportGenerator_1.generateReport)(opts.document, charts, opts.output);
40
+ console.log(result);
41
+ });
42
+ commander_1.program.parse();
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.generateReport = generateReport;
7
+ const fs_extra_1 = __importDefault(require("fs-extra"));
8
+ const ejs_1 = __importDefault(require("ejs"));
9
+ const marked_1 = require("marked");
10
+ const bar_1 = require("../charts/bar");
11
+ const line_1 = require("../charts/line");
12
+ const pie_1 = require("../charts/pie");
13
+ // Add more imports for other chart types as needed
14
+ const chartRenderers = {
15
+ bar: { schema: bar_1.barSchema, renderer: bar_1.renderBarChart },
16
+ line: { schema: line_1.lineSchema, renderer: line_1.renderLineChart },
17
+ pie: { schema: pie_1.pieSchema, renderer: pie_1.renderPieChart },
18
+ // Add more chart types here
19
+ };
20
+ async function generateReport(document, charts, outputFile) {
21
+ // Validate charts
22
+ for (const [id, { type, config }] of Object.entries(charts)) {
23
+ const { schema } = chartRenderers[type];
24
+ if (!schema)
25
+ throw new Error(`Unsupported chart type: ${type}`);
26
+ schema.parse(config);
27
+ }
28
+ // Render charts to HTML img tags
29
+ const renderedCharts = {};
30
+ for (const [id, { type, config }] of Object.entries(charts)) {
31
+ const htmlImg = await chartRenderers[type].renderer(config);
32
+ renderedCharts[id] = htmlImg;
33
+ }
34
+ // Replace placeholders in Markdown, e.g., [[chart:id]]
35
+ let mdWithCharts = document;
36
+ for (const [id, htmlImg] of Object.entries(renderedCharts)) {
37
+ mdWithCharts = mdWithCharts.replace(new RegExp(`\\[\\[chart:${id}\\]\\]`, 'g'), htmlImg);
38
+ }
39
+ // Convert Markdown to HTML
40
+ const htmlContent = await (0, marked_1.marked)(mdWithCharts);
41
+ // Wrap in full HTML template
42
+ const template = `
43
+ <!DOCTYPE html>
44
+ <html lang="en">
45
+ <head>
46
+ <meta charset="UTF-8">
47
+ <title>Report</title>
48
+ <style> body { font-family: Arial, sans-serif; } img { max-width: 100%; } </style>
49
+ </head>
50
+ <body>
51
+ <%- htmlContent %>
52
+ </body>
53
+ </html>
54
+ `;
55
+ const fullHtml = ejs_1.default.render(template, { htmlContent }, { escape: (str) => str });
56
+ // Save to file
57
+ await fs_extra_1.default.writeFile(outputFile, fullHtml);
58
+ return { success: true, filePath: outputFile };
59
+ }
@@ -0,0 +1 @@
1
+ {"success":true,"filePath":"/Applications/Python/report_gen_mcp/test-report.html"}
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@vint.tri/report_gen_mcp",
3
+ "version": "1.0.0",
4
+ "description": "CLI tool for generating HTML reports with embedded charts",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "report_gen_mcp": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "start": "node dist/index.js",
12
+ "test": "echo \"No tests yet\""
13
+ },
14
+ "dependencies": {
15
+ "chart.js": "^3.9.1",
16
+ "chartjs-node-canvas": "^4.1.6",
17
+ "commander": "^12.1.0",
18
+ "ejs": "^3.1.10",
19
+ "express": "^4.19.2",
20
+ "fs-extra": "^11.2.0",
21
+ "marked": "^13.0.2",
22
+ "zod": "^3.23.8"
23
+ },
24
+ "devDependencies": {
25
+ "@types/ejs": "^3.1.5",
26
+ "@types/express": "^4.17.21",
27
+ "@types/fs-extra": "^11.0.4",
28
+ "@types/node": "^22.4.1",
29
+ "typescript": "^5.5.4"
30
+ },
31
+ "license": "MIT",
32
+ "author": ""
33
+ }
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import { ChartConfiguration } from 'chart.js';
3
+ import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
4
+
5
+ export const barSchema = z.object({
6
+ labels: z.array(z.string()),
7
+ datasets: z.array(z.object({
8
+ label: z.string(),
9
+ data: z.array(z.number()),
10
+ backgroundColor: z.array(z.string()).optional(),
11
+ })),
12
+ options: z.object({
13
+ title: z.string().optional(),
14
+ // Add more Chart.js options as needed
15
+ }).optional(),
16
+ });
17
+
18
+ export async function renderBarChart(config: z.infer<typeof barSchema>): Promise<string> {
19
+ const chartConfig: ChartConfiguration = {
20
+ type: 'bar',
21
+ data: {
22
+ labels: config.labels,
23
+ datasets: config.datasets,
24
+ },
25
+ options: {
26
+ ...config.options,
27
+ plugins: {
28
+ title: config.options?.title ? {
29
+ display: true,
30
+ text: config.options.title
31
+ } : undefined
32
+ }
33
+ },
34
+ };
35
+
36
+ const width = 800;
37
+ const height = 600;
38
+ const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
39
+ const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
40
+ const base64Image = buffer.toString('base64');
41
+ return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
42
+ }
@@ -0,0 +1,42 @@
1
+ import { z } from 'zod';
2
+ import { ChartConfiguration } from 'chart.js';
3
+ import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
4
+
5
+ export const lineSchema = z.object({
6
+ labels: z.array(z.string()),
7
+ datasets: z.array(z.object({
8
+ label: z.string(),
9
+ data: z.array(z.number()),
10
+ borderColor: z.string().optional(),
11
+ })),
12
+ options: z.object({
13
+ title: z.string().optional(),
14
+ // Add more Chart.js options as needed
15
+ }).optional(),
16
+ });
17
+
18
+ export async function renderLineChart(config: z.infer<typeof lineSchema>): Promise<string> {
19
+ const chartConfig: ChartConfiguration = {
20
+ type: 'line',
21
+ data: {
22
+ labels: config.labels,
23
+ datasets: config.datasets,
24
+ },
25
+ options: {
26
+ ...config.options,
27
+ plugins: {
28
+ title: config.options?.title ? {
29
+ display: true,
30
+ text: config.options.title
31
+ } : undefined
32
+ }
33
+ },
34
+ };
35
+
36
+ const width = 800;
37
+ const height = 600;
38
+ const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
39
+ const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
40
+ const base64Image = buffer.toString('base64');
41
+ return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
42
+ }
@@ -0,0 +1,41 @@
1
+ import { z } from 'zod';
2
+ import { ChartConfiguration } from 'chart.js';
3
+ import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
4
+
5
+ export const pieSchema = z.object({
6
+ labels: z.array(z.string()),
7
+ datasets: z.array(z.object({
8
+ data: z.array(z.number()),
9
+ backgroundColor: z.array(z.string()).optional(),
10
+ })),
11
+ options: z.object({
12
+ title: z.string().optional(),
13
+ // Add more Chart.js options as needed
14
+ }).optional(),
15
+ });
16
+
17
+ export async function renderPieChart(config: z.infer<typeof pieSchema>): Promise<string> {
18
+ const chartConfig: ChartConfiguration = {
19
+ type: 'pie',
20
+ data: {
21
+ labels: config.labels,
22
+ datasets: config.datasets,
23
+ },
24
+ options: {
25
+ ...config.options,
26
+ plugins: {
27
+ title: config.options?.title ? {
28
+ display: true,
29
+ text: config.options.title
30
+ } : undefined
31
+ }
32
+ },
33
+ };
34
+
35
+ const width = 800;
36
+ const height = 600;
37
+ const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
38
+ const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
39
+ const base64Image = buffer.toString('base64');
40
+ return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
41
+ }
package/src/index.ts ADDED
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env node
2
+
3
+ import express from 'express';
4
+ import { program } from 'commander';
5
+ import { generateReport } from './utils/reportGenerator';
6
+ import path from 'path';
7
+
8
+ const app = express();
9
+ const port = 3000;
10
+
11
+ app.use(express.json());
12
+
13
+ app.post('/generate-report', async (req, res) => {
14
+ const { document, charts, outputFile = 'report.html' } = req.body;
15
+ try {
16
+ const result = await generateReport(document, charts, path.resolve(outputFile));
17
+ res.json(result);
18
+ } catch (error) {
19
+ res.status(500).json({ error: (error as Error).message });
20
+ }
21
+ });
22
+
23
+ program
24
+ .command('start-server')
25
+ .description('Start the MCP report generation server')
26
+ .action(() => {
27
+ app.listen(port, () => {
28
+ console.log(`Server running at http://localhost:${port}`);
29
+ });
30
+ });
31
+
32
+ program
33
+ .command('generate')
34
+ .option('--document <md>', 'Markdown document with placeholders [[chart:id]]')
35
+ .option('--charts <json>', 'JSON string of charts {id: {type: "bar", config: {...}}}')
36
+ .option('--output <file>', 'Output HTML file', 'report.html')
37
+ .action(async (opts) => {
38
+ const charts = JSON.parse(opts.charts);
39
+ const result = await generateReport(opts.document, charts, opts.output);
40
+ console.log(result);
41
+ });
42
+
43
+ program.parse();
@@ -0,0 +1,60 @@
1
+ import fs from 'fs-extra';
2
+ import ejs from 'ejs';
3
+ import { marked } from 'marked';
4
+ import { z } from 'zod';
5
+ import { barSchema, renderBarChart } from '../charts/bar';
6
+ import { lineSchema, renderLineChart } from '../charts/line';
7
+ import { pieSchema, renderPieChart } from '../charts/pie';
8
+ // Add more imports for other chart types as needed
9
+
10
+ const chartRenderers: Record<string, { schema: z.ZodObject<any>; renderer: (config: any) => Promise<string> }> = {
11
+ bar: { schema: barSchema, renderer: renderBarChart },
12
+ line: { schema: lineSchema, renderer: renderLineChart },
13
+ pie: { schema: pieSchema, renderer: renderPieChart },
14
+ // Add more chart types here
15
+ };
16
+
17
+ export async function generateReport(document: string, charts: Record<string, { type: string; config: any }>, outputFile: string) {
18
+ // Validate charts
19
+ for (const [id, { type, config }] of Object.entries(charts)) {
20
+ const { schema } = chartRenderers[type];
21
+ if (!schema) throw new Error(`Unsupported chart type: ${type}`);
22
+ schema.parse(config);
23
+ }
24
+
25
+ // Render charts to HTML img tags
26
+ const renderedCharts: Record<string, string> = {};
27
+ for (const [id, { type, config }] of Object.entries(charts)) {
28
+ const htmlImg = await chartRenderers[type].renderer(config);
29
+ renderedCharts[id] = htmlImg;
30
+ }
31
+
32
+ // Replace placeholders in Markdown, e.g., [[chart:id]]
33
+ let mdWithCharts = document;
34
+ for (const [id, htmlImg] of Object.entries(renderedCharts)) {
35
+ mdWithCharts = mdWithCharts.replace(new RegExp(`\\[\\[chart:${id}\\]\\]`, 'g'), htmlImg);
36
+ }
37
+
38
+ // Convert Markdown to HTML
39
+ const htmlContent = await marked(mdWithCharts);
40
+
41
+ // Wrap in full HTML template
42
+ const template = `
43
+ <!DOCTYPE html>
44
+ <html lang="en">
45
+ <head>
46
+ <meta charset="UTF-8">
47
+ <title>Report</title>
48
+ <style> body { font-family: Arial, sans-serif; } img { max-width: 100%; } </style>
49
+ </head>
50
+ <body>
51
+ <%- htmlContent %>
52
+ </body>
53
+ </html>
54
+ `;
55
+ const fullHtml = ejs.render(template, { htmlContent }, { escape: (str) => str });
56
+
57
+ // Save to file
58
+ await fs.writeFile(outputFile, fullHtml);
59
+ return { success: true, filePath: outputFile };
60
+ }
@@ -0,0 +1,14 @@
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>Report</title>
7
+ <style> body { font-family: Arial, sans-serif; } svg { max-width: 100%; } </style>
8
+ </head>
9
+ <body>
10
+ &lt;h1&gt;Test Report\n\nThis is a test report.\n\n&lt;img src=&#34;data:image/png;base64,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&#34; alt=&#34;Chart&#34; /&gt;&lt;/h1&gt;
11
+
12
+ </body>
13
+ </html>
14
+
Binary file
@@ -0,0 +1,19 @@
1
+
2
+ <!DOCTYPE html>
3
+ <html lang="en">
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <title>Report</title>
7
+ <style> body { font-family: Arial, sans-serif; } img { max-width: 100%; } </style>
8
+ </head>
9
+ <body>
10
+ <h1>Sales Report</h1>
11
+ <p>This is our monthly sales report.</p>
12
+ <img src="data:image/png;base64,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" alt="Chart" />
13
+
14
+ <h2>Conclusion</h2>
15
+ <p>This is the end of our report.</p>
16
+
17
+ </body>
18
+ </html>
19
+
@@ -0,0 +1,22 @@
1
+ {
2
+ "document": "# Sales Report\n\nThis is our monthly sales report.\n\n[[chart:sales]]\n\n## Conclusion\n\nThis is the end of our report.",
3
+ "charts": {
4
+ "sales": {
5
+ "type": "bar",
6
+ "config": {
7
+ "labels": ["January", "February", "March", "April", "May"],
8
+ "datasets": [
9
+ {
10
+ "label": "Sales",
11
+ "data": [100, 150, 200, 175, 225],
12
+ "backgroundColor": ["#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF"]
13
+ }
14
+ ],
15
+ "options": {
16
+ "title": "Monthly Sales Data"
17
+ }
18
+ }
19
+ }
20
+ },
21
+ "outputFile": "test-report.html"
22
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,13 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "outDir": "./dist",
6
+ "strict": true,
7
+ "esModuleInterop": true,
8
+ "skipLibCheck": true,
9
+ "forceConsistentCasingInFileNames": true
10
+ },
11
+ "include": ["src/**/*"],
12
+ "exclude": ["node_modules"]
13
+ }