@mcp-shark/mcp-shark 1.5.4 → 1.5.6
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 +154 -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 +63 -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 +163 -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 +205 -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 -138
- 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
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Scan endpoints - Aggregates all Smart Scan path definitions
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { discoveryPaths } from './discovery.js';
|
|
6
|
+
import { scansPaths } from './scans.js';
|
|
7
|
+
import { tokenPaths } from './token.js';
|
|
8
|
+
|
|
9
|
+
export const smartScanPaths = {
|
|
10
|
+
...scansPaths,
|
|
11
|
+
...tokenPaths,
|
|
12
|
+
...discoveryPaths,
|
|
13
|
+
};
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Scan - Scan endpoints
|
|
3
|
+
* Create, list, and retrieve scan results
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const scansPaths = {
|
|
7
|
+
'/api/smartscan/scans': {
|
|
8
|
+
get: {
|
|
9
|
+
tags: ['Smart Scan'],
|
|
10
|
+
summary: 'List scans',
|
|
11
|
+
description: 'Get a list of all cached Smart Scan results',
|
|
12
|
+
responses: {
|
|
13
|
+
200: {
|
|
14
|
+
description: 'List of scans',
|
|
15
|
+
content: {
|
|
16
|
+
'application/json': {
|
|
17
|
+
schema: {
|
|
18
|
+
type: 'array',
|
|
19
|
+
items: { $ref: '#/components/schemas/Scan' },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
500: {
|
|
25
|
+
description: 'Internal server error',
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
post: {
|
|
30
|
+
tags: ['Smart Scan'],
|
|
31
|
+
summary: 'Create scan',
|
|
32
|
+
description: 'Create a new Smart Scan for an MCP server',
|
|
33
|
+
requestBody: {
|
|
34
|
+
required: true,
|
|
35
|
+
content: {
|
|
36
|
+
'application/json': {
|
|
37
|
+
schema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
required: ['apiToken', 'scanData'],
|
|
40
|
+
properties: {
|
|
41
|
+
apiToken: { type: 'string', description: 'Smart Scan API token' },
|
|
42
|
+
scanData: {
|
|
43
|
+
type: 'object',
|
|
44
|
+
description: 'Scan configuration data',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
responses: {
|
|
52
|
+
200: {
|
|
53
|
+
description: 'Scan created',
|
|
54
|
+
content: {
|
|
55
|
+
'application/json': {
|
|
56
|
+
schema: { $ref: '#/components/schemas/Scan' },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
400: {
|
|
61
|
+
description: 'Bad request',
|
|
62
|
+
},
|
|
63
|
+
500: {
|
|
64
|
+
description: 'Internal server error',
|
|
65
|
+
},
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
'/api/smartscan/scans/{scanId}': {
|
|
70
|
+
get: {
|
|
71
|
+
tags: ['Smart Scan'],
|
|
72
|
+
summary: 'Get scan',
|
|
73
|
+
description: 'Get details of a specific scan',
|
|
74
|
+
parameters: [
|
|
75
|
+
{
|
|
76
|
+
name: 'scanId',
|
|
77
|
+
in: 'path',
|
|
78
|
+
required: true,
|
|
79
|
+
description: 'Scan ID',
|
|
80
|
+
schema: { type: 'string' },
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
responses: {
|
|
84
|
+
200: {
|
|
85
|
+
description: 'Scan details',
|
|
86
|
+
content: {
|
|
87
|
+
'application/json': {
|
|
88
|
+
schema: { $ref: '#/components/schemas/Scan' },
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
404: {
|
|
93
|
+
description: 'Scan not found',
|
|
94
|
+
},
|
|
95
|
+
500: {
|
|
96
|
+
description: 'Internal server error',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
'/api/smartscan/scans/batch': {
|
|
102
|
+
post: {
|
|
103
|
+
tags: ['Smart Scan'],
|
|
104
|
+
summary: 'Create batch scans',
|
|
105
|
+
description: 'Create multiple scans for multiple servers',
|
|
106
|
+
requestBody: {
|
|
107
|
+
required: true,
|
|
108
|
+
content: {
|
|
109
|
+
'application/json': {
|
|
110
|
+
schema: {
|
|
111
|
+
type: 'object',
|
|
112
|
+
required: ['apiToken', 'servers'],
|
|
113
|
+
properties: {
|
|
114
|
+
apiToken: { type: 'string', description: 'Smart Scan API token' },
|
|
115
|
+
servers: {
|
|
116
|
+
type: 'array',
|
|
117
|
+
items: { type: 'object' },
|
|
118
|
+
description: 'List of server configurations to scan',
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
responses: {
|
|
126
|
+
200: {
|
|
127
|
+
description: 'Batch scans created',
|
|
128
|
+
content: {
|
|
129
|
+
'application/json': {
|
|
130
|
+
schema: {
|
|
131
|
+
type: 'object',
|
|
132
|
+
properties: {
|
|
133
|
+
scans: {
|
|
134
|
+
type: 'array',
|
|
135
|
+
items: { $ref: '#/components/schemas/Scan' },
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
400: {
|
|
143
|
+
description: 'Bad request',
|
|
144
|
+
},
|
|
145
|
+
500: {
|
|
146
|
+
description: 'Internal server error',
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Smart Scan - Token management endpoints
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const tokenPaths = {
|
|
6
|
+
'/api/smartscan/token': {
|
|
7
|
+
get: {
|
|
8
|
+
tags: ['Smart Scan'],
|
|
9
|
+
summary: 'Get API token',
|
|
10
|
+
description: 'Get the stored Smart Scan API token',
|
|
11
|
+
responses: {
|
|
12
|
+
200: {
|
|
13
|
+
description: 'API token',
|
|
14
|
+
content: {
|
|
15
|
+
'application/json': {
|
|
16
|
+
schema: {
|
|
17
|
+
type: 'object',
|
|
18
|
+
properties: {
|
|
19
|
+
token: { type: 'string', nullable: true },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
500: {
|
|
26
|
+
description: 'Internal server error',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
post: {
|
|
31
|
+
tags: ['Smart Scan'],
|
|
32
|
+
summary: 'Save API token',
|
|
33
|
+
description: 'Save the Smart Scan API token',
|
|
34
|
+
requestBody: {
|
|
35
|
+
required: true,
|
|
36
|
+
content: {
|
|
37
|
+
'application/json': {
|
|
38
|
+
schema: {
|
|
39
|
+
type: 'object',
|
|
40
|
+
required: ['token'],
|
|
41
|
+
properties: {
|
|
42
|
+
token: { type: 'string', description: 'Smart Scan API token' },
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
responses: {
|
|
49
|
+
200: {
|
|
50
|
+
description: 'Token saved',
|
|
51
|
+
content: {
|
|
52
|
+
'application/json': {
|
|
53
|
+
schema: {
|
|
54
|
+
type: 'object',
|
|
55
|
+
properties: {
|
|
56
|
+
success: { type: 'boolean' },
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
400: {
|
|
63
|
+
description: 'Bad request',
|
|
64
|
+
},
|
|
65
|
+
500: {
|
|
66
|
+
description: 'Internal server error',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Statistics endpoints - Traffic statistics and analytics
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const statisticsPaths = {
|
|
6
|
+
'/api/statistics': {
|
|
7
|
+
get: {
|
|
8
|
+
tags: ['Statistics'],
|
|
9
|
+
summary: 'Get traffic statistics',
|
|
10
|
+
description: 'Retrieve aggregated statistics about captured traffic',
|
|
11
|
+
parameters: [
|
|
12
|
+
{
|
|
13
|
+
name: 'sessionId',
|
|
14
|
+
in: 'query',
|
|
15
|
+
description: 'Filter by session ID',
|
|
16
|
+
schema: { type: 'string' },
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
name: 'serverName',
|
|
20
|
+
in: 'query',
|
|
21
|
+
description: 'Filter by server name',
|
|
22
|
+
schema: { type: 'string' },
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
responses: {
|
|
26
|
+
200: {
|
|
27
|
+
description: 'Traffic statistics',
|
|
28
|
+
content: {
|
|
29
|
+
'application/json': {
|
|
30
|
+
schema: { $ref: '#/components/schemas/Statistics' },
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
500: {
|
|
35
|
+
description: 'Internal server error',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swagger/OpenAPI path definitions for MCP Shark API
|
|
3
|
+
* Aggregates all endpoint documentation from individual files
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { backupsPaths } from './paths/backups.js';
|
|
7
|
+
import { components } from './paths/components.js';
|
|
8
|
+
import { configPaths } from './paths/config.js';
|
|
9
|
+
import { conversationsPaths } from './paths/conversations.js';
|
|
10
|
+
import { helpPaths } from './paths/help.js';
|
|
11
|
+
import { logsPaths } from './paths/logs.js';
|
|
12
|
+
import { playgroundPaths } from './paths/playground.js';
|
|
13
|
+
import { requestsPaths } from './paths/requests.js';
|
|
14
|
+
import { serverManagementPaths } from './paths/serverManagement.js';
|
|
15
|
+
import { sessionsPaths } from './paths/sessions.js';
|
|
16
|
+
import { settingsPaths } from './paths/settings.js';
|
|
17
|
+
import { smartScanPaths } from './paths/smartScan/index.js';
|
|
18
|
+
import { statisticsPaths } from './paths/statistics.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Combine all path definitions into a single object
|
|
22
|
+
*/
|
|
23
|
+
export const paths = {
|
|
24
|
+
...requestsPaths,
|
|
25
|
+
...sessionsPaths,
|
|
26
|
+
...conversationsPaths,
|
|
27
|
+
...statisticsPaths,
|
|
28
|
+
...logsPaths,
|
|
29
|
+
...configPaths,
|
|
30
|
+
...backupsPaths,
|
|
31
|
+
...serverManagementPaths,
|
|
32
|
+
...helpPaths,
|
|
33
|
+
...playgroundPaths,
|
|
34
|
+
...smartScanPaths,
|
|
35
|
+
...settingsPaths,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { components };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { components, paths } from './paths.js';
|
|
2
|
+
|
|
3
|
+
export const swaggerSpec = {
|
|
4
|
+
openapi: '3.0.0',
|
|
5
|
+
info: {
|
|
6
|
+
title: 'MCP Shark API',
|
|
7
|
+
version: '1.5.4',
|
|
8
|
+
description:
|
|
9
|
+
'API documentation for MCP Shark - A powerful monitoring and debugging tool for Model Context Protocol (MCP) servers. Provides deep visibility into every request and response.',
|
|
10
|
+
contact: {
|
|
11
|
+
name: 'MCP Shark',
|
|
12
|
+
url: 'https://mcpshark.sh',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
servers: [
|
|
16
|
+
{
|
|
17
|
+
url: 'http://localhost:9853',
|
|
18
|
+
description: 'Development server',
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
tags: [
|
|
22
|
+
{ name: 'Requests', description: 'Traffic capture and request/response analysis' },
|
|
23
|
+
{ name: 'Sessions', description: 'Session management and tracking' },
|
|
24
|
+
{ name: 'Conversations', description: 'Conversation tracking and analysis' },
|
|
25
|
+
{ name: 'Statistics', description: 'Traffic statistics and analytics' },
|
|
26
|
+
{ name: 'Logs', description: 'MCP Shark server logs' },
|
|
27
|
+
{ name: 'Config', description: 'Configuration file management' },
|
|
28
|
+
{ name: 'Backups', description: 'Configuration backup management' },
|
|
29
|
+
{ name: 'Server Management', description: 'MCP Shark server lifecycle management' },
|
|
30
|
+
{ name: 'Help', description: 'Help and tour management' },
|
|
31
|
+
{ name: 'Playground', description: 'MCP playground for testing tools and resources' },
|
|
32
|
+
{ name: 'Smart Scan', description: 'AI-powered security analysis for MCP servers' },
|
|
33
|
+
{ name: 'Settings', description: 'Application settings' },
|
|
34
|
+
],
|
|
35
|
+
paths,
|
|
36
|
+
components,
|
|
37
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Perform cleanup operations on shutdown
|
|
3
|
+
* @param {number} intervalId - Interval ID to clear
|
|
4
|
+
* @param {object} processState - Process state object
|
|
5
|
+
* @param {Set} clients - Set of WebSocket clients
|
|
6
|
+
* @param {WebSocketServer} wss - WebSocket server instance
|
|
7
|
+
* @param {object} server - HTTP server instance
|
|
8
|
+
* @param {object} container - Dependency container
|
|
9
|
+
* @param {object} logger - Logger instance
|
|
10
|
+
* @returns {Promise} Promise that resolves when cleanup is complete
|
|
11
|
+
*/
|
|
12
|
+
export async function performCleanup(
|
|
13
|
+
intervalId,
|
|
14
|
+
processState,
|
|
15
|
+
clients,
|
|
16
|
+
wss,
|
|
17
|
+
server,
|
|
18
|
+
container,
|
|
19
|
+
logger
|
|
20
|
+
) {
|
|
21
|
+
logger?.info('Shutting down UI server...');
|
|
22
|
+
|
|
23
|
+
// Clear interval
|
|
24
|
+
clearInterval(intervalId);
|
|
25
|
+
|
|
26
|
+
// Stop MCP Shark server if running and restore config
|
|
27
|
+
// Use ServerManagementService to ensure proper cleanup and config restoration
|
|
28
|
+
try {
|
|
29
|
+
const serverManagementService = container.getService('serverManagement');
|
|
30
|
+
const serverStatus = serverManagementService.getServerStatus();
|
|
31
|
+
|
|
32
|
+
if (serverStatus.running) {
|
|
33
|
+
logger?.info('Stopping MCP Shark server...');
|
|
34
|
+
try {
|
|
35
|
+
await serverManagementService.stopServer();
|
|
36
|
+
logger?.info('MCP Shark server stopped');
|
|
37
|
+
} catch (stopErr) {
|
|
38
|
+
logger?.warn(
|
|
39
|
+
{ error: stopErr.message },
|
|
40
|
+
'Error stopping MCP Shark server, continuing with cleanup'
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
} catch (err) {
|
|
45
|
+
logger?.warn(
|
|
46
|
+
{ error: err.message },
|
|
47
|
+
'Error accessing server management service during shutdown'
|
|
48
|
+
);
|
|
49
|
+
// Continue with cleanup even if server stop fails
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Restore config (always attempt, even if server stop failed)
|
|
53
|
+
// This ensures patched configs are restored on exit
|
|
54
|
+
try {
|
|
55
|
+
const configService = container.getService('config');
|
|
56
|
+
const restored = configService.restoreOriginalConfig();
|
|
57
|
+
if (restored) {
|
|
58
|
+
logger?.info('Config restored successfully');
|
|
59
|
+
}
|
|
60
|
+
} catch (configErr) {
|
|
61
|
+
logger?.warn({ error: configErr.message }, 'Failed to restore config during shutdown');
|
|
62
|
+
// Continue anyway - config restoration failure shouldn't prevent exit
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Clear process state
|
|
66
|
+
processState.mcpSharkServer = null;
|
|
67
|
+
|
|
68
|
+
// Close WebSocket connections
|
|
69
|
+
try {
|
|
70
|
+
for (const client of clients) {
|
|
71
|
+
if (client.readyState === 1) {
|
|
72
|
+
client.close();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
clients.clear();
|
|
76
|
+
} catch (err) {
|
|
77
|
+
logger?.warn({ error: err.message }, 'Error closing WebSocket connections');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Close WebSocket server
|
|
81
|
+
try {
|
|
82
|
+
wss.close();
|
|
83
|
+
} catch (err) {
|
|
84
|
+
logger?.warn({ error: err.message }, 'Error closing WebSocket server');
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Close HTTP server
|
|
88
|
+
return new Promise((resolve) => {
|
|
89
|
+
try {
|
|
90
|
+
server.close(() => {
|
|
91
|
+
logger?.info('UI server stopped');
|
|
92
|
+
resolve();
|
|
93
|
+
});
|
|
94
|
+
} catch (err) {
|
|
95
|
+
logger?.warn({ error: err.message }, 'Error closing HTTP server');
|
|
96
|
+
resolve(); // Resolve anyway to allow exit
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -1,98 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export function
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
logger.info({ path: state.originalConfigData.filePath }, 'Restored original config');
|
|
19
|
-
state.originalConfigData = null;
|
|
20
|
-
return true;
|
|
21
|
-
}
|
|
22
|
-
state.originalConfigData = null;
|
|
23
|
-
return false;
|
|
24
|
-
} catch (error) {
|
|
25
|
-
logger.error({ error: error.message }, 'Failed to restore original config');
|
|
26
|
-
const timestamp = new Date().toISOString();
|
|
27
|
-
const errorLog = {
|
|
28
|
-
timestamp,
|
|
29
|
-
type: 'error',
|
|
30
|
-
line: `[RESTORE ERROR] Failed to restore: ${error.message}`,
|
|
31
|
-
};
|
|
32
|
-
mcpSharkLogs.push(errorLog);
|
|
33
|
-
if (mcpSharkLogs.length > 10000) {
|
|
34
|
-
mcpSharkLogs.shift();
|
|
35
|
-
}
|
|
36
|
-
broadcastLogUpdate(errorLog);
|
|
37
|
-
return false;
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return false;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function clearOriginalConfig() {
|
|
44
|
-
state.originalConfigData = null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function convertMcpServersToServers(config) {
|
|
48
|
-
const { mcpServers, servers } = config;
|
|
49
|
-
const converted = { servers: {} };
|
|
50
|
-
|
|
51
|
-
if (servers) {
|
|
52
|
-
converted.servers = servers;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (mcpServers) {
|
|
56
|
-
Object.entries(mcpServers).forEach(([name, cfg]) => {
|
|
57
|
-
const type = cfg.type || (cfg.url ? 'http' : cfg.command ? 'stdio' : 'stdio');
|
|
58
|
-
converted.servers[name] = { type, ...cfg };
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return converted;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export function extractServices(config) {
|
|
66
|
-
const { mcpServers, servers } = config;
|
|
67
|
-
const servicesMap = new Map();
|
|
68
|
-
|
|
69
|
-
if (servers) {
|
|
70
|
-
Object.entries(servers).forEach(([name, cfg]) => {
|
|
71
|
-
const type = cfg.type || (cfg.url ? 'http' : cfg.command ? 'stdio' : 'stdio');
|
|
72
|
-
servicesMap.set(name, {
|
|
73
|
-
name,
|
|
74
|
-
type,
|
|
75
|
-
url: cfg.url || null,
|
|
76
|
-
command: cfg.command || null,
|
|
77
|
-
args: cfg.args || null,
|
|
78
|
-
});
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (mcpServers) {
|
|
83
|
-
Object.entries(mcpServers).forEach(([name, cfg]) => {
|
|
84
|
-
if (!servicesMap.has(name)) {
|
|
85
|
-
const type = cfg.type || (cfg.url ? 'http' : cfg.command ? 'stdio' : 'stdio');
|
|
86
|
-
servicesMap.set(name, {
|
|
87
|
-
name,
|
|
88
|
-
type,
|
|
89
|
-
url: cfg.url || null,
|
|
90
|
-
command: cfg.command || null,
|
|
91
|
-
args: cfg.args || null,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
});
|
|
1
|
+
/**
|
|
2
|
+
* Restore original config from backup
|
|
3
|
+
* @param {object} container - Dependency container
|
|
4
|
+
* @returns {boolean} True if config was restored
|
|
5
|
+
*/
|
|
6
|
+
export function restoreConfig(container) {
|
|
7
|
+
const configService = container.getService('config');
|
|
8
|
+
const logService = container.getService('log');
|
|
9
|
+
const restored = configService.restoreOriginalConfig();
|
|
10
|
+
if (restored) {
|
|
11
|
+
const timestamp = new Date().toISOString();
|
|
12
|
+
const restoreLog = {
|
|
13
|
+
timestamp,
|
|
14
|
+
type: 'stdout',
|
|
15
|
+
line: '[RESTORE] Restored original config',
|
|
16
|
+
};
|
|
17
|
+
logService.addLog(restoreLog);
|
|
95
18
|
}
|
|
96
|
-
|
|
97
|
-
return Array.from(servicesMap.values());
|
|
19
|
+
return restored;
|
|
98
20
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { StatusCodes } from '#core/constants/index.js';
|
|
2
|
+
import { toApplicationError } from '#core/libraries/errors/ApplicationError.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Standardized error handler for controllers
|
|
6
|
+
* Converts errors to consistent HTTP responses
|
|
7
|
+
*
|
|
8
|
+
* @param {Error|ApplicationError} error - The error to handle
|
|
9
|
+
* @param {Object} res - Express response object
|
|
10
|
+
* @param {Object} logger - Logger instance
|
|
11
|
+
* @param {string} context - Context for logging (e.g., 'Error in endpoint name')
|
|
12
|
+
*/
|
|
13
|
+
export function handleError(error, res, logger, context) {
|
|
14
|
+
const appError = toApplicationError(error, 'An unexpected error occurred');
|
|
15
|
+
|
|
16
|
+
// Log error with full context
|
|
17
|
+
logger?.error(
|
|
18
|
+
{
|
|
19
|
+
error: appError.message,
|
|
20
|
+
statusCode: appError.statusCode,
|
|
21
|
+
stack: appError.stack,
|
|
22
|
+
originalError: appError.error?.message,
|
|
23
|
+
},
|
|
24
|
+
context || 'Error handling request'
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// Send standardized error response
|
|
28
|
+
res.status(appError.statusCode || StatusCodes.INTERNAL_SERVER_ERROR).json(appError.toResponse());
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Handle validation errors specifically
|
|
33
|
+
* @param {string} message - Validation error message
|
|
34
|
+
* @param {Object} res - Express response object
|
|
35
|
+
* @param {Object} logger - Logger instance
|
|
36
|
+
*/
|
|
37
|
+
export function handleValidationError(message, res, logger) {
|
|
38
|
+
logger?.warn({ message }, 'Validation error');
|
|
39
|
+
res.status(StatusCodes.BAD_REQUEST).json({
|
|
40
|
+
error: 'ValidationError',
|
|
41
|
+
message,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// Re-export
|
|
2
|
-
export { default } from '#
|
|
1
|
+
// Re-export bootstrap logger for UI server utilities
|
|
2
|
+
export { bootstrapLogger as default } from '#core/libraries/index.js';
|
package/ui/server/utils/paths.js
CHANGED
|
@@ -23,10 +23,10 @@ function getNvmNodeBinPaths(homeDir) {
|
|
|
23
23
|
|
|
24
24
|
export function findMcpServerPath() {
|
|
25
25
|
const pathsToCheck = [
|
|
26
|
-
path.join(process.cwd(), '
|
|
27
|
-
path.join(__dirname, '
|
|
28
|
-
path.join(process.cwd(), 'mcp-server'),
|
|
29
|
-
path.join(__dirname, '
|
|
26
|
+
path.join(process.cwd(), 'core/mcp-server'),
|
|
27
|
+
path.join(__dirname, '../../../core/mcp-server'),
|
|
28
|
+
path.join(process.cwd(), '../core/mcp-server'),
|
|
29
|
+
path.join(__dirname, '../../../../core/mcp-server'),
|
|
30
30
|
];
|
|
31
31
|
|
|
32
32
|
for (const possiblePath of pathsToCheck) {
|
|
@@ -35,7 +35,29 @@ export function findMcpServerPath() {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
return path.join(process.cwd(), '
|
|
38
|
+
return path.join(process.cwd(), 'core/mcp-server');
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getPathOutput(shell, shellName) {
|
|
42
|
+
const execOptions = {
|
|
43
|
+
encoding: 'utf8',
|
|
44
|
+
timeout: 2000,
|
|
45
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
46
|
+
maxBuffer: 1024 * 1024,
|
|
47
|
+
env: {
|
|
48
|
+
...Object.fromEntries(Object.entries(process.env).filter(([key]) => key !== 'PATH')),
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
if (shellName === 'zsh') {
|
|
53
|
+
try {
|
|
54
|
+
return execSync(`${shell} -i -c 'echo $PATH'`, execOptions);
|
|
55
|
+
} catch (_e) {
|
|
56
|
+
return execSync(`${shell} -l -c 'echo $PATH'`, execOptions);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return execSync(`${shell} -l -c 'echo $PATH'`, execOptions);
|
|
39
61
|
}
|
|
40
62
|
|
|
41
63
|
/**
|
|
@@ -60,31 +82,6 @@ function getSystemPath() {
|
|
|
60
82
|
if (fs.existsSync(shell)) {
|
|
61
83
|
try {
|
|
62
84
|
const shellName = path.basename(shell);
|
|
63
|
-
|
|
64
|
-
const getPathOutput = (shell, shellName) => {
|
|
65
|
-
const execOptions = {
|
|
66
|
-
encoding: 'utf8',
|
|
67
|
-
timeout: 2000,
|
|
68
|
-
stdio: ['ignore', 'pipe', 'ignore'],
|
|
69
|
-
maxBuffer: 1024 * 1024,
|
|
70
|
-
env: {
|
|
71
|
-
...Object.fromEntries(
|
|
72
|
-
Object.entries(process.env).filter(([key]) => key !== 'PATH')
|
|
73
|
-
),
|
|
74
|
-
},
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
if (shellName === 'zsh') {
|
|
78
|
-
try {
|
|
79
|
-
return execSync(`${shell} -i -c 'echo $PATH'`, execOptions);
|
|
80
|
-
} catch (_e) {
|
|
81
|
-
return execSync(`${shell} -l -c 'echo $PATH'`, execOptions);
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
return execSync(`${shell} -l -c 'echo $PATH'`, execOptions);
|
|
86
|
-
};
|
|
87
|
-
|
|
88
85
|
const pathOutput = getPathOutput(shell, shellName);
|
|
89
86
|
const systemPath = pathOutput.trim();
|
|
90
87
|
if (systemPath) {
|