@mcp-shark/mcp-shark 1.5.4 → 1.5.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.
Files changed (188) hide show
  1. package/README.md +32 -96
  2. package/bin/mcp-shark.js +1 -1
  3. package/core/configs/codex.js +68 -0
  4. package/core/configs/environment.js +51 -0
  5. package/{lib/common → core}/configs/index.js +16 -1
  6. package/core/constants/Defaults.js +15 -0
  7. package/core/constants/HttpStatus.js +14 -0
  8. package/core/constants/Server.js +20 -0
  9. package/core/constants/StatusCodes.js +25 -0
  10. package/core/constants/index.js +7 -0
  11. package/core/container/DependencyContainer.js +179 -0
  12. package/core/db/init.js +33 -0
  13. package/core/index.js +10 -0
  14. package/{mcp-server/lib/common/error.js → core/libraries/ErrorLibrary.js} +4 -0
  15. package/core/libraries/LoggerLibrary.js +91 -0
  16. package/core/libraries/SerializationLibrary.js +32 -0
  17. package/core/libraries/bootstrap-logger.js +19 -0
  18. package/core/libraries/errors/ApplicationError.js +97 -0
  19. package/core/libraries/index.js +17 -0
  20. package/{mcp-server/lib → core/mcp-server}/auditor/audit.js +77 -53
  21. package/core/mcp-server/index.js +192 -0
  22. package/{mcp-server/lib → core/mcp-server}/server/external/all.js +1 -1
  23. package/core/mcp-server/server/external/config.js +75 -0
  24. package/{mcp-server/lib → core/mcp-server}/server/external/single/client.js +1 -1
  25. package/{mcp-server/lib → core/mcp-server}/server/external/single/request.js +1 -1
  26. package/{mcp-server/lib → core/mcp-server}/server/external/single/run.js +20 -11
  27. package/{mcp-server/lib → core/mcp-server}/server/external/single/transport.js +1 -1
  28. package/{mcp-server/lib → core/mcp-server}/server/internal/handlers/error.js +1 -1
  29. package/core/mcp-server/server/internal/handlers/prompts-get.js +28 -0
  30. package/core/mcp-server/server/internal/handlers/prompts-list.js +21 -0
  31. package/core/mcp-server/server/internal/handlers/resources-list.js +21 -0
  32. package/core/mcp-server/server/internal/handlers/resources-read.js +28 -0
  33. package/core/mcp-server/server/internal/handlers/tools-call.js +44 -0
  34. package/core/mcp-server/server/internal/handlers/tools-list.js +23 -0
  35. package/core/mcp-server/server/internal/run.js +53 -0
  36. package/{mcp-server/lib → core/mcp-server}/server/internal/server.js +11 -1
  37. package/core/models/ConversationFilters.js +31 -0
  38. package/core/models/ExportFormat.js +8 -0
  39. package/core/models/RequestFilters.js +43 -0
  40. package/core/models/SessionFilters.js +23 -0
  41. package/core/models/index.js +8 -0
  42. package/core/repositories/AuditRepository.js +233 -0
  43. package/core/repositories/ConversationRepository.js +182 -0
  44. package/core/repositories/PacketRepository.js +237 -0
  45. package/core/repositories/SchemaRepository.js +107 -0
  46. package/core/repositories/SessionRepository.js +59 -0
  47. package/core/repositories/StatisticsRepository.js +54 -0
  48. package/core/repositories/index.js +10 -0
  49. package/core/services/AuditService.js +144 -0
  50. package/core/services/BackupService.js +222 -0
  51. package/core/services/ConfigDetectionService.js +89 -0
  52. package/core/services/ConfigFileService.js +210 -0
  53. package/core/services/ConfigPatchingService.js +137 -0
  54. package/core/services/ConfigService.js +250 -0
  55. package/core/services/ConfigTransformService.js +178 -0
  56. package/core/services/ConversationService.js +19 -0
  57. package/core/services/ExportService.js +117 -0
  58. package/core/services/LogService.js +64 -0
  59. package/core/services/McpClientService.js +235 -0
  60. package/core/services/McpDiscoveryService.js +107 -0
  61. package/core/services/RequestService.js +56 -0
  62. package/core/services/ScanCacheService.js +242 -0
  63. package/core/services/ScanService.js +167 -0
  64. package/core/services/ServerManagementService.js +206 -0
  65. package/core/services/SessionService.js +34 -0
  66. package/core/services/SettingsService.js +163 -0
  67. package/core/services/StatisticsService.js +64 -0
  68. package/core/services/TokenService.js +94 -0
  69. package/core/services/index.js +25 -0
  70. package/core/services/parsers/ConfigParserFactory.js +113 -0
  71. package/core/services/parsers/JsonConfigParser.js +66 -0
  72. package/core/services/parsers/LegacyJsonConfigParser.js +71 -0
  73. package/core/services/parsers/TomlConfigParser.js +87 -0
  74. package/core/services/parsers/index.js +4 -0
  75. package/{ui/server → core}/utils/scan-cache/directory.js +1 -1
  76. package/core/utils/validation.js +77 -0
  77. package/package.json +14 -11
  78. package/ui/dist/assets/index-CArYxKxS.js +35 -0
  79. package/ui/dist/index.html +1 -1
  80. package/ui/server/controllers/BackupController.js +129 -0
  81. package/ui/server/controllers/ConfigController.js +92 -0
  82. package/ui/server/controllers/ConversationController.js +41 -0
  83. package/ui/server/controllers/LogController.js +44 -0
  84. package/ui/server/controllers/McpClientController.js +60 -0
  85. package/ui/server/controllers/McpDiscoveryController.js +44 -0
  86. package/ui/server/controllers/RequestController.js +129 -0
  87. package/ui/server/controllers/ScanController.js +122 -0
  88. package/ui/server/controllers/ServerManagementController.js +134 -0
  89. package/ui/server/controllers/SessionController.js +57 -0
  90. package/ui/server/controllers/SettingsController.js +24 -0
  91. package/ui/server/controllers/StatisticsController.js +54 -0
  92. package/ui/server/controllers/TokenController.js +58 -0
  93. package/ui/server/controllers/index.js +17 -0
  94. package/ui/server/routes/backups/index.js +15 -9
  95. package/ui/server/routes/composite/index.js +62 -32
  96. package/ui/server/routes/composite/servers.js +20 -15
  97. package/ui/server/routes/config.js +13 -172
  98. package/ui/server/routes/conversations.js +9 -19
  99. package/ui/server/routes/help.js +4 -3
  100. package/ui/server/routes/logs.js +14 -26
  101. package/ui/server/routes/playground.js +11 -174
  102. package/ui/server/routes/requests.js +12 -232
  103. package/ui/server/routes/sessions.js +10 -21
  104. package/ui/server/routes/settings.js +10 -192
  105. package/ui/server/routes/smartscan.js +26 -15
  106. package/ui/server/routes/statistics.js +8 -79
  107. package/ui/server/setup.js +162 -0
  108. package/ui/server/swagger/paths/backups.js +151 -0
  109. package/ui/server/swagger/paths/components.js +76 -0
  110. package/ui/server/swagger/paths/config.js +117 -0
  111. package/ui/server/swagger/paths/conversations.js +29 -0
  112. package/ui/server/swagger/paths/help.js +82 -0
  113. package/ui/server/swagger/paths/logs.js +87 -0
  114. package/ui/server/swagger/paths/playground.js +49 -0
  115. package/ui/server/swagger/paths/requests.js +178 -0
  116. package/ui/server/swagger/paths/serverManagement.js +169 -0
  117. package/ui/server/swagger/paths/sessions.js +61 -0
  118. package/ui/server/swagger/paths/settings.js +31 -0
  119. package/ui/server/swagger/paths/smartScan/discovery.js +97 -0
  120. package/ui/server/swagger/paths/smartScan/index.js +13 -0
  121. package/ui/server/swagger/paths/smartScan/scans.js +151 -0
  122. package/ui/server/swagger/paths/smartScan/token.js +71 -0
  123. package/ui/server/swagger/paths/statistics.js +40 -0
  124. package/ui/server/swagger/paths.js +38 -0
  125. package/ui/server/swagger/swagger.js +37 -0
  126. package/ui/server/utils/cleanup.js +99 -0
  127. package/ui/server/utils/config.js +18 -96
  128. package/ui/server/utils/errorHandler.js +43 -0
  129. package/ui/server/utils/logger.js +2 -2
  130. package/ui/server/utils/paths.js +27 -30
  131. package/ui/server/utils/port.js +21 -21
  132. package/ui/server/utils/process.js +18 -10
  133. package/ui/server/utils/processState.js +17 -0
  134. package/ui/server/utils/signals.js +34 -0
  135. package/ui/server/websocket/broadcast.js +33 -0
  136. package/ui/server/websocket/handler.js +52 -0
  137. package/ui/server.js +51 -230
  138. package/ui/src/App.jsx +2 -0
  139. package/ui/src/CompositeSetup.jsx +23 -9
  140. package/ui/src/PacketFilters.jsx +17 -3
  141. package/ui/src/components/AlertModal.jsx +116 -0
  142. package/ui/src/components/App/ApiDocsButton.jsx +57 -0
  143. package/ui/src/components/App/useAppState.js +43 -1
  144. package/ui/src/components/BackupList.jsx +27 -3
  145. package/ui/src/utils/requestPairing.js +35 -36
  146. package/ui/src/utils/requestUtils.js +1 -0
  147. package/lib/common/db/init.js +0 -132
  148. package/lib/common/db/logger.js +0 -349
  149. package/lib/common/db/query.js +0 -403
  150. package/lib/common/logger.js +0 -90
  151. package/mcp-server/index.js +0 -138
  152. package/mcp-server/lib/server/external/config.js +0 -57
  153. package/mcp-server/lib/server/internal/handlers/prompts-get.js +0 -20
  154. package/mcp-server/lib/server/internal/handlers/prompts-list.js +0 -13
  155. package/mcp-server/lib/server/internal/handlers/resources-list.js +0 -13
  156. package/mcp-server/lib/server/internal/handlers/resources-read.js +0 -20
  157. package/mcp-server/lib/server/internal/handlers/tools-call.js +0 -35
  158. package/mcp-server/lib/server/internal/handlers/tools-list.js +0 -15
  159. package/mcp-server/lib/server/internal/run.js +0 -37
  160. package/mcp-server/mcp-shark.js +0 -22
  161. package/ui/dist/assets/index-CFHeMNwd.js +0 -35
  162. package/ui/server/routes/backups/deleteBackup.js +0 -54
  163. package/ui/server/routes/backups/listBackups.js +0 -75
  164. package/ui/server/routes/backups/restoreBackup.js +0 -83
  165. package/ui/server/routes/backups/viewBackup.js +0 -47
  166. package/ui/server/routes/composite/setup.js +0 -129
  167. package/ui/server/routes/composite/status.js +0 -7
  168. package/ui/server/routes/composite/stop.js +0 -39
  169. package/ui/server/routes/composite/utils.js +0 -45
  170. package/ui/server/routes/smartscan/discover.js +0 -118
  171. package/ui/server/routes/smartscan/scans/clearCache.js +0 -23
  172. package/ui/server/routes/smartscan/scans/createBatchScans.js +0 -124
  173. package/ui/server/routes/smartscan/scans/createScan.js +0 -43
  174. package/ui/server/routes/smartscan/scans/getCachedResults.js +0 -52
  175. package/ui/server/routes/smartscan/scans/getScan.js +0 -42
  176. package/ui/server/routes/smartscan/scans/listScans.js +0 -25
  177. package/ui/server/routes/smartscan/scans.js +0 -13
  178. package/ui/server/routes/smartscan/token.js +0 -57
  179. package/ui/server/utils/config-update.js +0 -240
  180. package/ui/server/utils/scan-cache/all-results.js +0 -197
  181. package/ui/server/utils/scan-cache/file-operations.js +0 -107
  182. package/ui/server/utils/scan-cache/hash.js +0 -47
  183. package/ui/server/utils/scan-cache/server-operations.js +0 -85
  184. package/ui/server/utils/scan-cache.js +0 -12
  185. package/ui/server/utils/smartscan-token.js +0 -43
  186. /package/{mcp-server/lib → core/mcp-server}/server/external/kv.js +0 -0
  187. /package/{mcp-server/lib → core/mcp-server}/server/internal/handlers/common.js +0 -0
  188. /package/{mcp-server/lib → core/mcp-server}/server/internal/session.js +0 -0
