@vint.tri/report_gen_mcp 1.5.17 → 1.5.18

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.d.ts CHANGED
@@ -1,19 +1,3 @@
1
1
  #!/usr/bin/env node
2
- /**
3
- * Generate an image from a text prompt using AI
4
- * @param prompt Text prompt for image generation (must be in English)
5
- * @param options Additional options for image generation
6
- * @returns Promise<{ filePath: string, fileUrl: string }> Object containing file path and URL of the saved image
7
- */
8
- export declare function generateImage(prompt: string, options?: {
9
- width?: number;
10
- height?: number;
11
- guidance_scale?: number;
12
- negative_prompt?: string;
13
- num_inference_steps?: number;
14
- seed?: number;
15
- }): Promise<{
16
- filePath: string;
17
- fileUrl: string;
18
- }>;
2
+ export {};
19
3
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AA+fA;;;;;GAKG;AACH,wBAAsB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;IAC5D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAgCjD"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js CHANGED
@@ -4,12 +4,10 @@ import { program } from 'commander';
4
4
  import { generateReport } from './utils/reportGenerator.js';
5
5
  import path from 'path';
6
6
  import fs from 'fs-extra';
7
- import os from 'os';
8
7
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
8
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
- import { z } from 'zod';
11
9
  import { pathToFileURL } from 'url';
12
- import { ImageGenerator } from './mcp/imageGenerationServer.js';
10
+ import { simpleReportTool } from './tools/simpleReport.js';
13
11
  // Check if we're running in stdio mode (no command-line arguments)
14
12
  const isStdioMode = process.argv.length === 2;
15
13
  // For CLI and HTTP API modes, check for mandatory REPORTS_DIR environment variable
