@mcp-shark/mcp-shark 1.5.3 → 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.
- package/README.md +32 -96
- package/bin/mcp-shark.js +1 -1
- package/core/configs/codex.js +68 -0
- package/core/configs/environment.js +51 -0
- package/{lib/common → core}/configs/index.js +16 -1
- package/core/constants/Defaults.js +15 -0
- package/core/constants/HttpStatus.js +14 -0
- package/core/constants/Server.js +20 -0
- package/core/constants/StatusCodes.js +25 -0
- package/core/constants/index.js +7 -0
- package/core/container/DependencyContainer.js +179 -0
- package/core/db/init.js +33 -0
- package/core/index.js +10 -0
- package/{mcp-server/lib/common/error.js → core/libraries/ErrorLibrary.js} +4 -0
- package/core/libraries/LoggerLibrary.js +91 -0
- package/core/libraries/SerializationLibrary.js +32 -0
- package/core/libraries/bootstrap-logger.js +19 -0
- package/core/libraries/errors/ApplicationError.js +97 -0
- package/core/libraries/index.js +17 -0
- package/{mcp-server/lib → core/mcp-server}/auditor/audit.js +77 -53
- package/core/mcp-server/index.js +192 -0
- package/{mcp-server/lib → core/mcp-server}/server/external/all.js +1 -1
- package/core/mcp-server/server/external/config.js +75 -0
- package/{mcp-server/lib → core/mcp-server}/server/external/single/client.js +1 -1
- package/{mcp-server/lib → core/mcp-server}/server/external/single/request.js +1 -1
- package/{mcp-server/lib → core/mcp-server}/server/external/single/run.js +20 -11
- package/{mcp-server/lib → core/mcp-server}/server/external/single/transport.js +1 -1
- package/{mcp-server/lib → core/mcp-server}/server/internal/handlers/error.js +1 -1
- package/core/mcp-server/server/internal/handlers/prompts-get.js +28 -0
- package/core/mcp-server/server/internal/handlers/prompts-list.js +21 -0
- package/core/mcp-server/server/internal/handlers/resources-list.js +21 -0
- package/core/mcp-server/server/internal/handlers/resources-read.js +28 -0
- package/core/mcp-server/server/internal/handlers/tools-call.js +44 -0
- package/core/mcp-server/server/internal/handlers/tools-list.js +23 -0
- package/core/mcp-server/server/internal/run.js +53 -0
- package/{mcp-server/lib → core/mcp-server}/server/internal/server.js +11 -1
- package/core/models/ConversationFilters.js +31 -0
- package/core/models/ExportFormat.js +8 -0
- package/core/models/RequestFilters.js +43 -0
- package/core/models/SessionFilters.js +23 -0
- package/core/models/index.js +8 -0
- package/core/repositories/AuditRepository.js +233 -0
- package/core/repositories/ConversationRepository.js +182 -0
- package/core/repositories/PacketRepository.js +237 -0
- package/core/repositories/SchemaRepository.js +107 -0
- package/core/repositories/SessionRepository.js +59 -0
- package/core/repositories/StatisticsRepository.js +54 -0
- package/core/repositories/index.js +10 -0
- package/core/services/AuditService.js +144 -0
- package/core/services/BackupService.js +222 -0
- package/core/services/ConfigDetectionService.js +89 -0
- package/core/services/ConfigFileService.js +210 -0
- package/core/services/ConfigPatchingService.js +137 -0
- package/core/services/ConfigService.js +250 -0
- package/core/services/ConfigTransformService.js +178 -0
- package/core/services/ConversationService.js +19 -0
- package/core/services/ExportService.js +117 -0
- package/core/services/LogService.js +64 -0
- package/core/services/McpClientService.js +235 -0
- package/core/services/McpDiscoveryService.js +107 -0
- package/core/services/RequestService.js +56 -0
- package/core/services/ScanCacheService.js +242 -0
- package/core/services/ScanService.js +167 -0
- package/core/services/ServerManagementService.js +206 -0
- package/core/services/SessionService.js +34 -0
- package/core/services/SettingsService.js +163 -0
- package/core/services/StatisticsService.js +64 -0
- package/core/services/TokenService.js +94 -0
- package/core/services/index.js +25 -0
- package/core/services/parsers/ConfigParserFactory.js +113 -0
- package/core/services/parsers/JsonConfigParser.js +66 -0
- package/core/services/parsers/LegacyJsonConfigParser.js +71 -0
- package/core/services/parsers/TomlConfigParser.js +87 -0
- package/core/services/parsers/index.js +4 -0
- package/{ui/server → core}/utils/scan-cache/directory.js +1 -1
- package/core/utils/validation.js +77 -0
- package/package.json +14 -11
- package/ui/dist/assets/index-CArYxKxS.js +35 -0
- package/ui/dist/index.html +1 -1
- package/ui/server/controllers/BackupController.js +129 -0
- package/ui/server/controllers/ConfigController.js +92 -0
- package/ui/server/controllers/ConversationController.js +41 -0
- package/ui/server/controllers/LogController.js +44 -0
- package/ui/server/controllers/McpClientController.js +60 -0
- package/ui/server/controllers/McpDiscoveryController.js +44 -0
- package/ui/server/controllers/RequestController.js +129 -0
- package/ui/server/controllers/ScanController.js +122 -0
- package/ui/server/controllers/ServerManagementController.js +134 -0
- package/ui/server/controllers/SessionController.js +57 -0
- package/ui/server/controllers/SettingsController.js +24 -0
- package/ui/server/controllers/StatisticsController.js +54 -0
- package/ui/server/controllers/TokenController.js +58 -0
- package/ui/server/controllers/index.js +17 -0
- package/ui/server/routes/backups/index.js +15 -9
- package/ui/server/routes/composite/index.js +62 -32
- package/ui/server/routes/composite/servers.js +20 -15
- package/ui/server/routes/config.js +13 -172
- package/ui/server/routes/conversations.js +9 -19
- package/ui/server/routes/help.js +4 -3
- package/ui/server/routes/logs.js +14 -26
- package/ui/server/routes/playground.js +11 -174
- package/ui/server/routes/requests.js +12 -232
- package/ui/server/routes/sessions.js +10 -21
- package/ui/server/routes/settings.js +10 -192
- package/ui/server/routes/smartscan.js +26 -15
- package/ui/server/routes/statistics.js +8 -79
- package/ui/server/setup.js +162 -0
- package/ui/server/swagger/paths/backups.js +151 -0
- package/ui/server/swagger/paths/components.js +76 -0
- package/ui/server/swagger/paths/config.js +117 -0
- package/ui/server/swagger/paths/conversations.js +29 -0
- package/ui/server/swagger/paths/help.js +82 -0
- package/ui/server/swagger/paths/logs.js +87 -0
- package/ui/server/swagger/paths/playground.js +49 -0
- package/ui/server/swagger/paths/requests.js +178 -0
- package/ui/server/swagger/paths/serverManagement.js +169 -0
- package/ui/server/swagger/paths/sessions.js +61 -0
- package/ui/server/swagger/paths/settings.js +31 -0
- package/ui/server/swagger/paths/smartScan/discovery.js +97 -0
- package/ui/server/swagger/paths/smartScan/index.js +13 -0
- package/ui/server/swagger/paths/smartScan/scans.js +151 -0
- package/ui/server/swagger/paths/smartScan/token.js +71 -0
- package/ui/server/swagger/paths/statistics.js +40 -0
- package/ui/server/swagger/paths.js +38 -0
- package/ui/server/swagger/swagger.js +37 -0
- package/ui/server/utils/cleanup.js +99 -0
- package/ui/server/utils/config.js +18 -96
- package/ui/server/utils/errorHandler.js +43 -0
- package/ui/server/utils/logger.js +2 -2
- package/ui/server/utils/paths.js +27 -30
- package/ui/server/utils/port.js +21 -21
- package/ui/server/utils/process.js +18 -10
- package/ui/server/utils/processState.js +17 -0
- package/ui/server/utils/signals.js +34 -0
- package/ui/server/websocket/broadcast.js +33 -0
- package/ui/server/websocket/handler.js +52 -0
- package/ui/server.js +51 -230
- package/ui/src/App.jsx +2 -0
- package/ui/src/CompositeSetup.jsx +23 -9
- package/ui/src/PacketFilters.jsx +17 -3
- package/ui/src/components/AlertModal.jsx +116 -0
- package/ui/src/components/App/ApiDocsButton.jsx +57 -0
- package/ui/src/components/App/useAppState.js +43 -1
- package/ui/src/components/BackupList.jsx +27 -3
- package/ui/src/utils/requestPairing.js +35 -36
- package/ui/src/utils/requestUtils.js +1 -0
- package/lib/common/db/init.js +0 -132
- package/lib/common/db/logger.js +0 -349
- package/lib/common/db/query.js +0 -403
- package/lib/common/logger.js +0 -90
- package/mcp-server/index.js +0 -111
- package/mcp-server/lib/server/external/config.js +0 -57
- package/mcp-server/lib/server/internal/handlers/prompts-get.js +0 -20
- package/mcp-server/lib/server/internal/handlers/prompts-list.js +0 -13
- package/mcp-server/lib/server/internal/handlers/resources-list.js +0 -13
- package/mcp-server/lib/server/internal/handlers/resources-read.js +0 -20
- package/mcp-server/lib/server/internal/handlers/tools-call.js +0 -35
- package/mcp-server/lib/server/internal/handlers/tools-list.js +0 -15
- package/mcp-server/lib/server/internal/run.js +0 -37
- package/mcp-server/mcp-shark.js +0 -22
- package/ui/dist/assets/index-CFHeMNwd.js +0 -35
- package/ui/server/routes/backups/deleteBackup.js +0 -54
- package/ui/server/routes/backups/listBackups.js +0 -75
- package/ui/server/routes/backups/restoreBackup.js +0 -83
- package/ui/server/routes/backups/viewBackup.js +0 -47
- package/ui/server/routes/composite/setup.js +0 -129
- package/ui/server/routes/composite/status.js +0 -7
- package/ui/server/routes/composite/stop.js +0 -39
- package/ui/server/routes/composite/utils.js +0 -45
- package/ui/server/routes/smartscan/discover.js +0 -118
- package/ui/server/routes/smartscan/scans/clearCache.js +0 -23
- package/ui/server/routes/smartscan/scans/createBatchScans.js +0 -124
- package/ui/server/routes/smartscan/scans/createScan.js +0 -43
- package/ui/server/routes/smartscan/scans/getCachedResults.js +0 -52
- package/ui/server/routes/smartscan/scans/getScan.js +0 -42
- package/ui/server/routes/smartscan/scans/listScans.js +0 -25
- package/ui/server/routes/smartscan/scans.js +0 -13
- package/ui/server/routes/smartscan/token.js +0 -57
- package/ui/server/utils/config-update.js +0 -240
- package/ui/server/utils/scan-cache/all-results.js +0 -197
- package/ui/server/utils/scan-cache/file-operations.js +0 -107
- package/ui/server/utils/scan-cache/hash.js +0 -47
- package/ui/server/utils/scan-cache/server-operations.js +0 -85
- package/ui/server/utils/scan-cache.js +0 -12
- package/ui/server/utils/smartscan-token.js +0 -43
- /package/{mcp-server/lib → core/mcp-server}/server/external/kv.js +0 -0
- /package/{mcp-server/lib → core/mcp-server}/server/internal/handlers/common.js +0 -0
- /package/{mcp-server/lib → core/mcp-server}/server/internal/session.js +0 -0
|
@@ -1,239 +1,19 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import logger from '../utils/logger.js';
|
|
3
|
-
import { serializeBigInt } from '../utils/serialization.js';
|
|
1
|
+
import { RequestController } from '../controllers/RequestController.js';
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return null;
|
|
11
|
-
};
|
|
3
|
+
export function createRequestsRoutes(container) {
|
|
4
|
+
const requestService = container.getService('request');
|
|
5
|
+
const exportService = container.getService('export');
|
|
6
|
+
const serializationLib = container.getLibrary('serialization');
|
|
7
|
+
const logger = container.getLibrary('logger');
|
|
12
8
|
|
|
13
|
-
|
|
14
|
-
const router = {};
|
|
15
|
-
|
|
16
|
-
router.getRequests = (req, res) => {
|
|
17
|
-
try {
|
|
18
|
-
const limit = Number.parseInt(req.query.limit) || 1000;
|
|
19
|
-
const offset = Number.parseInt(req.query.offset) || 0;
|
|
20
|
-
|
|
21
|
-
// Sanitize search parameter - convert empty strings to null
|
|
22
|
-
const search = sanitizeSearch(req.query.search);
|
|
23
|
-
|
|
24
|
-
// Build filters object, ensuring all values are properly typed
|
|
25
|
-
const filters = {
|
|
26
|
-
sessionId: (req.query.sessionId && String(req.query.sessionId).trim()) || null,
|
|
27
|
-
direction: (req.query.direction && String(req.query.direction).trim()) || null,
|
|
28
|
-
method: (req.query.method && String(req.query.method).trim()) || null,
|
|
29
|
-
jsonrpcMethod: (req.query.jsonrpcMethod && String(req.query.jsonrpcMethod).trim()) || null,
|
|
30
|
-
statusCode: req.query.statusCode ? Number.parseInt(req.query.statusCode) : null,
|
|
31
|
-
jsonrpcId: (req.query.jsonrpcId && String(req.query.jsonrpcId).trim()) || null,
|
|
32
|
-
search: search,
|
|
33
|
-
serverName: (req.query.serverName && String(req.query.serverName).trim()) || null,
|
|
34
|
-
startTime: req.query.startTime ? BigInt(req.query.startTime) : null,
|
|
35
|
-
endTime: req.query.endTime ? BigInt(req.query.endTime) : null,
|
|
36
|
-
limit,
|
|
37
|
-
offset,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// Remove undefined values to avoid issues
|
|
41
|
-
Object.keys(filters).forEach((key) => {
|
|
42
|
-
if (filters[key] === undefined) {
|
|
43
|
-
filters[key] = null;
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
const requests = queryRequests(db, filters);
|
|
48
|
-
res.json(serializeBigInt(requests));
|
|
49
|
-
} catch (error) {
|
|
50
|
-
logger.error({ error: error.message }, 'Error in getRequests');
|
|
51
|
-
res.status(500).json({ error: 'Failed to query requests', details: error.message });
|
|
52
|
-
}
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
router.getRequest = (req, res) => {
|
|
56
|
-
const stmt = db.prepare('SELECT * FROM packets WHERE frame_number = ?');
|
|
57
|
-
const request = stmt.get(Number.parseInt(req.params.frameNumber));
|
|
58
|
-
if (!request) {
|
|
59
|
-
return res.status(404).json({ error: 'Request not found' });
|
|
60
|
-
}
|
|
61
|
-
res.json(serializeBigInt(request));
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
router.clearRequests = (_req, res) => {
|
|
65
|
-
try {
|
|
66
|
-
// Disable foreign key constraints temporarily to avoid constraint violations
|
|
67
|
-
db.exec('PRAGMA foreign_keys = OFF');
|
|
68
|
-
|
|
69
|
-
// Get list of all tables in the database
|
|
70
|
-
const tablesResult = db
|
|
71
|
-
.prepare(
|
|
72
|
-
`
|
|
73
|
-
SELECT name FROM sqlite_master
|
|
74
|
-
WHERE type='table' AND name NOT LIKE 'sqlite_%'
|
|
75
|
-
`
|
|
76
|
-
)
|
|
77
|
-
.all();
|
|
78
|
-
|
|
79
|
-
const existingTables = tablesResult.map((row) => row.name);
|
|
80
|
-
|
|
81
|
-
// Based on lib/common/db schema, these are the traffic-related tables:
|
|
82
|
-
// - packets: Individual HTTP request/response packets
|
|
83
|
-
// - conversations: Correlated request/response pairs
|
|
84
|
-
// - sessions: Session tracking
|
|
85
|
-
// Clear in order to respect any foreign key dependencies
|
|
86
|
-
const trafficTables = [
|
|
87
|
-
'conversations', // Clear conversations first (may reference packets)
|
|
88
|
-
'packets', // Clear packets (main traffic data)
|
|
89
|
-
'sessions', // Clear sessions (may reference packets)
|
|
90
|
-
];
|
|
9
|
+
const controller = new RequestController(requestService, exportService, serializationLib, logger);
|
|
91
10
|
|
|
92
|
-
|
|
93
|
-
const clearResults = trafficTables.reduce(
|
|
94
|
-
(acc, table) => {
|
|
95
|
-
if (existingTables.includes(table)) {
|
|
96
|
-
try {
|
|
97
|
-
db.exec(`DELETE FROM ${table}`);
|
|
98
|
-
return {
|
|
99
|
-
count: acc.count + 1,
|
|
100
|
-
tables: [...acc.tables, table],
|
|
101
|
-
};
|
|
102
|
-
} catch (err) {
|
|
103
|
-
logger.warn({ table, error: err.message }, 'Error clearing table');
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return acc;
|
|
107
|
-
},
|
|
108
|
-
{ count: 0, tables: [] }
|
|
109
|
-
);
|
|
110
|
-
const clearedCount = clearResults.count;
|
|
111
|
-
const clearedTables = clearResults.tables;
|
|
112
|
-
|
|
113
|
-
// Re-enable foreign key constraints
|
|
114
|
-
db.exec('PRAGMA foreign_keys = ON');
|
|
115
|
-
|
|
116
|
-
res.json({
|
|
117
|
-
success: true,
|
|
118
|
-
message: `Cleared ${clearedCount} table(s): ${clearedTables.join(', ')}. All captured traffic has been cleared.`,
|
|
119
|
-
});
|
|
120
|
-
} catch (error) {
|
|
121
|
-
// Make sure to re-enable foreign keys even if there's an error
|
|
122
|
-
try {
|
|
123
|
-
db.exec('PRAGMA foreign_keys = ON');
|
|
124
|
-
} catch (_e) {
|
|
125
|
-
// Ignore
|
|
126
|
-
}
|
|
127
|
-
logger.error({ error: error.message }, 'Error clearing requests');
|
|
128
|
-
res.status(500).json({ error: 'Failed to clear traffic', details: error.message });
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
|
-
router.exportRequests = (req, res) => {
|
|
133
|
-
try {
|
|
134
|
-
// Sanitize search parameter - convert empty strings to null
|
|
135
|
-
const search = sanitizeSearch(req.query.search);
|
|
136
|
-
|
|
137
|
-
const filters = {
|
|
138
|
-
sessionId: req.query.sessionId || null,
|
|
139
|
-
direction: req.query.direction || null,
|
|
140
|
-
method: req.query.method || null,
|
|
141
|
-
jsonrpcMethod: req.query.jsonrpcMethod || null,
|
|
142
|
-
statusCode: req.query.statusCode ? Number.parseInt(req.query.statusCode) : null,
|
|
143
|
-
jsonrpcId: req.query.jsonrpcId || null,
|
|
144
|
-
search: search,
|
|
145
|
-
serverName: req.query.serverName || null,
|
|
146
|
-
startTime: req.query.startTime ? BigInt(req.query.startTime) : null,
|
|
147
|
-
endTime: req.query.endTime ? BigInt(req.query.endTime) : null,
|
|
148
|
-
limit: 100000,
|
|
149
|
-
offset: 0,
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const requests = queryRequests(db, filters);
|
|
153
|
-
const format = req.query.format || 'json';
|
|
154
|
-
|
|
155
|
-
const formatExport = (requests, format) => {
|
|
156
|
-
if (format === 'csv') {
|
|
157
|
-
const headers = [
|
|
158
|
-
'Frame',
|
|
159
|
-
'Time',
|
|
160
|
-
'Source',
|
|
161
|
-
'Destination',
|
|
162
|
-
'Protocol',
|
|
163
|
-
'Length',
|
|
164
|
-
'Method',
|
|
165
|
-
'Status',
|
|
166
|
-
'JSON-RPC Method',
|
|
167
|
-
'Session ID',
|
|
168
|
-
'Server Name',
|
|
169
|
-
];
|
|
170
|
-
const rows = requests.map((req) => [
|
|
171
|
-
req.frame_number || '',
|
|
172
|
-
req.timestamp_iso || '',
|
|
173
|
-
req.request?.host || '',
|
|
174
|
-
req.request?.host || '',
|
|
175
|
-
'HTTP',
|
|
176
|
-
req.length || '',
|
|
177
|
-
req.request?.method || '',
|
|
178
|
-
req.response?.status_code || '',
|
|
179
|
-
req.jsonrpc_method || '',
|
|
180
|
-
req.session_id || '',
|
|
181
|
-
req.server_name || '',
|
|
182
|
-
]);
|
|
183
|
-
|
|
184
|
-
const content = [
|
|
185
|
-
headers.join(','),
|
|
186
|
-
...rows.map((row) =>
|
|
187
|
-
row.map((cell) => `"${String(cell).replace(/"/g, '""')}"`).join(',')
|
|
188
|
-
),
|
|
189
|
-
].join('\n');
|
|
190
|
-
return { content, contentType: 'text/csv', extension: 'csv' };
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (format === 'txt') {
|
|
194
|
-
const content = requests
|
|
195
|
-
.map((req, idx) => {
|
|
196
|
-
const lines = [
|
|
197
|
-
`=== Request/Response #${idx + 1} (Frame ${req.frame_number || 'N/A'}) ===`,
|
|
198
|
-
`Time: ${req.timestamp_iso || 'N/A'}`,
|
|
199
|
-
`Session ID: ${req.session_id || 'N/A'}`,
|
|
200
|
-
`Server: ${req.server_name || 'N/A'}`,
|
|
201
|
-
`Direction: ${req.direction || 'N/A'}`,
|
|
202
|
-
`Method: ${req.request?.method || 'N/A'}`,
|
|
203
|
-
`Status: ${req.response?.status_code || 'N/A'}`,
|
|
204
|
-
`JSON-RPC Method: ${req.jsonrpc_method || 'N/A'}`,
|
|
205
|
-
`JSON-RPC ID: ${req.jsonrpc_id || 'N/A'}`,
|
|
206
|
-
`Length: ${req.length || 0} bytes`,
|
|
207
|
-
'',
|
|
208
|
-
'Request:',
|
|
209
|
-
JSON.stringify(req.request || {}, null, 2),
|
|
210
|
-
'',
|
|
211
|
-
'Response:',
|
|
212
|
-
JSON.stringify(req.response || {}, null, 2),
|
|
213
|
-
'',
|
|
214
|
-
'---',
|
|
215
|
-
'',
|
|
216
|
-
];
|
|
217
|
-
return lines.join('\n');
|
|
218
|
-
})
|
|
219
|
-
.join('\n');
|
|
220
|
-
return { content, contentType: 'text/plain', extension: 'txt' };
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const content = JSON.stringify(serializeBigInt(requests), null, 2);
|
|
224
|
-
return { content, contentType: 'application/json', extension: 'json' };
|
|
225
|
-
};
|
|
226
|
-
|
|
227
|
-
const { content, contentType, extension } = formatExport(requests, format);
|
|
11
|
+
const router = {};
|
|
228
12
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
} catch (error) {
|
|
234
|
-
res.status(500).json({ error: 'Failed to export traffic', details: error.message });
|
|
235
|
-
}
|
|
236
|
-
};
|
|
13
|
+
router.getRequests = (req, res) => controller.getRequests(req, res);
|
|
14
|
+
router.getRequest = (req, res) => controller.getRequest(req, res);
|
|
15
|
+
router.clearRequests = (req, res) => controller.clearRequests(req, res);
|
|
16
|
+
router.exportRequests = (req, res) => controller.exportRequests(req, res);
|
|
237
17
|
|
|
238
18
|
return router;
|
|
239
19
|
}
|
|
@@ -1,27 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { serializeBigInt } from '../utils/serialization.js';
|
|
1
|
+
import { SessionController } from '../controllers/SessionController.js';
|
|
3
2
|
|
|
4
|
-
export function createSessionsRoutes(
|
|
5
|
-
const
|
|
3
|
+
export function createSessionsRoutes(container) {
|
|
4
|
+
const sessionService = container.getService('session');
|
|
5
|
+
const serializationLib = container.getLibrary('serialization');
|
|
6
|
+
const logger = container.getLibrary('logger');
|
|
7
|
+
|
|
8
|
+
const controller = new SessionController(sessionService, serializationLib, logger);
|
|
6
9
|
|
|
7
|
-
router
|
|
8
|
-
const limit = Number.parseInt(req.query.limit) || 1000;
|
|
9
|
-
const offset = Number.parseInt(req.query.offset) || 0;
|
|
10
|
-
const filters = {
|
|
11
|
-
startTime: req.query.startTime ? BigInt(req.query.startTime) : null,
|
|
12
|
-
endTime: req.query.endTime ? BigInt(req.query.endTime) : null,
|
|
13
|
-
limit,
|
|
14
|
-
offset,
|
|
15
|
-
};
|
|
16
|
-
const sessions = getSessions(db, filters);
|
|
17
|
-
res.json(serializeBigInt(sessions));
|
|
18
|
-
};
|
|
10
|
+
const router = {};
|
|
19
11
|
|
|
20
|
-
router.
|
|
21
|
-
|
|
22
|
-
const requests = getSessionRequests(db, req.params.sessionId, limit);
|
|
23
|
-
res.json(serializeBigInt(requests));
|
|
24
|
-
};
|
|
12
|
+
router.getSessions = (req, res) => controller.getSessions(req, res);
|
|
13
|
+
router.getSessionRequests = (req, res) => controller.getSessionRequests(req, res);
|
|
25
14
|
|
|
26
15
|
return router;
|
|
27
16
|
}
|
|
@@ -1,199 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
|
-
import { join } from 'node:path';
|
|
4
|
-
import { getDatabaseFile, getWorkingDirectory } from '#common/configs';
|
|
5
|
-
import logger from '../utils/logger.js';
|
|
6
|
-
import { getScanResultsDirectory } from '../utils/scan-cache/directory.js';
|
|
1
|
+
import { SettingsController } from '#ui/server/controllers/index.js';
|
|
7
2
|
|
|
8
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Create settings routes
|
|
5
|
+
* Routes delegate to SettingsController which calls SettingsService
|
|
6
|
+
*/
|
|
7
|
+
export function createSettingsRoutes(container) {
|
|
8
|
+
const settingsService = container.getService('settings');
|
|
9
|
+
const logger = container.getLibrary('logger');
|
|
10
|
+
const settingsController = new SettingsController(settingsService, logger);
|
|
9
11
|
|
|
10
|
-
function getSmartScanTokenPath() {
|
|
11
|
-
return join(getWorkingDirectory(), SMART_SCAN_TOKEN_NAME);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
function getTokenMetadata() {
|
|
15
|
-
try {
|
|
16
|
-
const tokenPath = getSmartScanTokenPath();
|
|
17
|
-
if (existsSync(tokenPath)) {
|
|
18
|
-
const content = readFileSync(tokenPath, 'utf8');
|
|
19
|
-
const data = JSON.parse(content);
|
|
20
|
-
const stats = statSync(tokenPath);
|
|
21
|
-
return {
|
|
22
|
-
token: data.token || null,
|
|
23
|
-
updatedAt: data.updatedAt || stats.mtime.toISOString(),
|
|
24
|
-
path: tokenPath,
|
|
25
|
-
exists: true,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
token: null,
|
|
30
|
-
updatedAt: null,
|
|
31
|
-
path: tokenPath,
|
|
32
|
-
exists: false,
|
|
33
|
-
};
|
|
34
|
-
} catch (error) {
|
|
35
|
-
logger.error({ error: error.message }, 'Error reading Smart Scan token metadata');
|
|
36
|
-
return {
|
|
37
|
-
token: null,
|
|
38
|
-
updatedAt: null,
|
|
39
|
-
path: getSmartScanTokenPath(),
|
|
40
|
-
exists: false,
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function getBackupCount() {
|
|
46
|
-
try {
|
|
47
|
-
const homeDir = homedir();
|
|
48
|
-
const backupDirs = [join(homeDir, '.cursor'), join(homeDir, '.codeium', 'windsurf')];
|
|
49
|
-
|
|
50
|
-
const newFormatCount = backupDirs.reduce((count, dir) => {
|
|
51
|
-
if (existsSync(dir)) {
|
|
52
|
-
const files = readdirSync(dir);
|
|
53
|
-
const matchingFiles = files.filter((file) => {
|
|
54
|
-
return /^\.(.+)-mcpshark\.\d{4}-\d{2}-\d{2}_\d{2}-\d{2}-\d{2}\.json$/.test(file);
|
|
55
|
-
});
|
|
56
|
-
return count + matchingFiles.length;
|
|
57
|
-
}
|
|
58
|
-
return count;
|
|
59
|
-
}, 0);
|
|
60
|
-
|
|
61
|
-
// Also count old .backup format
|
|
62
|
-
const commonPaths = [
|
|
63
|
-
join(homeDir, '.cursor', 'mcp.json'),
|
|
64
|
-
join(homeDir, '.codeium', 'windsurf', 'mcp_config.json'),
|
|
65
|
-
];
|
|
66
|
-
const oldFormatCount = commonPaths.reduce((count, configPath) => {
|
|
67
|
-
if (existsSync(`${configPath}.backup`)) {
|
|
68
|
-
return count + 1;
|
|
69
|
-
}
|
|
70
|
-
return count;
|
|
71
|
-
}, 0);
|
|
72
|
-
|
|
73
|
-
return newFormatCount + oldFormatCount;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
logger.error({ error: error.message }, 'Error counting backups');
|
|
76
|
-
return 0;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
function toDisplayPath(absolutePath) {
|
|
81
|
-
const homeDir = homedir();
|
|
82
|
-
return absolutePath.replace(homeDir, '~');
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
export function createSettingsRoutes() {
|
|
86
12
|
const router = {};
|
|
87
13
|
|
|
88
|
-
router.getSettings =
|
|
89
|
-
try {
|
|
90
|
-
const homeDir = homedir();
|
|
91
|
-
const workingDir = getWorkingDirectory();
|
|
92
|
-
const databasePath = getDatabaseFile();
|
|
93
|
-
const scanResultsDir = getScanResultsDirectory();
|
|
94
|
-
const tokenPath = getSmartScanTokenPath();
|
|
95
|
-
const tokenMetadata = getTokenMetadata();
|
|
96
|
-
|
|
97
|
-
const cursorConfigPath = join(homeDir, '.cursor', 'mcp.json');
|
|
98
|
-
const windsurfConfigPath = join(homeDir, '.codeium', 'windsurf', 'mcp_config.json');
|
|
99
|
-
|
|
100
|
-
const cursorBackupDir = join(homeDir, '.cursor');
|
|
101
|
-
const windsurfBackupDir = join(homeDir, '.codeium', 'windsurf');
|
|
102
|
-
|
|
103
|
-
const settings = {
|
|
104
|
-
paths: {
|
|
105
|
-
workingDirectory: {
|
|
106
|
-
absolute: workingDir,
|
|
107
|
-
display: toDisplayPath(workingDir),
|
|
108
|
-
exists: existsSync(workingDir),
|
|
109
|
-
},
|
|
110
|
-
database: {
|
|
111
|
-
absolute: databasePath,
|
|
112
|
-
display: toDisplayPath(databasePath),
|
|
113
|
-
exists: existsSync(databasePath),
|
|
114
|
-
},
|
|
115
|
-
smartScanResults: {
|
|
116
|
-
absolute: scanResultsDir,
|
|
117
|
-
display: toDisplayPath(scanResultsDir),
|
|
118
|
-
exists: existsSync(scanResultsDir),
|
|
119
|
-
},
|
|
120
|
-
smartScanToken: {
|
|
121
|
-
absolute: tokenPath,
|
|
122
|
-
display: toDisplayPath(tokenPath),
|
|
123
|
-
exists: tokenMetadata.exists,
|
|
124
|
-
},
|
|
125
|
-
backupDirectories: {
|
|
126
|
-
cursor: {
|
|
127
|
-
absolute: cursorBackupDir,
|
|
128
|
-
display: toDisplayPath(cursorBackupDir),
|
|
129
|
-
exists: existsSync(cursorBackupDir),
|
|
130
|
-
},
|
|
131
|
-
windsurf: {
|
|
132
|
-
absolute: windsurfBackupDir,
|
|
133
|
-
display: toDisplayPath(windsurfBackupDir),
|
|
134
|
-
exists: existsSync(windsurfBackupDir),
|
|
135
|
-
},
|
|
136
|
-
},
|
|
137
|
-
configFiles: {
|
|
138
|
-
cursor: {
|
|
139
|
-
absolute: cursorConfigPath,
|
|
140
|
-
display: toDisplayPath(cursorConfigPath),
|
|
141
|
-
exists: existsSync(cursorConfigPath),
|
|
142
|
-
},
|
|
143
|
-
windsurf: {
|
|
144
|
-
absolute: windsurfConfigPath,
|
|
145
|
-
display: toDisplayPath(windsurfConfigPath),
|
|
146
|
-
exists: existsSync(windsurfConfigPath),
|
|
147
|
-
},
|
|
148
|
-
},
|
|
149
|
-
},
|
|
150
|
-
smartScan: {
|
|
151
|
-
token: tokenMetadata.token,
|
|
152
|
-
tokenPath: {
|
|
153
|
-
absolute: tokenMetadata.path,
|
|
154
|
-
display: toDisplayPath(tokenMetadata.path),
|
|
155
|
-
},
|
|
156
|
-
tokenUpdatedAt: tokenMetadata.updatedAt,
|
|
157
|
-
tokenExists: tokenMetadata.exists,
|
|
158
|
-
},
|
|
159
|
-
database: {
|
|
160
|
-
path: {
|
|
161
|
-
absolute: databasePath,
|
|
162
|
-
display: toDisplayPath(databasePath),
|
|
163
|
-
},
|
|
164
|
-
exists: existsSync(databasePath),
|
|
165
|
-
},
|
|
166
|
-
system: {
|
|
167
|
-
platform: process.platform,
|
|
168
|
-
homeDirectory: {
|
|
169
|
-
absolute: homeDir,
|
|
170
|
-
display: '~',
|
|
171
|
-
},
|
|
172
|
-
},
|
|
173
|
-
backups: {
|
|
174
|
-
directories: [
|
|
175
|
-
{
|
|
176
|
-
absolute: cursorBackupDir,
|
|
177
|
-
display: toDisplayPath(cursorBackupDir),
|
|
178
|
-
},
|
|
179
|
-
{
|
|
180
|
-
absolute: windsurfBackupDir,
|
|
181
|
-
display: toDisplayPath(windsurfBackupDir),
|
|
182
|
-
},
|
|
183
|
-
],
|
|
184
|
-
count: getBackupCount(),
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
res.json(settings);
|
|
189
|
-
} catch (error) {
|
|
190
|
-
logger.error({ error: error.message }, 'Error getting settings');
|
|
191
|
-
res.status(500).json({
|
|
192
|
-
error: 'Failed to get settings',
|
|
193
|
-
details: error.message,
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
};
|
|
14
|
+
router.getSettings = settingsController.getSettings;
|
|
197
15
|
|
|
198
16
|
return router;
|
|
199
17
|
}
|
|
@@ -1,24 +1,35 @@
|
|
|
1
|
+
import {
|
|
2
|
+
McpDiscoveryController,
|
|
3
|
+
ScanController,
|
|
4
|
+
TokenController,
|
|
5
|
+
} from '#ui/server/controllers/index.js';
|
|
6
|
+
|
|
1
7
|
/**
|
|
2
|
-
* Smart Scan
|
|
3
|
-
*
|
|
8
|
+
* Create Smart Scan routes
|
|
9
|
+
* Routes delegate to controllers which call services
|
|
4
10
|
*/
|
|
11
|
+
export function createSmartScanRoutes(container) {
|
|
12
|
+
const scanService = container.getService('scan');
|
|
13
|
+
const scanCacheService = container.getService('scanCache');
|
|
14
|
+
const mcpDiscoveryService = container.getService('mcpDiscovery');
|
|
15
|
+
const tokenService = container.getService('token');
|
|
16
|
+
const logger = container.getLibrary('logger');
|
|
5
17
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
18
|
+
const scanController = new ScanController(scanService, scanCacheService, logger);
|
|
19
|
+
const mcpDiscoveryController = new McpDiscoveryController(mcpDiscoveryService, logger);
|
|
20
|
+
const tokenController = new TokenController(tokenService, logger);
|
|
9
21
|
|
|
10
|
-
export function createSmartScanRoutes() {
|
|
11
22
|
const router = {};
|
|
12
23
|
|
|
13
|
-
router.getToken =
|
|
14
|
-
router.saveToken =
|
|
15
|
-
router.discoverServers =
|
|
16
|
-
router.getCachedResults =
|
|
17
|
-
router.createScan =
|
|
18
|
-
router.getScan =
|
|
19
|
-
router.listScans =
|
|
20
|
-
router.createBatchScans =
|
|
21
|
-
router.clearCache =
|
|
24
|
+
router.getToken = tokenController.getToken;
|
|
25
|
+
router.saveToken = tokenController.saveToken;
|
|
26
|
+
router.discoverServers = mcpDiscoveryController.discoverServers;
|
|
27
|
+
router.getCachedResults = scanController.getCachedResults;
|
|
28
|
+
router.createScan = scanController.createScan;
|
|
29
|
+
router.getScan = scanController.getScan;
|
|
30
|
+
router.listScans = scanController.listScans;
|
|
31
|
+
router.createBatchScans = scanController.createBatchScans;
|
|
32
|
+
router.clearCache = scanController.clearCache;
|
|
22
33
|
|
|
23
34
|
return router;
|
|
24
35
|
}
|
|
@@ -1,86 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import logger from '../utils/logger.js';
|
|
3
|
-
import { serializeBigInt } from '../utils/serialization.js';
|
|
1
|
+
import { StatisticsController } from '../controllers/StatisticsController.js';
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
return null;
|
|
11
|
-
};
|
|
3
|
+
export function createStatisticsRoutes(container) {
|
|
4
|
+
const statisticsService = container.getService('statistics');
|
|
5
|
+
const serializationLib = container.getLibrary('serialization');
|
|
6
|
+
const logger = container.getLibrary('logger');
|
|
12
7
|
|
|
13
|
-
|
|
14
|
-
const router = {};
|
|
15
|
-
|
|
16
|
-
router.getStatistics = (req, res) => {
|
|
17
|
-
try {
|
|
18
|
-
// Sanitize search parameter - convert empty strings to null
|
|
19
|
-
const search = sanitizeSearch(req.query.search);
|
|
20
|
-
|
|
21
|
-
// Build filters object matching the requests route
|
|
22
|
-
const filters = {
|
|
23
|
-
sessionId: (req.query.sessionId && String(req.query.sessionId).trim()) || null,
|
|
24
|
-
direction: (req.query.direction && String(req.query.direction).trim()) || null,
|
|
25
|
-
method: (req.query.method && String(req.query.method).trim()) || null,
|
|
26
|
-
jsonrpcMethod: (req.query.jsonrpcMethod && String(req.query.jsonrpcMethod).trim()) || null,
|
|
27
|
-
statusCode: req.query.statusCode ? Number.parseInt(req.query.statusCode) : null,
|
|
28
|
-
jsonrpcId: (req.query.jsonrpcId && String(req.query.jsonrpcId).trim()) || null,
|
|
29
|
-
search: search,
|
|
30
|
-
serverName: (req.query.serverName && String(req.query.serverName).trim()) || null,
|
|
31
|
-
startTime: req.query.startTime ? BigInt(req.query.startTime) : null,
|
|
32
|
-
endTime: req.query.endTime ? BigInt(req.query.endTime) : null,
|
|
33
|
-
limit: 1000000, // Large limit for accurate statistics
|
|
34
|
-
offset: 0,
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Remove undefined values to avoid issues
|
|
38
|
-
Object.keys(filters).forEach((key) => {
|
|
39
|
-
if (filters[key] === undefined) {
|
|
40
|
-
filters[key] = null;
|
|
41
|
-
}
|
|
42
|
-
});
|
|
8
|
+
const controller = new StatisticsController(statisticsService, serializationLib, logger);
|
|
43
9
|
|
|
44
|
-
|
|
45
|
-
const allRequests = queryRequests(db, filters);
|
|
46
|
-
|
|
47
|
-
// Calculate statistics from filtered requests
|
|
48
|
-
const totalPackets = allRequests.length;
|
|
49
|
-
const totalRequests = allRequests.filter((r) => r.direction === 'request').length;
|
|
50
|
-
const totalResponses = allRequests.filter((r) => r.direction === 'response').length;
|
|
51
|
-
const totalErrors = allRequests.filter((r) => {
|
|
52
|
-
if (r.direction === 'response') {
|
|
53
|
-
const statusCode = r.status_code || r.status;
|
|
54
|
-
return (
|
|
55
|
-
statusCode >= 400 ||
|
|
56
|
-
(r.body_json && typeof r.body_json === 'object' && r.body_json.error)
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
return false;
|
|
60
|
-
}).length;
|
|
61
|
-
|
|
62
|
-
// Get unique sessions
|
|
63
|
-
const uniqueSessions = new Set();
|
|
64
|
-
allRequests.forEach((r) => {
|
|
65
|
-
if (r.session_id) {
|
|
66
|
-
uniqueSessions.add(r.session_id);
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
const stats = {
|
|
71
|
-
total_packets: totalPackets,
|
|
72
|
-
total_requests: totalRequests,
|
|
73
|
-
total_responses: totalResponses,
|
|
74
|
-
total_errors: totalErrors,
|
|
75
|
-
unique_sessions: uniqueSessions.size,
|
|
76
|
-
};
|
|
10
|
+
const router = {};
|
|
77
11
|
|
|
78
|
-
|
|
79
|
-
} catch (error) {
|
|
80
|
-
logger.error({ error: error.message }, 'Error in getStatistics');
|
|
81
|
-
res.status(500).json({ error: 'Failed to get statistics', details: error.message });
|
|
82
|
-
}
|
|
83
|
-
};
|
|
12
|
+
router.getStatistics = (req, res) => controller.getStatistics(req, res);
|
|
84
13
|
|
|
85
14
|
return router;
|
|
86
15
|
}
|