@vint.tri/report_gen_mcp 1.0.36 → 1.0.39
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.
- package/README.md +3 -3
- package/demonstrate-all-features.js +168 -0
- package/direct-test.js +31 -0
- package/dist/charts/bar.js +13 -17
- package/dist/charts/line.js +13 -17
- package/dist/charts/pie.js +12 -16
- package/dist/index.js +278 -81
- package/dist/utils/reportGenerator.js +14 -20
- package/dollar_to_ruble_report.html +37 -4
- package/package/README.md +445 -0
- package/package.json +2 -1
- package/simple-test-tools.js +80 -0
- package/src/index.ts +244 -24
- package/src/utils/reportGenerator.ts +3 -3
- package/test_reports/new-report.html +12 -0
- package/test_reports/simple-test.html +1 -0
- package/test_reports/test-file.html +1 -0
package/README.md
CHANGED
|
@@ -17,13 +17,13 @@ A powerful CLI tool for generating HTML reports with embedded charts, designed t
|
|
|
17
17
|
### Global Installation (Recommended)
|
|
18
18
|
|
|
19
19
|
```bash
|
|
20
|
-
npm install -g @vint.tri/report_gen_mcp@1.0.
|
|
20
|
+
npm install -g @vint.tri/report_gen_mcp@1.0.39
|
|
21
21
|
```
|
|
22
22
|
|
|
23
23
|
### Direct Execution with npx
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
REPORTS_DIR=./reports npx @vint.tri/report_gen_mcp@1.0.
|
|
26
|
+
REPORTS_DIR=./reports npx @vint.tri/report_gen_mcp@1.0.39
|
|
27
27
|
```
|
|
28
28
|
|
|
29
29
|
## Usage
|
|
@@ -80,7 +80,7 @@ To use this tool with Claude Desktop, add the following configuration to your Cl
|
|
|
80
80
|
"REPORTS_DIR": "./reports"
|
|
81
81
|
},
|
|
82
82
|
"args": [
|
|
83
|
-
"@vint.tri/report_gen_mcp@1.0.
|
|
83
|
+
"@vint.tri/report_gen_mcp@1.0.39"
|
|
84
84
|
]
|
|
85
85
|
}
|
|
86
86
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import fs from 'fs-extra';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { fileURLToPath } from 'url';
|
|
7
|
+
|
|
8
|
+
// Get the directory of this script
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const __dirname = path.dirname(__filename);
|
|
11
|
+
|
|
12
|
+
// Path to our package
|
|
13
|
+
const packagePath = path.join(__dirname, 'dist', 'index.js');
|
|
14
|
+
|
|
15
|
+
console.log('Demonstrating all features...\n');
|
|
16
|
+
|
|
17
|
+
// Function to send a JSON-RPC request
|
|
18
|
+
function sendRequest(child, method, params, id) {
|
|
19
|
+
const request = {
|
|
20
|
+
jsonrpc: "2.0",
|
|
21
|
+
id: id,
|
|
22
|
+
method: method,
|
|
23
|
+
params: params
|
|
24
|
+
};
|
|
25
|
+
child.stdin.write(JSON.stringify(request) + '\n');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Function to demonstrate all features
|
|
29
|
+
async function demonstrateFeatures() {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
// Spawn the child process
|
|
32
|
+
const child = spawn('node', [packagePath], {
|
|
33
|
+
cwd: __dirname
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
let responseCount = 0;
|
|
37
|
+
const expectedResponses = 6; // We expect 6 responses
|
|
38
|
+
|
|
39
|
+
// Handle stdout (responses from the server)
|
|
40
|
+
child.stdout.on('data', (data) => {
|
|
41
|
+
const responses = data.toString().trim().split('\n');
|
|
42
|
+
for (const responseStr of responses) {
|
|
43
|
+
if (responseStr) {
|
|
44
|
+
try {
|
|
45
|
+
const response = JSON.parse(responseStr);
|
|
46
|
+
console.log('Received response:', JSON.stringify(response, null, 2));
|
|
47
|
+
|
|
48
|
+
responseCount++;
|
|
49
|
+
if (responseCount >= expectedResponses) {
|
|
50
|
+
child.kill();
|
|
51
|
+
resolve();
|
|
52
|
+
}
|
|
53
|
+
} catch (err) {
|
|
54
|
+
console.error('Error parsing response:', err);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Handle stderr (logs from the server)
|
|
61
|
+
child.stderr.on('data', (data) => {
|
|
62
|
+
console.log('Server log:', data.toString());
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
// Handle process exit
|
|
66
|
+
child.on('close', (code) => {
|
|
67
|
+
console.log(`Child process exited with code ${code}`);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// Handle errors
|
|
71
|
+
child.on('error', (err) => {
|
|
72
|
+
console.error('Failed to start child process:', err);
|
|
73
|
+
reject(err);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// After a short delay, send initialization request
|
|
77
|
+
setTimeout(() => {
|
|
78
|
+
// Send initialize request
|
|
79
|
+
sendRequest(child, "initialize", {
|
|
80
|
+
protocolVersion: "2024-05-03",
|
|
81
|
+
capabilities: {},
|
|
82
|
+
clientInfo: {
|
|
83
|
+
name: "test-client",
|
|
84
|
+
version: "1.0.0"
|
|
85
|
+
}
|
|
86
|
+
}, 1);
|
|
87
|
+
|
|
88
|
+
// Send tools listing request
|
|
89
|
+
setTimeout(() => {
|
|
90
|
+
sendRequest(child, "tools/list", {}, 2);
|
|
91
|
+
}, 1000);
|
|
92
|
+
|
|
93
|
+
// Send a generate-report request
|
|
94
|
+
setTimeout(() => {
|
|
95
|
+
sendRequest(child, "tools/call", {
|
|
96
|
+
name: "generate-report",
|
|
97
|
+
arguments: {
|
|
98
|
+
document: "# Sales Report\n\nThis is a sample sales report with charts.\n\n[[chart:sales]]\n\n## Summary\n\nThis report shows sales data for the quarter.",
|
|
99
|
+
charts: {
|
|
100
|
+
sales: {
|
|
101
|
+
type: "bar",
|
|
102
|
+
config: {
|
|
103
|
+
labels: ["Q1", "Q2", "Q3", "Q4"],
|
|
104
|
+
datasets: [{
|
|
105
|
+
label: "Sales ($)",
|
|
106
|
+
data: [12000, 19000, 15000, 22000],
|
|
107
|
+
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0"]
|
|
108
|
+
}]
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
outputFile: "demo-report.html"
|
|
113
|
+
}
|
|
114
|
+
}, 3);
|
|
115
|
+
}, 2000);
|
|
116
|
+
|
|
117
|
+
// Send a get-report-url request
|
|
118
|
+
setTimeout(() => {
|
|
119
|
+
// First, let's find out where the report was saved
|
|
120
|
+
const reportsDir = process.env.REPORTS_DIR || require('os').tmpdir();
|
|
121
|
+
const reportPath = path.join(reportsDir, "demo-report.html");
|
|
122
|
+
|
|
123
|
+
sendRequest(child, "tools/call", {
|
|
124
|
+
name: "get-report-url",
|
|
125
|
+
arguments: {
|
|
126
|
+
filePath: reportPath
|
|
127
|
+
}
|
|
128
|
+
}, 4);
|
|
129
|
+
}, 4000);
|
|
130
|
+
|
|
131
|
+
// Send an edit-generate-report read request
|
|
132
|
+
setTimeout(() => {
|
|
133
|
+
const reportsDir = process.env.REPORTS_DIR || require('os').tmpdir();
|
|
134
|
+
const reportPath = path.join(reportsDir, "demo-report.html");
|
|
135
|
+
|
|
136
|
+
sendRequest(child, "tools/call", {
|
|
137
|
+
name: "edit-generate-report",
|
|
138
|
+
arguments: {
|
|
139
|
+
operation: "read",
|
|
140
|
+
filePath: reportPath
|
|
141
|
+
}
|
|
142
|
+
}, 5);
|
|
143
|
+
}, 6000);
|
|
144
|
+
|
|
145
|
+
// Send an edit-generate-report append request
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
const reportsDir = process.env.REPORTS_DIR || require('os').tmpdir();
|
|
148
|
+
const reportPath = path.join(reportsDir, "demo-report.html");
|
|
149
|
+
|
|
150
|
+
sendRequest(child, "tools/call", {
|
|
151
|
+
name: "edit-generate-report",
|
|
152
|
+
arguments: {
|
|
153
|
+
operation: "append",
|
|
154
|
+
filePath: reportPath,
|
|
155
|
+
content: "\n\n<!-- Appended content -->\n<p>This content was appended to the report.</p>"
|
|
156
|
+
}
|
|
157
|
+
}, 6);
|
|
158
|
+
}, 8000);
|
|
159
|
+
}, 1000);
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Run the demonstration
|
|
164
|
+
demonstrateFeatures().then(() => {
|
|
165
|
+
console.log('\nDemonstration completed successfully!');
|
|
166
|
+
}).catch((err) => {
|
|
167
|
+
console.error('Demonstration failed:', err);
|
|
168
|
+
});
|
package/direct-test.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { generateReport } from './src/utils/reportGenerator.js';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
|
|
5
|
+
async function testDirectFunction() {
|
|
6
|
+
console.log('Testing direct function call...');
|
|
7
|
+
|
|
8
|
+
try {
|
|
9
|
+
// Test generateReport function directly
|
|
10
|
+
const document = '# Test Report\n\nThis is a test report.';
|
|
11
|
+
const charts = {};
|
|
12
|
+
const outputPath = path.resolve('./test_direct.html');
|
|
13
|
+
|
|
14
|
+
const result = await generateReport(document, charts, outputPath);
|
|
15
|
+
console.log('generateReport result:', result);
|
|
16
|
+
|
|
17
|
+
// Check if file was created
|
|
18
|
+
const fileExists = await fs.pathExists(outputPath);
|
|
19
|
+
console.log('File created:', fileExists);
|
|
20
|
+
|
|
21
|
+
if (fileExists) {
|
|
22
|
+
const content = await fs.readFile(outputPath, 'utf8');
|
|
23
|
+
console.log('File content length:', content.length);
|
|
24
|
+
await fs.remove(outputPath); // Clean up
|
|
25
|
+
}
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.error('Error:', error.message);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
testDirectFunction();
|
package/dist/charts/bar.js
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
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
|
-
borderColor: zod_1.z.array(zod_1.z.string()).optional(),
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
|
|
3
|
+
export const barSchema = z.object({
|
|
4
|
+
labels: z.array(z.string()),
|
|
5
|
+
datasets: z.array(z.object({
|
|
6
|
+
label: z.string(),
|
|
7
|
+
data: z.array(z.number()),
|
|
8
|
+
backgroundColor: z.array(z.string()).optional(),
|
|
9
|
+
borderColor: z.array(z.string()).optional(),
|
|
14
10
|
})),
|
|
15
|
-
options:
|
|
16
|
-
title:
|
|
11
|
+
options: z.object({
|
|
12
|
+
title: z.string().optional(),
|
|
17
13
|
// Add more Chart.js options as needed
|
|
18
14
|
}).optional(),
|
|
19
15
|
});
|
|
20
|
-
async function renderBarChart(config) {
|
|
16
|
+
export async function renderBarChart(config) {
|
|
21
17
|
const chartConfig = {
|
|
22
18
|
type: 'bar',
|
|
23
19
|
data: {
|
|
@@ -36,7 +32,7 @@ async function renderBarChart(config) {
|
|
|
36
32
|
};
|
|
37
33
|
const width = 800;
|
|
38
34
|
const height = 600;
|
|
39
|
-
const chartJSNodeCanvas = new
|
|
35
|
+
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
|
|
40
36
|
const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
|
|
41
37
|
const base64Image = buffer.toString('base64');
|
|
42
38
|
return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
|
package/dist/charts/line.js
CHANGED
|
@@ -1,23 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
label: zod_1.z.string(),
|
|
11
|
-
data: zod_1.z.array(zod_1.z.number()),
|
|
12
|
-
borderColor: zod_1.z.array(zod_1.z.string()).optional(),
|
|
13
|
-
fill: zod_1.z.boolean().optional(),
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
|
|
3
|
+
export const lineSchema = z.object({
|
|
4
|
+
labels: z.array(z.string()),
|
|
5
|
+
datasets: z.array(z.object({
|
|
6
|
+
label: z.string(),
|
|
7
|
+
data: z.array(z.number()),
|
|
8
|
+
borderColor: z.array(z.string()).optional(),
|
|
9
|
+
fill: z.boolean().optional(),
|
|
14
10
|
})),
|
|
15
|
-
options:
|
|
16
|
-
title:
|
|
11
|
+
options: z.object({
|
|
12
|
+
title: z.string().optional(),
|
|
17
13
|
// Add more Chart.js options as needed
|
|
18
14
|
}).optional(),
|
|
19
15
|
});
|
|
20
|
-
async function renderLineChart(config) {
|
|
16
|
+
export async function renderLineChart(config) {
|
|
21
17
|
const chartConfig = {
|
|
22
18
|
type: 'line',
|
|
23
19
|
data: {
|
|
@@ -36,7 +32,7 @@ async function renderLineChart(config) {
|
|
|
36
32
|
};
|
|
37
33
|
const width = 800;
|
|
38
34
|
const height = 600;
|
|
39
|
-
const chartJSNodeCanvas = new
|
|
35
|
+
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
|
|
40
36
|
const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
|
|
41
37
|
const base64Image = buffer.toString('base64');
|
|
42
38
|
return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
|
package/dist/charts/pie.js
CHANGED
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
-
borderColor: zod_1.z.array(zod_1.z.string()).optional(),
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ChartJSNodeCanvas } from 'chartjs-node-canvas';
|
|
3
|
+
export const pieSchema = z.object({
|
|
4
|
+
labels: z.array(z.string()),
|
|
5
|
+
datasets: z.array(z.object({
|
|
6
|
+
data: z.array(z.number()),
|
|
7
|
+
backgroundColor: z.array(z.string()).optional(),
|
|
8
|
+
borderColor: z.array(z.string()).optional(),
|
|
13
9
|
})),
|
|
14
|
-
options:
|
|
15
|
-
title:
|
|
10
|
+
options: z.object({
|
|
11
|
+
title: z.string().optional(),
|
|
16
12
|
// Add more Chart.js options as needed
|
|
17
13
|
}).optional(),
|
|
18
14
|
});
|
|
19
|
-
async function renderPieChart(config) {
|
|
15
|
+
export async function renderPieChart(config) {
|
|
20
16
|
const chartConfig = {
|
|
21
17
|
type: 'pie',
|
|
22
18
|
data: {
|
|
@@ -35,7 +31,7 @@ async function renderPieChart(config) {
|
|
|
35
31
|
};
|
|
36
32
|
const width = 800;
|
|
37
33
|
const height = 600;
|
|
38
|
-
const chartJSNodeCanvas = new
|
|
34
|
+
const chartJSNodeCanvas = new ChartJSNodeCanvas({ width, height });
|
|
39
35
|
const buffer = await chartJSNodeCanvas.renderToBuffer(chartConfig);
|
|
40
36
|
const base64Image = buffer.toString('base64');
|
|
41
37
|
return `<img src="data:image/png;base64,${base64Image}" alt="Chart" />`;
|