@@ -103,339 +101,17 @@ if (process.argv.length === 2) {
103
101
  // No command specified, run in stdio mode using MCP SDK
104
102
  const mcpServer = new McpServer({
105
103
  name: "report_gen_mcp",
106
- version: "1.5.17"
104
+ version: "1.5.18"
107
105
  }, {
108
106
  // Disable health check to prevent automatic calls
109
107
  capabilities: {
110
108
  tools: {}
111
109
  }
112
110
  });
113
- // Register the generate-report tool
114
- mcpServer.registerTool("generate-report", {
115
- description: "Generate an HTML report with embedded charts",
116
- inputSchema: {
117
- document: z.string().describe("Markdown document with element placeholders [[chart:id]] or [[image:id]]"),
118
- elements: z.record(z.union([
119
- z.object({
120
- type: z.enum(["bar", "line", "pie", "doughnut", "radar", "polarArea"]),
121
- config: z.object({
122
- labels: z.array(z.string()),
123
- datasets: z.array(z.object({
124
- label: z.string().optional(),
125
- data: z.array(z.number()),
126
- backgroundColor: z.array(z.string()).optional(),
127
- borderColor: z.array(z.string()).optional(),
128
- fill: z.boolean().optional(),
129
- })),
130
- options: z.object({
131
- title: z.string().optional(),
132
- }).optional(),
133
- }),
134
- }).describe("Chart configuration"),
135
- z.object({
136
- type: z.literal("pollinations"),
137
- config: z.object({
138
- prompt: z.string().describe("Text description of the image to generate"),
139
- width: z.number().optional().default(512).describe("Width of the image in pixels"),
140
- height: z.number().optional().default(512).describe("Height of the image in pixels"),
141
- model: z.string().optional().default("flux").describe("Model to use for image generation"),
142
- seed: z.number().optional().describe("Seed for reproducible image generation"),
143
- nologo: z.boolean().optional().default(true).describe("Remove logo from the image"),
144
- enhance: z.boolean().optional().default(true).describe("Enhance image quality"),
145
- }),
146
- }).describe("Pollinations.ai generated image configuration"),
147
- z.object({
148
- type: z.literal("url"),
149
- config: z.object({
150
- url: z.string().url().describe("URL of the image"),
151
- alt: z.string().optional().describe("Alternative text for the image"),
152
- width: z.number().optional().describe("Width of the image in pixels"),
153
- height: z.number().optional().describe("Height of the image in pixels"),
154
- }),
155
- }).describe("Image from URL configuration"),
156
- z.object({
157
- type: z.literal("image"),
158
- config: z.object({
159
- url: z.string().url().describe("File URL of the image"),
160
- alt: z.string().optional().describe("Alternative text for the image"),
161
- width: z.number().optional().describe("Width of the image in pixels"),
162
- height: z.number().optional().describe("Height of the image in pixels"),
163
- }),
164
- }).describe("Local image file configuration"),
165
- ])).describe("Report elements (charts and images) mapped by ID"),
166
- outputFile: z.string().optional().describe("Output HTML file path"),
167
- tempDirectory: z.string().optional().describe("Temporary directory for file storage (optional, will use REPORTS_DIR environment variable if set)"),
168
- },
169
- }, async (params) => {
170
- // Handle case where arguments might be sent as a JSON string by Claude desktop
171
- let processedParams = params;
172
- if (typeof params === 'string') {
173
- try {
174
- processedParams = JSON.parse(params);
175
- }
176
- catch (parseError) {
177
- throw new Error('Invalid JSON string in arguments');
178
- }
179
- }
180
- if (processedParams.arguments && typeof processedParams.arguments === 'string') {
181
- try {
182
- processedParams = JSON.parse(processedParams.arguments);
183
- }
184
- catch (parseError) {
185
- throw new Error('Invalid JSON string in arguments');
186
- }
187
- }
188
- else if (processedParams.arguments && typeof processedParams.arguments === 'object') {
189
- processedParams = processedParams.arguments;
190
- }
191
- // Extract parameters correctly, ensuring outputFile is not nested within elements
192
- const { document, elements, charts, outputFile = 'report.html', tempDirectory } = processedParams;
193
- // Поддержка обратной совместимости: если переданы charts, используем их как elements
194
- const reportElements = elements || charts || {};
195
- // Determine the output directory:
196
- // 1. Use REPORTS_DIR environment variable if set
197
- // 2. Fall back to tempDirectory parameter if provided
198
- // 3. Default to system temp directory if neither is available
199
- let outputDir;
200
- if (process.env.REPORTS_DIR) {
201
- outputDir = process.env.REPORTS_DIR;
202
- // Ensure the reports directory exists
203
- try {
204
- fs.ensureDirSync(outputDir);
205
- }
206
- catch (error) {
207
- throw new Error(`Cannot create or access the reports directory: ${outputDir}`);
208
- }
209
- }
210
- else if (tempDirectory) {
211
- outputDir = tempDirectory;
212
- }
213
- else {
214
- outputDir = os.tmpdir();
215
- }
216
- const outputPath = path.resolve(outputDir, outputFile);
217
- try {
218
- const result = await generateReport(document, reportElements, outputPath);
219
- // Generate proper file URL
220
- const fileUrl = pathToFileURL(outputPath).href;
221
- // Read the file content
222
- const fileContent = await fs.readFile(outputPath, 'utf8');
223
- // Create a comprehensive result object
224
- const comprehensiveResult = {
225
- success: true,
226
- message: "Report generated successfully",
227
- filePath: outputPath,
228
- fileUrl: fileUrl,
229
- fileContent: fileContent
230
- };
231
- // Return comprehensive information for neural network to use
232
- // Neural network should present to user: file path, web link, and file content
233
- return {
234
- content: [
235
- {
236
- type: "text",
237
- text: `Report generated successfully.
238
-
239
- FOR THE NEURAL NETWORK: Please present the following information to the user:
240
- 1. Path to file: ${outputPath}
241
- 2. Web browser link: ${fileUrl}
242
- 3. Web link 2: http://localhost:3000/${outputFile}
243
- 4. File content:
244
- ${fileContent}`
245
- }
246
- ]
247
- };
248
- }
249
- catch (error) {
250
- throw error;
251
- }
252
- });
253
- // Register a new tool for editing existing reports
254
- mcpServer.registerTool("edit-report", {
255
- description: "Edit an existing HTML report by adding or removing content",
256
- inputSchema: {
257
- filePath: z.string().describe("Path to the existing HTML report file"),
258
- operation: z.enum(["add", "remove", "replace"]).describe("Operation to perform: add content, remove content, or replace content"),
259
- contentToAdd: z.string().optional().describe("Content to add to the report (for 'add' operation)"),
260
- selector: z.string().optional().describe("CSS selector for element to modify (for 'add', 'remove', or 'replace' operations)"),
261
- contentToReplace: z.string().optional().describe("Content to replace the selected element with (for 'replace' operation)"),
262
- position: z.enum(["beforebegin", "afterbegin", "beforeend", "afterend"]).optional().describe("Position to insert new content relative to the selected element (for 'add' operation)"),
263
- },
264
- }, async (params) => {
265
- // Handle case where arguments might be sent as a JSON string
266
- let processedParams = params;
267
- if (typeof params === 'string') {
268
- try {
269
- processedParams = JSON.parse(params);
270
- }
271
- catch (parseError) {
272
- throw new Error('Invalid JSON string in arguments');
273
- }
274
- }
275
- else if (params.arguments && typeof params.arguments === 'object') {
276
- processedParams = params.arguments;
277
- }
278
- const { filePath, operation, contentToAdd, selector, contentToReplace, position } = processedParams;
279
- try {
280
- // Check if file exists
281
- if (!await fs.pathExists(filePath)) {
282
- throw new Error(`File not found: ${filePath}`);
283
- }
284
- // Read the existing file content
285
- let fileContent = await fs.readFile(filePath, 'utf8');
286
- // Perform the requested operation
287
- switch (operation) {
288
- case "add":
289
- if (!contentToAdd || !selector || !position) {
290
- throw new Error("contentToAdd, selector, and position are required for 'add' operation");
291
- }
292
- // Insert content at the specified position relative to the selected element
293
- const addRegex = new RegExp(`(<${selector}[^>]*>)|(<\\/[^>]*${selector}>)`, 'i');
294
- const addMatch = fileContent.match(addRegex);
295
- if (addMatch) {
296
- const matchIndex = addMatch.index;
297
- const matchLength = addMatch[0].length;
298
- switch (position) {
299
- case "beforebegin":
300
- fileContent = fileContent.slice(0, matchIndex) + contentToAdd + fileContent.slice(matchIndex);
301
- break;
302
- case "afterbegin":
303
- fileContent = fileContent.slice(0, matchIndex + matchLength) + contentToAdd + fileContent.slice(matchIndex + matchLength);
304
- break;
305
- case "beforeend":
306
- const closingTagIndex = fileContent.indexOf('</', matchIndex);
307
- fileContent = fileContent.slice(0, closingTagIndex) + contentToAdd + fileContent.slice(closingTagIndex);
308
- break;
309
- case "afterend":
310
- const endTagIndex = fileContent.indexOf('>', matchIndex) + 1;
311
- fileContent = fileContent.slice(0, endTagIndex) + contentToAdd + fileContent.slice(endTagIndex);
312
- break;
313
- }
314
- }
315
- else {
316
- throw new Error(`Element with selector '${selector}' not found`);
317
- }
318
- break;
319
- case "remove":
320
- if (!selector) {
321
- throw new Error("selector is required for 'remove' operation");
322
- }
323
- // Remove the element with the specified selector
324
- const removeRegex = new RegExp(`<${selector}[^>]*>[^]*?<\\/[^>]*${selector}[^>]*>|<${selector}[^>]*/?>`, 'gi');
325
- fileContent = fileContent.replace(removeRegex, '');
326
- break;
327
- case "replace":
328
- if (!selector || !contentToReplace) {
329
- throw new Error("selector and contentToReplace are required for 'replace' operation");
330
- }
331
- // Replace the element with the specified selector
332
- const replaceRegex = new RegExp(`<${selector}[^>]*>[^]*?<\\/[^>]*${selector}[^>]*>|<${selector}[^>]*/?>`, 'gi');
333
- fileContent = fileContent.replace(replaceRegex, contentToReplace);
334
- break;
335
- default:
336
- throw new Error(`Unsupported operation: ${operation}`);
337
- }
338
- // Write the modified content back to the file
339
- await fs.writeFile(filePath, fileContent, 'utf8');
340
- // Generate proper file URL
341
- const fileUrl = pathToFileURL(filePath).href;
342
- return {
343
- content: [
344
- {
345
- type: "text",
346
- text: `Report edited successfully.
347
-
348
- FOR THE NEURAL NETWORK: Please present the following information to the user:
349
- 1. Path to file: ${filePath}
350
- 2. Web browser link: ${fileUrl}
351
- 3. Operation performed: ${operation}`
352
- }
353
- ]
354
- };
355
- }
356
- catch (error) {
357
- throw new Error(`Error editing report: ${error.message}`);
358
- }
359
- });
360
- // Register the generate-image tool
361
- mcpServer.registerTool("generate-image", {
362
- description: "Generate an image from a text prompt using AI",
363
- inputSchema: {
364
- prompt: z.string().describe("Text prompt for image generation (must be in English)"),
365
- width: z.number().optional().describe("Width of the image (128-2048 pixels)"),
366
- height: z.number().optional().describe("Height of the image (128-2048 pixels)"),
367
- guidance_scale: z.number().optional().describe("Strength of prompt following (1.0-20.0)"),
368
- negative_prompt: z.string().optional().describe("Negative prompt (what NOT to include in the image)"),
369
- num_inference_steps: z.number().optional().describe("Number of generation steps (1-50)"),
370
- seed: z.number().optional().describe("Seed for reproducibility (0 = random)")
371
- },
372
- }, async (params) => {
373
- try {
374
- // Handle case where arguments might be sent as a JSON string
375
- let processedParams = params;
376
- if (typeof params === 'string') {
377
- try {
378
- processedParams = JSON.parse(params);
379
- }
380
- catch (parseError) {
381
- throw new Error('Invalid JSON string in arguments');
382
- }
383
- }
384
- else if (params.arguments && typeof params.arguments === 'object') {
385
- processedParams = params.arguments;
386
- }
387
- const { prompt, width, height, guidance_scale, negative_prompt, num_inference_steps, seed } = processedParams;
388
- if (!prompt) {
389
- throw new Error("Parameter 'prompt' is required");
390
- }
391
- // Prepare options for generateImage function. Parameters are already numbers due to schema validation.
392
- const options = {};
393
- if (width !== undefined)
394
- options.width = width;
395
- if (height !== undefined)
396
- options.height = height;
397
- if (guidance_scale !== undefined)
398
- options.guidance_scale = guidance_scale;
399
- if (negative_prompt !== undefined)
400
- options.negative_prompt = negative_prompt;
401
- if (num_inference_steps !== undefined)
402
- options.num_inference_steps = num_inference_steps;
403
- if (seed !== undefined)
404
- options.seed = seed;
405
- // Generate the image
406
- const imageResult = await generateImage(prompt, options);
407
- // Extract base64 data from the saved file
408
- const imageData = await fs.readFile(imageResult.filePath);
409
- const base64Data = imageData.toString('base64');
410
- // Return file paths and URLs
411
- const reportServerPort = 2000;
412
- const httpUrl = `http://localhost:${reportServerPort}/${path.basename(imageResult.filePath)}`;
413
- return {
414
- content: [
415
- {
416
- type: "text",
417
- text: `Image generated successfully.
418
-
419
- FOR THE NEURAL NETWORK: Please present the following information to the user:
420
- 1. Path to file: ${imageResult.filePath}
421
- 2. Web browser link: ${imageResult.fileUrl}
422
- 3. Web link: ${httpUrl}`
423
- }
424
- ]
425
- };
426
- }
427
- catch (error) {
428
- // Return error as text content
429
- return {
430
- content: [
431
- {
432
- type: "text",
433
- text: `❌ Error generating image: ${error.message}`
434
- }
435
- ]
436
- };
437
- }
438
- });
111
+ mcpServer.registerTool(simpleReportTool.name, {
112
+ description: simpleReportTool.description,
113
+ inputSchema: simpleReportTool.inputSchema,
114
+ }, simpleReportTool.action);
439
115
  async function main() {
440
116
  const transport = new StdioServerTransport();
441
117
  await mcpServer.connect(transport);
@@ -450,47 +126,3 @@ else {
450
126
  // Run commander program when arguments are provided
451
127
  program.parse();
452
128
  }
453
- // Create a singleton instance of ImageGenerator for the generateImage function
454
- const imageGenerator = new ImageGenerator();
455
- // Start the report server in non-stdio mode as well
456
- if (!isStdioMode && reportsDir) {
457
- const reportServer = express();
458
- const reportServerPort = 2000;
459
- reportServer.use(express.static(reportsDir));
460
- reportServer.listen(reportServerPort, () => {
461
- console.log(`Report server running at http://localhost:${reportServerPort}`);
462
- });
463
- }
464
- /**
465
- * Generate an image from a text prompt using AI
466
- * @param prompt Text prompt for image generation (must be in English)
467
- * @param options Additional options for image generation
468
- * @returns Promise<{ filePath: string, fileUrl: string }> Object containing file path and URL of the saved image
469
- */
470
- export async function generateImage(prompt, options) {
471
- // Generate the image data URI
472
- const imageDataUri = await imageGenerator.generateImage(prompt, options);
473
- // Extract base64 data without prefix
474
- let base64Data = imageDataUri;
475
- if (imageDataUri.startsWith("data:image/jpeg;base64,")) {
476
- base64Data = imageDataUri.substring("data:image/jpeg;base64,".length);
477
- }
478
- // Save image to home folder
479
- const homeDir = os.homedir();
480
- const imagesDir = path.join(homeDir, 'generated_images');
481
- await fs.ensureDir(imagesDir);
482
- // Create unique filename
483
- const timestamp = Date.now();
484
- const filename = `generated-image-${timestamp}.jpeg`;
485
- const outputPath = path.join(imagesDir, filename);
486
- // Save image to file
487
- const imageBuffer = Buffer.from(base64Data, 'base64');
488
- await fs.writeFile(outputPath, imageBuffer);
489
- // Create file URL
490
- const fileUrl = pathToFileURL(outputPath).href;
491
- // Return both file path and URL
492
- return {
493
- filePath: outputPath,
494
- fileUrl: fileUrl
495
- };
496
- }
@@ -0,0 +1,19 @@
1
+ import { z } from 'zod';
2
+ export declare const simpleReportTool: {
3
+ name: string;
4
+ description: string;
5
+ inputSchema: {
6
+ document: z.ZodString;
7
+ outputFile: z.ZodOptional<z.ZodString>;
8
+ };
9
+ action: (params: any) => Promise<{
10
+ content: {
11
+ type: "resource";
12
+ resource: {
13
+ uri: string;
14
+ text: string;
15
+ };
16
+ }[];
17
+ }>;
18
+ };
19
+ //# sourceMappingURL=simpleReport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simpleReport.d.ts","sourceRoot":"","sources":["../../src/tools/simpleReport.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,eAAO,MAAM,gBAAgB;;;;;;;qBAOJ,GAAG;iBAwCG;YAAE,IAAI,EAAE,UAAU,CAAC;YAAC,QAAQ,EAAE;gBAAE,GAAG,EAAE,MAAM,CAAC;gBAAC,IAAI,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,EAAE;;CAa7F,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { generateReport } from '../utils/reportGenerator.js';
2
+ import { z } from 'zod';
3
+ import { pathToFileURL } from 'url';
4
+ import fs from 'fs-extra';
5
+ export const simpleReportTool = {
6
+ name: "generate-report",
7
+ description: "Generate an HTML report from a single string of Markdown content with embedded image and chart tags.",
8
+ inputSchema: {
9
+ document: z.string().describe("The full content of the report in Markdown format, with `<img>` and `<canvas>` tags for images and charts."),
10
+ outputFile: z.string().optional().describe("The name of the output HTML file."),
11
+ },
12
+ action: async (params) => {
13
+ let { document, outputFile } = params;
14
+ const elements = {};
15
+ // Regex to find canvas tags and extract id and data-chart
16
+ const canvasRegex = /<canvas\s+id="([^"]+)"\s+data-chart='([^']*)'><\/canvas>/g;
17
+ document = document.replace(canvasRegex, (match, id, chartConfigString) => {
18
+ try {
19
+ const chartConfig = JSON.parse(chartConfigString);
20
+ elements[id] = chartConfig;
21
+ return `[[chart:${id}]]`;
22
+ }
23
+ catch (error) {
24
+ console.error(`Error parsing chart config for id ${id}:`, error);
25
+ // Keep the original tag if parsing fails to avoid losing content
26
+ return match;
27
+ }
28
+ });
29
+ // Regex to find img tags and extract id and data-image
30
+ const imgRegex = /<img\s+id="([^"]+)"\s+data-image='([^']*)'\/?>/g;
31
+ document = document.replace(imgRegex, (match, id, imageConfigString) => {
32
+ try {
33
+ const imageConfig = JSON.parse(imageConfigString);
34
+ elements[id] = imageConfig;
35
+ return `[[image:${id}]]`;
36
+ }
37
+ catch (error) {
38
+ console.error(`Error parsing image config for id ${id}:`, error);
39
+ // Keep the original tag if parsing fails
40
+ return match;
41
+ }
42
+ });
43
+ if (!outputFile) {
44
+ outputFile = `report-${Date.now()}.html`;
45
+ }
46
+ const result = await generateReport(document, elements, outputFile);
47
+ const fileUrl = pathToFileURL(result.filePath).href;
48
+ const fileContent = await fs.readFile(result.filePath, 'utf8');
49
+ const response = {
50
+ content: [
51
+ {
52
+ type: 'resource',
53
+ resource: {
54
+ uri: fileUrl,
55
+ text: fileContent,
56
+ },
57
+ },
58
+ ],
59
+ };
60
+ return response;
61
+ },
62
+ };
@@ -0,0 +1,12 @@
1
+ export declare const testReportTool: {
2
+ name: string;
3
+ description: string;
4
+ inputSchema: {};
5
+ action: () => Promise<{
6
+ content: {
7
+ type: string;
8
+ text: string;
9
+ }[];
10
+ }>;
11
+ };
12
+ //# sourceMappingURL=testReport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"testReport.d.ts","sourceRoot":"","sources":["../../src/tools/testReport.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,cAAc;;;;;;;;;;CAyE1B,CAAC"}
@@ -0,0 +1,76 @@
1
+ import { generateReport } from '../utils/reportGenerator.js';
2
+ import { pathToFileURL } from 'url';
3
+ import fs from 'fs-extra';
4
+ export const testReportTool = {
5
+ name: "test-report",
6
+ description: "Generate a hardcoded test report to verify that the MCP server is working correctly.",
7
+ inputSchema: {},
8
+ action: async () => {
9
+ const reportContent = `# Test Report
10
+
11
+ This is a test report.
12
+
13
+ ## Image
14
+
15
+ <img src="https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" alt="Google Logo" />
16
+
17
+ ## Chart
18
+
19
+ <canvas id="myChart"></canvas>
20
+ <script>
21
+ const ctx = document.getElementById('myChart').getContext('2d');
22
+ new Chart(ctx, {
23
+ type: 'bar',
24
+ data: {
25
+ labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
26
+ datasets: [{
27
+ label: '# of Votes',
28
+ data: [12, 19, 3, 5, 2, 3],
29
+ backgroundColor: [
30
+ 'rgba(255, 99, 132, 0.2)',
31
+ 'rgba(54, 162, 235, 0.2)',
32
+ 'rgba(255, 206, 86, 0.2)',
33
+ 'rgba(75, 192, 192, 0.2)',
34
+ 'rgba(153, 102, 255, 0.2)',
35
+ 'rgba(255, 159, 64, 0.2)'
36
+ ],
37
+ borderColor: [
38
+ 'rgba(255, 99, 132, 1)',
39
+ 'rgba(54, 162, 235, 1)',
40
+ 'rgba(255, 206, 86, 1)',
41
+ 'rgba(75, 192, 192, 1)',
42
+ 'rgba(153, 102, 255, 1)',
43
+ 'rgba(255, 159, 64, 1)'
44
+ ],
45
+ borderWidth: 1
46
+ }]
47
+ },
48
+ options: {
49
+ scales: {
50
+ y: {
51
+ beginAtZero: true
52
+ }
53
+ }
54
+ }
55
+ });
56
+ </script>
57
+ `;
58
+ const result = await generateReport(reportContent, {}, "test-report.html");
59
+ const fileUrl = pathToFileURL(result.filePath).href;
60
+ const fileContent = await fs.readFile(result.filePath, 'utf8');
61
+ return {
62
+ content: [
63
+ {
64
+ type: "text",
65
+ text: `Test report generated successfully.
66
+
67
+ FOR THE NEURAL NETWORK: Please present the following information to the user:
68
+ 1. Path to file: ${result.filePath}
69
+ 2. Web browser link: ${fileUrl}
70
+ 3. File content:
71
+ ${fileContent}`
72
+ }
73
+ ]
74
+ };
75
+ },
76
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vint.tri/report_gen_mcp",
3
- "version": "1.5.17",
3
+ "version": "1.5.18",
4
4
  "description": "CLI tool for generating HTML reports with embedded charts and images",
5
5
  "main": "dist/index.js",
6
6
  "bin": {