@vint.tri/report_gen_mcp 1.3.3 → 1.3.5

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.
@@ -37,7 +37,8 @@
37
37
  Обязательно покажите пользователю содержимое файла, чтобы он мог сразу ознакомиться с результатом без необходимости открывать файл отдельно.
38
38
 
39
39
  **ВАЖНО ПО ФОРМАТИРОВАНИЮ ОТЧЕТОВ:**
40
- - Все диаграммы автоматически создаются с разумными размерами (примерно 267x200 пикселей) для лучшего визуального восприятия
40
+ - Все диаграммы автоматически создаются с адекватными размерами (примерно 400x300 пикселей) для лучшего визуального восприятия и пропорциональности в отчете
41
+ - Диаграммы автоматически оборачиваются в контейнеры с CSS классами для обеспечения правильного масштабирования и отступов
41
42
  - Текст в отчетах автоматически форматируется с использованием HTML-разметки для улучшения читаемости
42
43
  - Отчеты имеют профессиональный внешний вид с улучшенным стилем, включая:
43
44
  * Четкую типографику с выравниванием текста по ширине
@@ -29,7 +29,8 @@
29
29
  Обязательно покажите пользователю содержимое файла, чтобы он мог сразу ознакомиться с результатом без необходимости открывать файл отдельно.
30
30
 
31
31
  **ВАЖНО ПО ФОРМАТИРОВАНИЮ ОТЧЕТОВ:**
32
- - Все диаграммы автоматически создаются с разумными размерами (примерно 267x200 пикселей) для лучшего визуального восприятия
32
+ - Все диаграммы автоматически создаются с адекватными размерами (примерно 400x300 пикселей) для лучшего визуального восприятия и пропорциональности в отчете
33
+ - Диаграммы автоматически оборачиваются в контейнеры с CSS классами для обеспечения правильного масштабирования и отступов
33
34
  - Текст в отчетах автоматически форматируется с использованием HTML-разметки для улучшения читаемости
34
35
  - Отчеты имеют профессиональный внешний вид с улучшенным стилем, включая:
35
36
  * Четкую типографику с выравниванием текста по ширине
@@ -1,30 +1,26 @@
1
- # Публикация версии 1.3.0
1
+ # Publication Confirmation - Version 1.3.4
2
2
 
3
- Версия 1.3.0 пакета @vint.tri/report_gen_mcp успешно опубликована в npm registry.
3
+ The @vint.tri/report_gen_mcp package has been successfully published to npm as version 1.3.4.
4
4
 
5
- ## Что было сделано:
5
+ ## Changes in Version 1.3.4
6
6
 
7
- 1. Обновлена версия в package.json с 1.2.2 до 1.3.0
8
- 2. Обновлена версия в src/index.ts с 1.2.1 до 1.3.0
9
- 3. Обновлена версия в dist/index.js с 1.2.1 до 1.3.0
10
- 4. Обновлены упоминания версий в README.md
11
- 5. Выполнена сборка проекта
12
- 6. Пакет успешно опубликован в npm registry
7
+ 1. **Fixed CSS Selector Issue**: Resolved the problem with the edit-report tool not working correctly with CSS selectors like `h2:nth-of-type(3)`
8
+ 2. **Added jsdom Dependency**: Integrated jsdom library for proper DOM manipulation and robust CSS selector support
9
+ 3. **Updated Edit-Report Implementation**: Refactored the edit-report tool to use jsdom's querySelector method instead of regex-based approach
10
+ 4. **Version Updates**: Updated both package.json and src/index.ts to reflect version 1.3.4
13
11
 
14
- ## Проверка:
12
+ ## Verification
15
13
 
16
- ```bash
17
- npm info @vint.tri/report_gen_mcp version
18
- # Вывод: 1.3.0
19
- ```
14
+ - ✅ Package successfully published to npm
15
+ - Version 1.3.4 is now the latest version on npm
16
+ - CSS selector functionality tested and working correctly
17
+ - ✅ All existing functionality preserved
20
18
 
21
- Теперь пользователи могут установить последнюю версию инструмента с помощью:
19
+ ## Testing
22
20
 
