@vint.tri/report_gen_mcp 1.0.30 โ†’ 1.0.31

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/dist/index.js CHANGED
@@ -9,6 +9,7 @@ const commander_1 = require("commander");
9
9
  const reportGenerator_1 = require("./utils/reportGenerator");
10
10
  const path_1 = __importDefault(require("path"));
11
11
  const fs_extra_1 = __importDefault(require("fs-extra"));
12
+ const os_1 = __importDefault(require("os"));
12
13
  const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
13
14
  const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
14
15
  const zod_1 = require("zod");
@@ -88,7 +89,7 @@ if (process.argv.length === 2) {
88
89
  // No command specified, run in stdio mode using MCP SDK
89
90
  const mcpServer = new mcp_js_1.McpServer({
90
91
  name: "report_gen_mcp",
91
- version: "1.0.29",
92
+ version: "1.0.31",
92
93
  }, {
93
94
  // Disable health check to prevent automatic calls
94
95
  capabilities: {
@@ -117,7 +118,7 @@ if (process.argv.length === 2) {
117
118
  }),
118
119
  })).describe("Chart configurations mapped by ID"),
119
120
  outputFile: zod_1.z.string().optional().describe("Output HTML file path"),
120
- tempDirectory: zod_1.z.string().describe("Temporary directory for file storage (required to prevent read-only file system errors)"),
121
+ tempDirectory: zod_1.z.string().optional().describe("Temporary directory for file storage (optional, will use REPORTS_DIR environment variable if set)"),
121
122
  },