@@ -1,197 +0,0 @@
1
- import { existsSync, readFileSync, readdirSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import logger from '../logger.js';
4
- import { getScanResultsDirectory } from './directory.js';
5
-
6
- /**
7
- * Extract server name from cached scan data
8
- * @param {Object} data - Cached file data
9
- * @param {Object} scanData - Scan data from API
10
- * @returns {string} Server name
11
- */
12
- function extractServerName(data, scanData) {
13
- const cachedServerName = data.serverName; // From cache file metadata (most reliable)
14
-
15
- // If not found at top level, try to extract from scan data (API response)
16
- if (!cachedServerName || cachedServerName === 'Unknown Server') {
17
- const actualScanData = scanData.data || scanData;
18
-
19
- const serverName =
20
- actualScanData.serverName ||
21
- actualScanData.server_name ||
22
- actualScanData.server?.name ||
23
- actualScanData.mcp_server_data?.server?.name ||
24
- scanData.serverName ||
25
- scanData.server_name ||
26
- scanData.server?.name ||
27
- scanData.mcp_server_data?.server?.name ||
28
- 'Unknown Server';
29
-
30
- return serverName;
31
- }
32
-
33
- return cachedServerName;
34
- }
35
-
36
- /**
37
- * Process a single cached scan file
38
- * @param {string} file - File name
39
- * @param {string} scanResultsDir - Directory path
40
- * @returns {Object|null} Processed scan result or null if error
41
- */
42
- function processScanFile(file, scanResultsDir) {
43
- try {
44
- const filePath = join(scanResultsDir, file);
45
- logger.debug({ file }, 'Reading cached scan result file');
46
-
47
- const fileContent = readFileSync(filePath, 'utf8');
48
- const data = JSON.parse(fileContent);
49
-
50
- // Validate that this is a scan result file
51
- if (!data || typeof data !== 'object') {
52
- logger.warn({ file }, 'Invalid data in file: not an object');
53
- return null;
54
- }
55
-
56
- // Debug: Log the structure to understand what we're working with
57
- logger.debug(
58
- {
59
- file,
60
- hasServerName: !!data.serverName,
61
- serverName: data.serverName,
62
- hasScanData: !!data.scanData,
63
- scanDataKeys: data.scanData ? Object.keys(data.scanData) : [],
64
- topLevelKeys: Object.keys(data),
65
- },
66
- 'File structure'
67
- );
68
-
69
- // Create a scan-like object with id, server name, and scan data
70
- const scanData = data.scanData || data;
71
- const scanId = scanData.id || scanData.scan_id || data.hash || file.replace('.json', '');
72
- const serverName = extractServerName(data, scanData);
73
-
74
- // Log if we couldn't find server name
75
- if (serverName === 'Unknown Server') {
76
- logger.warn(
77
- {
78
- file,
79
- dataServerName: data.serverName,
80
- dataKeys: Object.keys(data || {}).join(', '),
81
- scanDataKeys: Object.keys(scanData || {}).join(', '),
82
- scanDataDataKeys: scanData?.data ? Object.keys(scanData.data || {}).join(', ') : null,
83
- },
84
- 'Could not find server name in file'
85
- );
86
- }
87
-
88
- const scanResult = {
89
- id: scanId,
90
- scan_id: scanId,
91
- server: {
92
- name: serverName,
93
- },
94
- server_name: serverName,
95
- serverName: serverName,
96
- status: 'completed',
97
- risk_level: scanData.overall_risk_level || scanData.risk_level || 'unknown',
98
- overall_risk_level: scanData.overall_risk_level || scanData.risk_level || 'unknown',
99
- created_at: data.createdAt || data.created_at || scanData.created_at,
100
- updated_at: data.updatedAt || data.updated_at || scanData.updated_at,
101
- cached: true,
102
- hash: data.hash || file.replace('.json', ''),
103
- data: scanData,
104
- result: scanData,
105
- };
106
-
107
- logger.debug({ serverName, scanId }, 'Successfully loaded scan');
108
- return scanResult;
109
- } catch (error) {
110
- logger.warn(
111
- {
112
- file,
113
- filePath: join(scanResultsDir, file),
114
- error: error.message,
115
- stack: error.stack,
116
- },
117
- 'Error reading scan result file'
118
- );
119
- return null;
120
- }
121
- }
122
-
123
- /**
124
- * Get all cached scan results (across all servers)
125
- * @returns {Array} Array of cached scan results
126
- */
127
- export function getAllCachedScanResults() {
128
- try {
129
- const scanResultsDir = getScanResultsDirectory();
130
- logger.debug({ scanResultsDir }, 'Reading cached scans from directory');
131
-
132
- // Check if directory exists (don't create it, just check)
133
- if (!existsSync(scanResultsDir)) {
134
- logger.debug({ scanResultsDir }, 'Scan results directory does not exist');
135
- return [];
136
- }
137
-
138
- // Read all files in the directory
139
- const allFiles = readdirSync(scanResultsDir);
140
- logger.debug({ count: allFiles.length }, 'Total files in directory');
141
-
142
- // Filter for JSON files only
143
- const jsonFiles = allFiles.filter((f) => f.endsWith('.json'));
144
- logger.debug({ count: jsonFiles.length, scanResultsDir }, 'Found JSON files');
145
-
146
- if (jsonFiles.length === 0) {
147
- logger.debug('No cached scan JSON files found');
148
- return [];
149
- }
150
-
151
- // Read each file
152
- const { results, successCount, errorCount } = jsonFiles.reduce(
153
- (acc, file) => {
154
- const result = processScanFile(file, scanResultsDir);
155
- if (result) {
156
- return {
157
- results: [...acc.results, result],
158
- successCount: acc.successCount + 1,
159
- errorCount: acc.errorCount,
160
- };
161
- }
162
- return {
163
- results: acc.results,
164
- successCount: acc.successCount,
165
- errorCount: acc.errorCount + 1,
166
- };
167
- },
168
- { results: [], successCount: 0, errorCount: 0 }
169
- );
170
-
171
- // Sort by updatedAt descending (most recent first)
172
- results.sort((a, b) => {
173
- const aTime = a.updated_at || a.created_at || 0;
174
- const bTime = b.updated_at || b.created_at || 0;
175
- return bTime - aTime;
176
- });
177
-
178
- logger.info(
179
- {
180
- successCount,
181
- errorCount,
182
- total: results.length,
183
- },
184
- 'Summary: cached scans loaded'
185
- );
186
- return results;
187
- } catch (error) {
188
- logger.error(
189
- {
190
- error: error.message,
191
- stack: error.stack,
192
- },
193
- 'Fatal error getting all cached scan results'
194
- );
195
- return [];
196
- }
197
- }
@@ -1,107 +0,0 @@
1
- import { existsSync, readFileSync, readdirSync, unlinkSync, writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import logger from '../logger.js';
4
- import { getScanResultFilePath, getScanResultsDirectory } from './directory.js';
5
-
6
- /**
7
- * Get cached scan result by hash
8
- * @param {string} hash - SHA-256 hash of MCP server data
9
- * @returns {Object|null} Cached scan result or null if not found
10
- */
11
- export function getCachedScanResult(hash) {
12
- try {
13
- const filePath = getScanResultFilePath(hash);
14
-
15
- if (!existsSync(filePath)) {
16
- return null;
17
- }
18
-
19
- const fileContent = readFileSync(filePath, 'utf8');
20
- const data = JSON.parse(fileContent);
21
-
22
- return {
23
- ...data.scanData,
24
- cached: true,
25
- cachedAt: data.createdAt,
26
- updatedAt: data.updatedAt,
27
- serverName: data.serverName,
28
- };
29
- } catch (error) {
30
- logger.error({ hash, error: error.message }, 'Error getting cached scan result');
31
- return null;
32
- }
33
- }
34
-
35
- /**
36
- * Store scan result in cache
37
- * @param {string} serverName - Name of the MCP server
38
- * @param {string} hash - SHA-256 hash of MCP server data
39
- * @param {Object} scanData - Scan result data to store
40
- * @returns {boolean} Success status
41
- */
42
- export function storeScanResult(serverName, hash, scanData) {
43
- try {
44
- const filePath = getScanResultFilePath(hash);
45
- const now = Date.now();
46
-
47
- // Check if file exists to preserve original creation time
48
- const getCreatedAt = (filePath, defaultTime) => {
49
- if (!existsSync(filePath)) {
50
- return defaultTime;
51
- }
52
- try {
53
- const existingContent = readFileSync(filePath, 'utf8');
54
- const existingData = JSON.parse(existingContent);
55
- return existingData.createdAt || defaultTime;
56
- } catch (_e) {
57
- return defaultTime;
58
- }
59
- };
60
- const createdAt = getCreatedAt(filePath, now);
61
-
62
- const dataToStore = {
63
- serverName,
64
- hash,
65
- scanData,
66
- createdAt,
67
- updatedAt: now,
68
- };
69
-
70
- writeFileSync(filePath, JSON.stringify(dataToStore, null, 2), 'utf8');
71
- return true;
72
- } catch (error) {
73
- logger.error({ serverName, hash, error: error.message }, 'Error storing scan result');
74
- return false;
75
- }
76
- }
77
-
78
- /**
79
- * Clear all cached scan results
80
- * @returns {number} Number of files deleted
81
- */
82
- export function clearAllScanResults() {
83
- try {
84
- const scanResultsDir = getScanResultsDirectory();
85
- if (!existsSync(scanResultsDir)) {
86
- return 0;
87
- }
88
-
89
- const files = readdirSync(scanResultsDir).filter((f) => f.endsWith('.json'));
90
-
91
- const deletedCount = files.reduce((count, file) => {
92
- try {
93
- const filePath = join(scanResultsDir, file);
94
- unlinkSync(filePath);
95
- return count + 1;
96
- } catch (error) {
97
- logger.warn({ file, error: error.message }, 'Error deleting scan result file');
98
- return count;
99
- }
100
- }, 0);
101
-
102
- return deletedCount;
103
- } catch (error) {
104
- logger.error({ error: error.message }, 'Error clearing all scan results');
105
- return 0;
106
- }
107
- }
@@ -1,47 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
-
3
- /**
4
- * Compute SHA-256 hash of MCP server data for change detection
5
- * @param {Object} serverData - MCP server data (name, tools, resources, prompts)
6
- * @returns {string} SHA-256 hash in hex format
7
- */
8
- export function computeMcpHash(serverData) {
9
- // Normalize the data to ensure consistent hashing
10
- // Sort arrays to ensure order doesn't matter
11
- const normalized = {
12
- name: serverData.name || '',
13
- tools: (serverData.tools || [])
14
- .map((tool) => ({
15
- name: tool.name || '',
16
- description: tool.description || '',
17
- inputSchema: tool.inputSchema || tool.input_schema || null,
18
- outputSchema: tool.outputSchema || tool.output_schema || null,
19
- }))
20
- .sort((a, b) => (a.name || '').localeCompare(b.name || '')),
21
- resources: (serverData.resources || [])
22
- .map((resource) => ({
23
- uri: resource.uri || '',
24
- name: resource.name || '',
25
- description: resource.description || '',
26
- mimeType: resource.mimeType || resource.mime_type || null,
27
- }))
28
- .sort((a, b) => (a.uri || '').localeCompare(b.uri || '')),
29
- prompts: (serverData.prompts || [])
30
- .map((prompt) => ({
31
- name: prompt.name || '',
32
- description: prompt.description || '',
33
- arguments: (prompt.arguments || []).sort((a, b) => {
34
- const aName = (a.name || '').toString();
35
- const bName = (b.name || '').toString();
36
- return aName.localeCompare(bName);
37
- }),
38
- }))
39
- .sort((a, b) => (a.name || '').localeCompare(b.name || '')),
40
- };
41
-
42
- // Create deterministic JSON string (sorted keys)
43
- const jsonString = JSON.stringify(normalized);
44
-
45
- // Compute SHA-256 hash
46
- return createHash('sha256').update(jsonString).digest('hex');
47
- }
@@ -1,85 +0,0 @@
1
- import { readFileSync, readdirSync, unlinkSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import logger from '../logger.js';
4
- import { ensureScanResultsDirectory } from './directory.js';
5
-
6
- /**
7
- * Get all cached scan results for a server
8
- * @param {string} serverName - Name of the MCP server
9
- * @returns {Array} Array of cached scan results
10
- */
11
- export function getCachedScanResultsForServer(serverName) {
12
- try {
13
- const scanResultsDir = ensureScanResultsDirectory();
14
- const files = readdirSync(scanResultsDir).filter((f) => f.endsWith('.json'));
15
- const results = [];
16
-
17
- for (const file of files) {
18
- try {
19
- const filePath = join(scanResultsDir, file);
20
- const fileContent = readFileSync(filePath, 'utf8');
21
- const data = JSON.parse(fileContent);
22
-
23
- if (data.serverName === serverName) {
24
- results.push({
25
- ...data.scanData,
26
- cached: true,
27
- cachedAt: data.createdAt,
28
- updatedAt: data.updatedAt,
29
- hash: data.hash,
30
- });
31
- }
32
- } catch (error) {
33
- // Skip files that can't be parsed
34
- logger.warn({ file, error: error.message }, 'Error reading scan result file');
35
- }
36
- }
37
-
38
- // Sort by updatedAt descending
39
- results.sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
40
-
41
- return results;
42
- } catch (error) {
43
- logger.error({ error: error.message }, 'Error getting cached scan results for server');
44
- return [];
45
- }
46
- }
47
-
48
- /**
49
- * Clear old scan results (optional cleanup function)
50
- * @param {number} maxAgeMs - Maximum age in milliseconds (default: 30 days)
51
- * @returns {number} Number of files deleted
52
- */
53
- export function clearOldScanResults(maxAgeMs = 30 * 24 * 60 * 60 * 1000) {
54
- try {
55
- const scanResultsDir = ensureScanResultsDirectory();
56
- const files = readdirSync(scanResultsDir).filter((f) => f.endsWith('.json'));
57
- const cutoffTime = Date.now() - maxAgeMs;
58
-
59
- const deletedCount = files.reduce((count, file) => {
60
- try {
61
- const filePath = join(scanResultsDir, file);
62
- const fileContent = readFileSync(filePath, 'utf8');
63
- const data = JSON.parse(fileContent);
64
-
65
- if (data.updatedAt && data.updatedAt < cutoffTime) {
66
- unlinkSync(filePath);
67
- return count + 1;
68
- }
69
- return count;
70
- } catch (error) {
71
- // Skip files that can't be parsed
72
- logger.warn(
73
- { file, error: error.message },
74
- 'Error processing scan result file for cleanup'
75
- );
76
- return count;
77
- }
78
- }, 0);
79
-
80
- return deletedCount;
81
- } catch (error) {
82
- logger.error({ error: error.message }, 'Error clearing old scan results');
83
- return 0;
84
- }
85
- }
@@ -1,12 +0,0 @@
1
- // Main entry point - re-export all functions
2
- export { computeMcpHash } from './scan-cache/hash.js';
3
- export {
4
- getCachedScanResult,
5
- storeScanResult,
6
- clearAllScanResults,
7
- } from './scan-cache/file-operations.js';
8
- export {
9
- getCachedScanResultsForServer,
10
- clearOldScanResults,
11
- } from './scan-cache/server-operations.js';
12
- export { getAllCachedScanResults } from './scan-cache/all-results.js';
@@ -1,43 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
3
- import { getWorkingDirectory, prepareAppDataSpaces } from '#common/configs';
4
- import logger from './logger.js';
5
-
6
- const SMART_SCAN_TOKEN_NAME = 'smart-scan-token.json';
7
-
8
- function getSmartScanTokenPath() {
9
- return join(getWorkingDirectory(), SMART_SCAN_TOKEN_NAME);
10
- }
11
-
12
- export function readSmartScanToken() {
13
- try {
14
- const tokenPath = getSmartScanTokenPath();
15
- if (existsSync(tokenPath)) {
16
- const content = readFileSync(tokenPath, 'utf8');
17
- const data = JSON.parse(content);
18
- return data.token || null;
19
- }
20
- return null;
21
- } catch (error) {
22
- logger.error({ error: error.message }, 'Error reading Smart Scan token');
23
- return null;
24
- }
25
- }
26
-
27
- export function writeSmartScanToken(token) {
28
- try {
29
- const tokenPath = getSmartScanTokenPath();
30
- prepareAppDataSpaces(); // Ensure directory exists
31
-
32
- const data = {
33
- token: token || null,
34
- updatedAt: new Date().toISOString(),
35
- };
36
-
37
- writeFileSync(tokenPath, JSON.stringify(data, null, 2), { mode: 0o600 }); // Read/write for owner only
38
- return true;
39
- } catch (error) {
40
- logger.error({ error: error.message }, 'Error writing Smart Scan token');
41
- return false;
42
- }
43
- }