23
- ```bash
24
- npm install -g @vint.tri/report_gen_mcp@latest
25
- ```
21
+ The fix has been verified with a test script that confirms:
22
+ - CSS selectors like `h2:nth-of-type(3)` now work correctly
23
+ - Content can be successfully inserted at the correct positions in HTML documents
24
+ - The edit-report tool functions as expected with complex CSS selectors
26
25
 
27
- или использовать его напрямую через npx:
28
-
29
- ```bash
30
- REPORTS_DIR=./reports npx @vint.tri/report_gen_mcp@latest
26
+ Users can now successfully use CSS selectors with the edit-report tool to modify their HTML reports.
@@ -0,0 +1,57 @@
1
+ # Исправление проблемы с путем сохранения отчетов
2
+
3
+ ## Проблема
4
+
5
+ При генерации отчетов с помощью инструмента `report_gen_mcp` в Claude Desktop, файлы сохранялись в системной временной директории `/tmp/` вместо указанной пользователем директории. Это происходило потому, что переменная окружения `REPORTS_DIR` не была задана в конфигурации Claude Desktop.
6
+
7
+ ## Причина
8
+
9
+ В коде `src/index.ts` реализована следующая логика определения директории для сохранения отчетов в stdio режиме (Claude Desktop):
10
+
11
+ 1. Если задана переменная окружения `REPORTS_DIR` - используется она
12
+ 2. Иначе, если передан параметр `tempDirectory` - используется он
13
+ 3. В противном случае используется системная временная директория (`/tmp/` в Unix-подобных системах)
14
+
15
+ В конфигурации Claude Desktop отсутствовала секция `env` с переменной `REPORTS_DIR`, поэтому система использовала значение по умолчанию - `/tmp/`.
16
+
17
+ ## Решение
18
+
19
+ Добавлена секция `env` в конфигурацию Claude Desktop с переменной `REPORTS_DIR`, указывающей на желаемую директорию для сохранения отчетов:
20
+
21
+ ```json
22
+ {
23
+ "report_gen_mcp": {
24
+ "name": "report_gen_mcp",
25
+ "type": "stdio",
26
+ "isActive": true,
27
+ "registryUrl": "",
28
+ "longRunning": false,
29
+ "tags": [],
30
+ "command": "npx",
31
+ "env": {
32
+ "REPORTS_DIR": "./reports"
33
+ },
34
+ "args": [
35
+ "@vint.tri/report_gen_mcp@latest"
36
+ ]
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Результат
42
+
43
+ После применения исправления отчеты будут сохраняться в директории `./reports` относительно текущей рабочей директории, а не в `/tmp/`. Это позволяет пользователю легко находить и управлять своими отчетами.
44
+
45
+ ## Тестирование
46
+
47
+ Создан тестовый скрипт `test-report-path-fix.js`, который проверяет:
48
+ 1. Что отчеты сохраняются в правильной директории
49
+ 2. Что путь в результате совпадает с ожидаемым
50
+ 3. Что нейросеть может правильно обработать ответ и предоставить пользователю всю необходимую информацию
51
+
52
+ ## Рекомендации
53
+
54
+ Для избежания подобных проблем в будущем рекомендуется:
55
+ 1. Всегда указывать переменную `REPORTS_DIR` в конфигурации Claude Desktop
56
+ 2. Использовать относительные пути для лучшей переносимости между системами
57
+ 3. Регулярно тестировать конфигурацию инструментов Claude Desktop
@@ -37,7 +37,8 @@
37
37
  - Выбирайте подходящий тип диаграммы в зависимости от характера данных
38
38
  - Добавляйте поясняющие подписи к диаграммам
39
39
  - Используйте разнообразные цвета для лучшей визуализации
40
- - **ВАЖНО**: Все диаграммы автоматически создаются с разумными размерами (примерно 267x200 пикселей) для лучшего визуального восприятия
40
+ - **ВАЖНО**: Все диаграммы автоматически создаются с адекватными размерами (примерно 400x300 пикселей) для лучшего визуального восприятия и пропорциональности в отчете
41
+ - Диаграммы автоматически оборачиваются в контейнеры с CSS классами для обеспечения правильного масштабирования и отступов
41
42
 
42
43
  3. **Изображения**:
43
44
  - Добавляйте тематические изображения для иллюстрации контента
@@ -617,18 +618,18 @@
617
618
 
618
619
  1. **Ошибка формата параметров**: Передача `elements` как строки вместо объекта
619
620
  - ❌ Неправильно: `"elements": "{\"mychart\":{...}}"`
620
- - ✅ Правильно: `"elements": {"mychart":{...}}`
621
+ - ✅ Правильно: `"elements": {"mychart":{...}}"
621
622
 
622
623
  2. **Ошибка формата цвета**: Передача `borderColor` или `backgroundColor` как строк вместо массивов
623
624
  - ❌ Неправильно: `"borderColor": "red"`
624
- - ✅ Правильно: `"borderColor": ["red"]`
625
+ - ✅ Правильно: `"borderColor": ["red"]"
625
626
 
626
627
  3. **Ошибка формата данных**: Передача числовых данных как отдельных значений вместо массивов
627
- - ❌ Неправильно: `"data": 10`
628
+ - ❌ Неправильно: `"data": 10
628
629
  - ✅ Правильно: `"data": [10]`
629
630
 
630
631
  4. **Ошибка формата меток**: Передача меток как отдельных значений вместо массивов
631
- - ❌ Неправильно: `"labels": "Январь"`
632
+ - ❌ Неправильно: `"labels": "Январь"
632
633
  - ✅ Правильно: `"labels": ["Январь"]"
633
634
 
634
635
  ## Дополнительные рекомендации
@@ -0,0 +1,61 @@
1
+ # Версия 1.3.5 - Исправление пути сохранения отчетов
2
+
3
+ ## Изменения в версии 1.3.5
4
+
5
+ ### Исправления ошибок
6
+ - **Исправлена проблема с сохранением отчетов в неправильной директории**: Теперь отчеты сохраняются в директории, указанной в переменной окружения `REPORTS_DIR`, вместо системной временной директории `/tmp/`.
7
+ - **Обновлена конфигурация Claude Desktop**: Добавлена секция `env` с переменной `REPORTS_DIR` для правильного указания директории сохранения отчетов.
8
+
9
+ ### Улучшения
10
+ - **Обновлена версия пакета**: Версия пакета обновлена с 1.3.4 до 1.3.5 во всех соответствующих файлах (`package.json`, `src/index.ts`, `dist/index.js`).
11
+ - **Добавлена документация**: Создана подробная документация с объяснением проблемы и решения (`REPORT_PATH_FIX_EXPLANATION.md`).
12
+ - **Добавлен тест**: Создан тестовый скрипт для проверки правильности сохранения отчетов в указанной директории (`test-report-path-fix.js`).
13
+
14
+ ## Инструкции по обновлению
15
+
16
+ Для использования новой версии обновите пакет:
17
+
18
+ ```bash
19
+ npm install @vint.tri/report_gen_mcp@1.3.5
20
+ ```
21
+
22
+ Или используйте через npx:
23
+
24
+ ```bash
25
+ npx @vint.tri/report_gen_mcp@1.3.5
26
+ ```
27
+
28
+ ## Конфигурация Claude Desktop
29
+
30
+ Для правильной работы с Claude Desktop убедитесь, что ваша конфигурация содержит секцию `env` с переменной `REPORTS_DIR`:
31
+
32
+ ```json
33
+ {
34
+ "report_gen_mcp": {
35
+ "name": "report_gen_mcp",
36
+ "type": "stdio",
37
+ "isActive": true,
38
+ "registryUrl": "",
39
+ "longRunning": false,
40
+ "tags": [],
41
+ "command": "npx",
42
+ "env": {
43
+ "REPORTS_DIR": "./reports"
44
+ },
45
+ "args": [
46
+ "@vint.tri/report_gen_mcp@1.3.5"
47
+ ]
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## Тестирование
53
+
54
+ В новой версии добавлен тестовый скрипт `test-report-path-fix.js`, который проверяет:
55
+ 1. Что отчеты сохраняются в правильной директории
56
+ 2. Что путь в результате совпадает с ожидаемым
57
+ 3. Что нейросеть может правильно обработать ответ и предоставить пользователю всю необходимую информацию
58
+
59
+ ## Совместимость
60
+
61
+ Версия 1.3.5 полностью совместима с предыдущими версиями и не содержит критических изменений в API.
@@ -30,10 +30,10 @@ export async function renderBarChart(config) {
30
30
  } : undefined
31
31
  }
32
32
  };
33
- // Return interactive Chart.js HTML
33
+ // Return interactive Chart.js HTML with proper container
34
34
  return `
35
- <div>
36
- <canvas id="${chartId}" width="267" height="200"></canvas>
35
+ <div class="chart-container">
36
+ <canvas id="${chartId}" width="400" height="300"></canvas>
37
37
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
38
38
  <script>
39
39
  document.addEventListener('DOMContentLoaded', function() {
@@ -29,10 +29,10 @@ export async function renderDoughnutChart(config) {
29
29
  } : undefined
30
30
  }
31
31
  };
32
- // Return interactive Chart.js HTML
32
+ // Return interactive Chart.js HTML with proper container
33
33
  return `
34
- <div>
35
- <canvas id="${chartId}" width="267" height="200"></canvas>
34
+ <div class="chart-container">
35
+ <canvas id="${chartId}" width="400" height="300"></canvas>
36
36
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
37
37
  <script>
38
38
  document.addEventListener('DOMContentLoaded', function() {
@@ -30,10 +30,10 @@ export async function renderLineChart(config) {
30
30
  } : undefined
31
31
  }
32
32
  };
33
- // Return interactive Chart.js HTML
33
+ // Return interactive Chart.js HTML with proper container
34
34
  return `
35
- <div>
36
- <canvas id="${chartId}" width="267" height="200"></canvas>
35
+ <div class="chart-container">
36
+ <canvas id="${chartId}" width="400" height="300"></canvas>
37
37
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
38
38
  <script>
39
39
  document.addEventListener('DOMContentLoaded', function() {
@@ -29,10 +29,10 @@ export async function renderPieChart(config) {
29
29
  } : undefined
30
30
  }
31
31
  };
32
- // Return interactive Chart.js HTML
32
+ // Return interactive Chart.js HTML with proper container
33
33
  return `
34
- <div>
35
- <canvas id="${chartId}" width="267" height="200"></canvas>
34
+ <div class="chart-container">
35
+ <canvas id="${chartId}" width="400" height="300"></canvas>
36
36
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
37
37
  <script>
38
38
  document.addEventListener('DOMContentLoaded', function() {
@@ -29,10 +29,10 @@ export async function renderPolarAreaChart(config) {
29
29
  } : undefined
30
30
  }
31
31
  };
32
- // Return interactive Chart.js HTML
32
+ // Return interactive Chart.js HTML with proper container
33
33
  return `
34
- <div>
35
- <canvas id="${chartId}" width="267" height="200"></canvas>
34
+ <div class="chart-container">
35
+ <canvas id="${chartId}" width="400" height="300"></canvas>
36
36
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
37
37
  <script>
38
38
  document.addEventListener('DOMContentLoaded', function() {
@@ -30,10 +30,10 @@ export async function renderRadarChart(config) {
30
30
  } : undefined
31
31
  }
32
32
  };
33
- // Return interactive Chart.js HTML
33
+ // Return interactive Chart.js HTML with proper container
34
34
  return `
35
- <div>
36
- <canvas id="${chartId}" width="267" height="200"></canvas>
35
+ <div class="chart-container">
36
+ <canvas id="${chartId}" width="400" height="300"></canvas>
37
37
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
38
38
  <script>
39
39
  document.addEventListener('DOMContentLoaded', function() {
package/dist/index.js CHANGED
@@ -9,6 +9,7 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
9
9
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
10
  import { z } from 'zod';
11
11
  import { pathToFileURL } from 'url';
12
+ import { JSDOM } from 'jsdom';
12
13
  // Check if we're running in stdio mode (no command-line arguments)
13
14
  const isStdioMode = process.argv.length === 2;
14
15
  // For CLI and HTTP API modes, check for mandatory REPORTS_DIR environment variable
@@ -102,7 +103,7 @@ if (process.argv.length === 2) {
102
103
  // No command specified, run in stdio mode using MCP SDK
103
104
  const mcpServer = new McpServer({
104
105
  name: "report_gen_mcp",
105
- version: "1.3.3",
106
+ version: "1.3.5",
106
107
  }, {
107
108
  // Disable health check to prevent automatic calls
108
109
  capabilities: {
@@ -322,28 +323,29 @@ ${fileContent}`
322
323
  if (!contentToAdd || !selector || !position) {
323
324
  throw new Error("contentToAdd, selector, and position are required for 'add' operation");
324
325
  }
325
- // Insert content at the specified position relative to the selected element
326
- const addRegex = new RegExp(`(<${selector}[^>]*>)|(<\\/[^>]*${selector}>)`, 'i');
327
- const addMatch = fileContent.match(addRegex);
328
- if (addMatch) {
329
- const matchIndex = addMatch.index;
330
- const matchLength = addMatch[0].length;
326
+ // Use a more robust approach for finding elements with CSS selectors
327
+ const dom = new JSDOM(fileContent);
328
+ const document = dom.window.document;
329
+ // Find the element using querySelector
330
+ const element = document.querySelector(selector);
331
+ if (element) {
332
+ // Insert content at the specified position relative to the selected element
331
333
  switch (position) {
332
334
  case "beforebegin":
333
- fileContent = fileContent.slice(0, matchIndex) + contentToAdd + fileContent.slice(matchIndex);
335
+ element.insertAdjacentHTML('beforebegin', contentToAdd);
334
336
  break;
335
337
  case "afterbegin":
336
- fileContent = fileContent.slice(0, matchIndex + matchLength) + contentToAdd + fileContent.slice(matchIndex + matchLength);
338
+ element.insertAdjacentHTML('afterbegin', contentToAdd);
337
339
  break;
338
340
  case "beforeend":
339
- const closingTagIndex = fileContent.indexOf('</', matchIndex);
340
- fileContent = fileContent.slice(0, closingTagIndex) + contentToAdd + fileContent.slice(closingTagIndex);
341
+ element.insertAdjacentHTML('beforeend', contentToAdd);
341
342
  break;
342
343
  case "afterend":
343
- const endTagIndex = fileContent.indexOf('>', matchIndex) + 1;
344
- fileContent = fileContent.slice(0, endTagIndex) + contentToAdd + fileContent.slice(endTagIndex);
344
+ element.insertAdjacentHTML('afterend', contentToAdd);
345
345
  break;
346
346
  }
347
+ // Serialize the modified DOM back to HTML
348
+ fileContent = dom.serialize();
347
349
  }
348
350
  else {
349
351
  throw new Error(`Element with selector '${selector}' not found`);
@@ -353,17 +355,29 @@ ${fileContent}`
353
355
  if (!selector) {
354
356
  throw new Error("selector is required for 'remove' operation");
355
357
  }
356
- // Remove the element with the specified selector
357
- const removeRegex = new RegExp(`<${selector}[^>]*>[^]*?<\\/[^>]*${selector}[^>]*>|<${selector}[^>]*/?>`, 'gi');
358
- fileContent = fileContent.replace(removeRegex, '');
358
+ // Use a more robust approach for finding and removing elements
359
+ const domRemove = new JSDOM(fileContent);
360
+ const documentRemove = domRemove.window.document;
361
+ // Find and remove all elements matching the selector
362
+ const elementsToRemove = documentRemove.querySelectorAll(selector);
363
+ elementsToRemove.forEach((el) => el.remove());
364
+ // Serialize the modified DOM back to HTML
365
+ fileContent = domRemove.serialize();
359
366
  break;
360
367
  case "replace":
361
368
  if (!selector || !contentToReplace) {
362
369
  throw new Error("selector and contentToReplace are required for 'replace' operation");
363
370
  }
364
- // Replace the element with the specified selector
365
- const replaceRegex = new RegExp(`<${selector}[^>]*>[^]*?<\\/[^>]*${selector}[^>]*>|<${selector}[^>]*/?>`, 'gi');
366
- fileContent = fileContent.replace(replaceRegex, contentToReplace);
371
+ // Use a more robust approach for finding and replacing elements
372
+ const domReplace = new JSDOM(fileContent);
373
+ const documentReplace = domReplace.window.document;
374
+ // Find and replace all elements matching the selector
375
+ const elementsToReplace = documentReplace.querySelectorAll(selector);
376
+ elementsToReplace.forEach((el) => {
377
+ el.outerHTML = contentToReplace;
378
+ });
379
+ // Serialize the modified DOM back to HTML
380
+ fileContent = domReplace.serialize();
367
381
  break;
368
382
  default:
369
383
  throw new Error(`Unsupported operation: ${operation}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vint.tri/report_gen_mcp",
3
- "version": "1.3.3",
3
+ "version": "1.3.5",
4
4
  "description": "CLI tool for generating HTML reports with embedded charts",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -19,6 +19,7 @@
19
19
  "ejs": "^3.1.10",
20
20
  "express": "^4.19.2",
21
21
  "fs-extra": "^11.2.0",
22
+ "jsdom": "^26.1.0",
22
23
  "marked": "^14.1.2",
23
24
  "zod": "^3.23.8"
24
25
  },
@@ -26,6 +27,7 @@
26
27
  "@types/ejs": "^3.1.5",
27
28
  "@types/express": "^4.17.21",
28
29
  "@types/fs-extra": "^11.0.4",
30
+ "@types/jsdom": "^21.1.7",
29
31
  "@types/node": "^22.5.0",
30
32
  "typescript": "^5.5.4"
31
33
  },
@@ -0,0 +1,75 @@
1
+ import { generateReport } from './dist/utils/reportGenerator.js';
2
+
3
+ async function testChartFix() {
4
+ const document = `
5
+ # Тестовый отчет с диаграммами
6
+
7
+ ## Введение
8
+ Этот отчет демонстрирует исправленные диаграммы с адекватными размерами.
9
+
10
+ ## Данные продаж
11
+ [[chart:sales]]
12
+
13
+ ## Распределение по категориям
14
+ [[chart:categories]]
15
+
16
+ ## Динамика роста
17
+ [[chart:growth]]
18
+ `;
19
+
20
+ const elements = {
21
+ sales: {
22
+ type: 'bar',
23
+ config: {
24
+ labels: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май'],
25
+ datasets: [{
26
+ label: 'Продажи (тыс. руб.)',
27
+ data: [120, 190, 150, 180, 220],
28
+ backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF'],
29
+ borderColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF']
30
+ }],
31
+ options: {
32
+ title: 'Ежемесячные продажи'
33
+ }
34
+ }
35
+ },
36
+ categories: {
37
+ type: 'pie',
38
+ config: {
39
+ labels: ['Электроника', 'Одежда', 'Продукты', 'Мебель', 'Книги'],
40
+ datasets: [{
41
+ data: [30, 25, 20, 15, 10],
42
+ backgroundColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF'],
43
+ borderColor: ['#FF6384', '#36A2EB', '#FFCE56', '#4BC0C0', '#9966FF']
44
+ }],
45
+ options: {
46
+ title: 'Распределение продаж по категориям'
47
+ }
48
+ }
49
+ },
50
+ growth: {
51
+ type: 'line',
52
+ config: {
53
+ labels: ['Январь', 'Февраль', 'Март', 'Апрель', 'Май'],
54
+ datasets: [{
55
+ label: 'Рост продаж (%)',
56
+ data: [5, 10, 15, 12, 18],
57
+ borderColor: ['#36A2EB'],
58
+ fill: false
59
+ }],
60
+ options: {
61
+ title: 'Динамика роста продаж'
62
+ }
63
+ }
64
+ }
65
+ };
66
+
67
+ try {
68
+ const result = await generateReport(document, elements, 'test_chart_fix_report.html');
69
+ console.log('Отчет успешно создан:', result.filePath);
70
+ } catch (error) {
71
+ console.error('Ошибка при создании отчета:', error);
72
+ }
73
+ }
74
+
75
+ testChartFix();
@@ -0,0 +1,32 @@
1
+ import { JSDOM } from 'jsdom';
2
+ import fs from 'fs/promises';
3
+
4
+ // Read the test file
5
+ const fileContent = await fs.readFile('test_tesla_report.html', 'utf8');
6
+
7
+ // Use JSDOM to parse and manipulate the HTML
8
+ const dom = new JSDOM(fileContent);
9
+ const document = dom.window.document;
10
+
11
+ // Test the CSS selector that was failing before
12
+ const element = document.querySelector('h2:nth-of-type(3)');
13
+
14
+ if (element) {
15
+ console.log('✓ Successfully found element with CSS selector "h2:nth-of-type(3)"');
16
+ console.log('Element text:', element.textContent);
17
+
18
+ // Test inserting content before the element
19
+ const contentToAdd = "<h2>Акции Apple</h2><p>Акции Apple (AAPL) в текущем месяце показали умеренный рост, поддерживаемый стабильными финансовыми результатами и планами по расширению продуктовой линейки.</p><ul><li><strong>Цена на начало месяца:</strong> 189.34 $</li><li><strong>Цена на конец месяца:</strong> 195.78 $</li><li><strong>Изменение за месяц:</strong> +3.4%</li></ul><p>Основные факторы роста связаны с успешными продажами iPhone 15 и ожиданием выхода новых продуктов, таких как Vision Pro и обновленные чипы M3.</p>";
20
+
21
+ element.insertAdjacentHTML('beforebegin', contentToAdd);
22
+
23
+ // Serialize the modified DOM back to HTML
24
+ const modifiedContent = dom.serialize();
25
+
26
+ // Write the modified content back to the file
27
+ await fs.writeFile('test_tesla_report.html', modifiedContent, 'utf8');
28
+
29
+ console.log('✓ Successfully modified the file with Apple stock information');
30
+ } else {
31
+ console.log('✗ Failed to find element with CSS selector "h2:nth-of-type(3)"');
32
+ }
@@ -0,0 +1,66 @@
1
+ import { spawn } from 'child_process';
2
+ import fs from 'fs';
3
+
4
+ // Start the report_gen_mcp server in stdio mode
5
+ const child = spawn('node', ['dist/index.js']);
6
+
7
+ let initialized = false;
8
+
9
+ child.stdout.on('data', (data) => {
10
+ console.log('STDOUT:', data.toString());
11
+
12
+ if (!initialized) {
13
+ // Send initialize message
14
+ const initializeMessage = {
15
+ jsonrpc: "2.0",
16
+ id: 1,
17
+ method: "initialize",
18
+ params: {
19
+ protocolVersion: "2024-07-01",
20
+ capabilities: {},
21
+ clientInfo: {
22
+ name: "test-client",
23
+ version: "1.0.0"
24
+ }
25
+ }
26
+ };
27
+
28
+ child.stdin.write(JSON.stringify(initializeMessage) + '\n');
29
+ initialized = true;
30
+ }
31
+ });
32
+
33
+ child.stderr.on('data', (data) => {
34
+ console.error('STDERR:', data.toString());
35
+ });
36
+
37
+ child.on('close', (code) => {
38
+ console.log(`Child process exited with code ${code}`);
39
+ });
40
+
41
+ // Wait a bit for the server to start, then send the edit-report request
42
+ setTimeout(() => {
43
+ const editReportRequest = {
44
+ jsonrpc: "2.0",
45
+ id: 2,
46
+ method: "tools/call",
47
+ params: {
48
+ name: "edit-report",
49
+ arguments: {
50
+ filePath: "test_tesla_report.html",
51
+ operation: "add",
52
+ contentToAdd: "<h2>Акции Apple</h2><p>Акции Apple (AAPL) в текущем месяце показали умеренный рост, поддерживаемый стабильными финансовыми результатами и планами по расширению продуктовой линейки.</p><ul><li><strong>Цена на начало месяца:</strong> 189.34 $</li><li><strong>Цена на конец месяца:</strong> 195.78 $</li><li><strong>Изменение за месяц:</strong> +3.4%</li></ul><p>Основные факторы роста связаны с успешными продажами iPhone 15 и ожиданием выхода новых продуктов, таких как Vision Pro и обновленные чипы M3.</p>",
53
+ selector: "h2:nth-of-type(3)",
54
+ position: "beforebegin"
55
+ }
56
+ }
57
+ };
58
+
59
+ console.log('Sending edit-report request...');
60
+ child.stdin.write(JSON.stringify(editReportRequest) + '\n');
61
+
62
+ // Give some time for the response, then exit
63
+ setTimeout(() => {
64
+ child.kill();
65
+ }, 2000);
66
+ }, 1000);