122
123
  }, async (params) => {
123
124
  // Handle case where arguments might be sent as a JSON string by Claude desktop
@@ -133,12 +134,29 @@ if (process.argv.length === 2) {
133
134
  else if (params.arguments && typeof params.arguments === 'object') {
134
135
  processedParams = params.arguments;
135
136
  }
136
- // Check if tempDirectory parameter is provided
137
- if (!processedParams.tempDirectory) {
138
- throw new Error('tempDirectory parameter is required. Please provide the directory where reports should be generated.');
139
- }
140
137
  const { document, charts, outputFile = 'report.html', tempDirectory } = processedParams;
141
- const outputPath = path_1.default.resolve(tempDirectory, outputFile);
138
+ // Determine the output directory:
139
+ // 1. Use REPORTS_DIR environment variable if set
140
+ // 2. Fall back to tempDirectory parameter if provided
141
+ // 3. Default to system temp directory if neither is available
142
+ let outputDir;
143
+ if (process.env.REPORTS_DIR) {
144
+ outputDir = process.env.REPORTS_DIR;
145
+ // Ensure the reports directory exists
146
+ try {
147
+ fs_extra_1.default.ensureDirSync(outputDir);
148
+ }
149
+ catch (error) {
150
+ throw new Error(`Cannot create or access the reports directory: ${outputDir}`);
151
+ }
152
+ }
153
+ else if (tempDirectory) {
154
+ outputDir = tempDirectory;
155
+ }
156
+ else {
157
+ outputDir = os_1.default.tmpdir();
158
+ }
159
+ const outputPath = path_1.default.resolve(outputDir, outputFile);
142
160
  try {
143
161
  const result = await (0, reportGenerator_1.generateReport)(document, charts, outputPath);
144
162
  // Properly encode the file path for URL
@@ -1,164 +1,139 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Final verification test for report_gen_mcp v1.0.23
4
- // This test verifies that the tempDirectory parameter is properly handled
5
-
6
3
  const { spawn } = require('child_process');
7
4
  const fs = require('fs');
8
5
  const path = require('path');
9
6
 
10
- console.log('๐Ÿ” Final Verification Test for report_gen_mcp v1.0.23');
11
- console.log('=====================================================\n');
12
-
13
- // Test 1: Verify the tool works with tempDirectory parameter
14
- console.log('๐Ÿงช Test 1: Testing with tempDirectory parameter...');
15
- const testWithTempDir = spawn('npx', ['@vint.tri/report_gen_mcp@1.0.23'], {
16
- stdio: ['pipe', 'pipe', 'pipe'],
7
+ console.log('=== Final Verification Test ===\n');
8
+
9
+ // Test 1: CLI mode with REPORTS_DIR
10
+ console.log('Test 1: CLI mode with REPORTS_DIR environment variable...');
11
+ const testReportsDir = path.join(__dirname, 'test-reports');
12
+ if (!fs.existsSync(testReportsDir)) {
13
+ fs.mkdirSync(testReportsDir);
14
+ }
15
+
16
+ const cliTest = spawn('node', [
17
+ 'dist/index.js',
18
+ 'generate',
19
+ '--document', '# CLI Test Report\n\nThis is a test report with a [[chart:cli]] chart.',
20
+ '--charts', JSON.stringify({
21
+ cli: {
22
+ type: "bar",
23
+ config: {
24
+ labels: ["X", "Y", "Z"],
25
+ datasets: [{
26
+ label: "CLI Data",
27
+ data: [10, 20, 30],
28
+ backgroundColor: ["red", "green", "blue"]
29
+ }]
30
+ }
31
+ }
32
+ }),
33
+ '--output', 'cli-test-report.html'
34
+ ], {
35
+ env: {
36
+ ...process.env,
37
+ REPORTS_DIR: testReportsDir
38
+ }
17
39
  });
18
40
 
19
- let test1Output = '';
20
-
21
- testWithTempDir.stdout.on('data', (data) => {
22
- test1Output += data.toString();
41
+ cliTest.stdout.on('data', (data) => {
42
+ console.log('CLI stdout:', data.toString());
23
43
  });
24
44
 
25
- testWithTempDir.stderr.on('data', (data) => {
26
- test1Output += data.toString();
45
+ cliTest.stderr.on('data', (data) => {
46
+ console.log('CLI stderr:', data.toString());
27
47
  });
28
48
 
29
- testWithTempDir.on('close', (code) => {
30
- console.log(`Test 1 exited with code ${code}`);
31
- console.log('Output:');
32
- console.log(test1Output);
33
-
34
- // Send a generate-report request with tempDirectory
35
- const testRequest = {
36
- method: "generate-report",
37
- params: {
38
- document: "# Test Report\n\nThis is a test report with tempDirectory.\n\n[[chart:testChart]]",
39
- charts: {
40
- testChart: {
41
- type: "bar",
42
- config: {
43
- labels: ["A", "B", "C"],
44
- datasets: [
45
- {
46
- label: "Test Data",
47
- data: [1, 2, 3],
48
- backgroundColor: ["red", "green", "blue"]
49
- }
50
- ],
51
- options: {
52
- title: "Test Chart"
53
- }
54
- }
55
- }
56
- },
57
- outputFile: "test-report.html",
58
- tempDirectory: "/tmp"
49
+ cliTest.on('close', (code) => {
50
+ console.log('CLI test exited with code:', code);
51
+
52
+ const expectedReportPath = path.join(testReportsDir, 'cli-test-report.html');
53
+ if (fs.existsSync(expectedReportPath)) {
54
+ console.log('โœ… CLI Test PASSED: Report generated in correct directory\n');
55
+ } else {
56
+ console.log('โŒ CLI Test FAILED: Report not found in expected directory\n');
57
+ }
58
+
59
+ // Clean up
60
+ if (fs.existsSync(testReportsDir)) {
61
+ fs.rmSync(testReportsDir, { recursive: true, force: true });
62
+ }
63
+
64
+ // Test 2: CLI mode without REPORTS_DIR (should fail)
65
+ console.log('Test 2: CLI mode without REPORTS_DIR environment variable (should fail)...');
66
+ const cliErrorTest = spawn('node', [
67
+ 'dist/index.js',
68
+ 'generate',
69
+ '--document', '# Error Test Report',
70
+ '--charts', JSON.stringify({}),
71
+ '--output', 'error-test-report.html'
72
+ ], {
73
+ env: {
74
+ ...process.env,
75
+ REPORTS_DIR: ''
59
76
  }
60
- };
61
-
62
- console.log('\n๐Ÿ“ Sending test request with tempDirectory...');
63
- console.log(JSON.stringify(testRequest, null, 2));
64
-
65
- const testProcess = spawn('npx', ['@vint.tri/report_gen_mcp@1.0.23'], {
66
- stdio: ['pipe', 'pipe', 'pipe'],
67
77
  });
68
78
 
69
- let testOutput = '';
70
-
71
- testProcess.stdout.on('data', (data) => {
72
- testOutput += data.toString();
79
+ cliErrorTest.stdout.on('data', (data) => {
80
+ console.log('CLI Error stdout:', data.toString());
73
81
  });
74
82
 
75
- testProcess.stderr.on('data', (data) => {
76
- testOutput += data.toString();
83
+ cliErrorTest.stderr.on('data', (data) => {
84
+ console.log('CLI Error stderr:', data.toString());
77
85
  });
78
86
 
79
- testProcess.stdin.write(JSON.stringify(testRequest));
80
- testProcess.stdin.end();
81
-
82
- testProcess.on('close', (code) => {
83
- console.log(`\nโœ… Test completed with code ${code}`);
84
- console.log('Full output:');
85
- console.log(testOutput);
86
-
87
- // Try to parse the response
88
- try {
89
- const lines = testOutput.split('\n').filter(line => line.trim());
90
- const lastLine = lines[lines.length - 1];
91
- const response = JSON.parse(lastLine);
92
-
93
- if (response.success) {
94
- console.log('๐ŸŽ‰ SUCCESS: Report generated successfully!');
95
- console.log(`๐Ÿ“ File path: ${response.filePath}`);
96
-
97
- // Test 2: Verify the file exists and get-report-url works
98
- console.log('\n๐Ÿงช Test 2: Testing get-report-url...');
99
- const urlRequest = {
100
- method: "get-report-url",
101
- params: {
102
- filePath: response.filePath
103
- }
104
- };
105
-
106
- const urlProcess = spawn('npx', ['@vint.tri/report_gen_mcp@1.0.23'], {
107
- stdio: ['pipe', 'pipe', 'pipe'],
108
- });
109
-
110
- let urlOutput = '';
111
-
112
- urlProcess.stdout.on('data', (data) => {
113
- urlOutput += data.toString();
114
- });
115
-
116
- urlProcess.stderr.on('data', (data) => {
117
- urlOutput += data.toString();
118
- });
119
-
120
- urlProcess.stdin.write(JSON.stringify(urlRequest));
121
- urlProcess.stdin.end();
122
-
123
- urlProcess.on('close', (code) => {
124
- console.log(`\nโœ… URL test completed with code ${code}`);
125
- console.log('Full output:');
126
- console.log(urlOutput);
127
-
128
- try {
129
- const urlLines = urlOutput.split('\n').filter(line => line.trim());
130
- const urlLastLine = urlLines[urlLines.length - 1];
131
- const urlResponse = JSON.parse(urlLastLine);
132
-
133
- if (urlResponse.success) {
134
- console.log('๐ŸŽ‰ SUCCESS: get-report-url works correctly!');
135
- console.log(`๐Ÿ”— File URL: ${urlResponse.fileUrl}`);
136
- console.log('\n๐Ÿ† ALL TESTS PASSED! The fix is working correctly.');
137
- console.log('๐Ÿ“‹ Summary:');
138
- console.log(' - tempDirectory parameter is properly handled');
139
- console.log(' - Reports are generated successfully');
140
- console.log(' - File URLs are returned correctly');
141
- console.log(' - Version 1.0.23 is working as expected');
142
- } else {
143
- console.log('โŒ FAILED: get-report-url did not succeed');
144
- }
145
- } catch (e) {
146
- console.log('โŒ ERROR: Could not parse URL response');
147
- console.error(e);
148
- }
149
- });
150
- } else {
151
- console.log('โŒ FAILED: Report generation was not successful');
152
- console.log(response.message || 'Unknown error');
153
- }
154
- } catch (e) {
155
- console.log('โš ๏ธ WARNING: Could not parse response, but checking for success indicators...');
156
- if (testOutput.includes('success') && testOutput.includes('filePath')) {
157
- console.log('๐ŸŽ‰ SUCCESS: Found success indicators in output!');
87
+ cliErrorTest.on('close', (code) => {
88
+ console.log('CLI error test exited with code:', code);
89
+
90
+ if (code !== 0) {
91
+ console.log('โœ… CLI Error Test PASSED: Correctly failed without REPORTS_DIR\n');
92
+ } else {
93
+ console.log('โŒ CLI Error Test FAILED: Should have failed without REPORTS_DIR\n');
94
+ }
95
+
96
+ // Test 3: Stdio mode (should work without REPORTS_DIR)
97
+ console.log('Test 3: Stdio mode (should work without REPORTS_DIR)...');
98
+ const stdioTest = spawn('node', ['dist/index.js'], {
99
+ env: process.env
100
+ });
101
+
102
+ // Send a simple MCP request
103
+ const mcpRequest = {
104
+ "jsonrpc": "2.0",
105
+ "id": 1,
106
+ "method": "tools/list",
107
+ "params": {}
108
+ };
109
+
110
+ stdioTest.stdin.write(JSON.stringify(mcpRequest) + '\n');
111
+
112
+ let stdioOutput = '';
113
+ stdioTest.stdout.on('data', (data) => {
114
+ stdioOutput += data.toString();
115
+ });
116
+
117
+ stdioTest.stderr.on('data', (data) => {
118
+ console.log('Stdio stderr:', data.toString());
119
+ });
120
+
121
+ stdioTest.on('close', (code) => {
122
+ console.log('Stdio test exited with code:', code);
123
+ console.log('Stdio output:', stdioOutput);
124
+
125
+ if (stdioOutput.includes('"tools"') || stdioOutput.includes('MCP server is running')) {
126
+ console.log('โœ… Stdio Test PASSED: Stdio mode is working\n');
158
127
  } else {
159
- console.log('โŒ FAILED: No clear success indicators found');
160
- console.error(e);
128
+ console.log('โŒ Stdio Test FAILED: Stdio mode not working correctly\n');
161
129
  }
162
- }
130
+
131
+ console.log('=== All Tests Completed ===');
132
+ });
133
+
134
+ // Give it a moment then close stdin
135
+ setTimeout(() => {
136
+ stdioTest.stdin.end();
137
+ }, 1000);
163
138
  });
164
139
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vint.tri/report_gen_mcp",
3
- "version": "1.0.30",
3
+ "version": "1.0.31",
4
4
  "description": "CLI tool for generating HTML reports with embedded charts",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/index.ts CHANGED
@@ -94,7 +94,7 @@ if (process.argv.length === 2) {
94
94
  // No command specified, run in stdio mode using MCP SDK
95
95
  const mcpServer = new McpServer({
96
96
  name: "report_gen_mcp",
97
- version: "1.0.29",
97
+ version: "1.0.31",
98
98
  }, {
99
99
  // Disable health check to prevent automatic calls
100
100
  capabilities: {
@@ -124,7 +124,7 @@ if (process.argv.length === 2) {
124
124
  }),
125
125
  })).describe("Chart configurations mapped by ID"),
126
126
  outputFile: z.string().optional().describe("Output HTML file path"),
127
- tempDirectory: z.string().describe("Temporary directory for file storage (required to prevent read-only file system errors)"),
127
+ tempDirectory: z.string().optional().describe("Temporary directory for file storage (optional, will use REPORTS_DIR environment variable if set)"),
128
128
  },
129
129
  }, async (params: any) => {
130
130
  // Handle case where arguments might be sent as a JSON string by Claude desktop
@@ -139,13 +139,28 @@ if (process.argv.length === 2) {
139
139
  processedParams = params.arguments;
140
140
  }
141
141
 
142
- // Check if tempDirectory parameter is provided
143
- if (!processedParams.tempDirectory) {
144
- throw new Error('tempDirectory parameter is required. Please provide the directory where reports should be generated.');
142
+ const { document, charts, outputFile = 'report.html', tempDirectory } = processedParams;
143
+
144
+ // Determine the output directory:
145
+ // 1. Use REPORTS_DIR environment variable if set
146
+ // 2. Fall back to tempDirectory parameter if provided
147
+ // 3. Default to system temp directory if neither is available
148
+ let outputDir: string;
149
+ if (process.env.REPORTS_DIR) {
150
+ outputDir = process.env.REPORTS_DIR;
151
+ // Ensure the reports directory exists
152
+ try {
153
+ fs.ensureDirSync(outputDir);
154
+ } catch (error) {
155
+ throw new Error(`Cannot create or access the reports directory: ${outputDir}`);
156
+ }
157
+ } else if (tempDirectory) {
158
+ outputDir = tempDirectory;
159
+ } else {
160
+ outputDir = os.tmpdir();
145
161
  }
146
162
 
147
- const { document, charts, outputFile = 'report.html', tempDirectory } = processedParams;
148
- const outputPath = path.resolve(tempDirectory, outputFile);
163
+ const outputPath = path.resolve(outputDir, outputFile);
149
164
 
150
165
  try {
151
166
  const result = await generateReport(document, charts, outputPath);