@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
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { CompositeError, isError } from '#core/libraries/ErrorLibrary.js';
|
|
3
|
+
import { ConfigParserFactory } from '#core/services/parsers/ConfigParserFactory.js';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_TYPE = 'stdio';
|
|
6
|
+
|
|
7
|
+
export class ConfigError extends CompositeError {
|
|
8
|
+
constructor(message, error) {
|
|
9
|
+
super('ConfigError', message, error);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const parserFactory = new ConfigParserFactory();
|
|
14
|
+
|
|
15
|
+
function parseConfig(configPath) {
|
|
16
|
+
if (!existsSync(configPath)) {
|
|
17
|
+
return new ConfigError(
|
|
18
|
+
'Config file not found',
|
|
19
|
+
new Error(`Config file not found: ${configPath}`)
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const content = readFileSync(configPath, 'utf-8');
|
|
25
|
+
const parsed = parserFactory.parse(content, configPath);
|
|
26
|
+
|
|
27
|
+
if (parsed && typeof parsed === 'object') {
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return new ConfigError('Invalid config file', new Error(`Invalid config file: ${configPath}`));
|
|
32
|
+
} catch (error) {
|
|
33
|
+
return new ConfigError(
|
|
34
|
+
'Error parsing config',
|
|
35
|
+
new Error(`Error parsing config: ${configPath} - ${error.message}`)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function normalizeConfig(configPath) {
|
|
41
|
+
const parsedConfigResult = parseConfig(configPath);
|
|
42
|
+
if (isError(parsedConfigResult)) {
|
|
43
|
+
return parsedConfigResult;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const normalized = parserFactory.normalizeToInternalFormat(parsedConfigResult, configPath);
|
|
47
|
+
if (!normalized) {
|
|
48
|
+
return new ConfigError('No servers found in config');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Convert to flat map format expected by MCP server
|
|
52
|
+
const out = new Map();
|
|
53
|
+
|
|
54
|
+
// Handle normalized mcpServers format
|
|
55
|
+
if (normalized.mcpServers) {
|
|
56
|
+
for (const [name, cfg] of Object.entries(normalized.mcpServers)) {
|
|
57
|
+
const type = cfg.type ?? DEFAULT_TYPE;
|
|
58
|
+
out.set(name, { type, ...cfg });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Handle normalized servers format (legacy)
|
|
63
|
+
if (normalized.servers) {
|
|
64
|
+
for (const [name, cfg] of Object.entries(normalized.servers)) {
|
|
65
|
+
const type = cfg.type ?? DEFAULT_TYPE;
|
|
66
|
+
out.set(name, { type, ...cfg });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (out.size === 0) {
|
|
71
|
+
return new ConfigError('No servers found in config');
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return Object.fromEntries(out);
|
|
75
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
-
import { CompositeError } from '
|
|
2
|
+
import { CompositeError } from '#core/libraries/ErrorLibrary.js';
|
|
3
3
|
|
|
4
4
|
const DEFAULT_VERSION = '1.0.0';
|
|
5
5
|
const DEFAULT_NAME = 'mcp-client';
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
ListToolsResultSchema,
|
|
5
5
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
6
6
|
|
|
7
|
-
import { CompositeError } from '
|
|
7
|
+
import { CompositeError } from '#core/libraries/ErrorLibrary.js';
|
|
8
8
|
const METHOD_NOT_FOUND_CODE = '-32601';
|
|
9
9
|
|
|
10
10
|
export class RequestError extends CompositeError {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CompositeError, getErrors, isError } from '
|
|
1
|
+
import { CompositeError, getErrors, isError } from '#core/libraries/ErrorLibrary.js';
|
|
2
2
|
import { createClient } from './client.js';
|
|
3
3
|
import * as requests from './request.js';
|
|
4
4
|
import { makeTransport } from './transport.js';
|
|
@@ -10,6 +10,21 @@ export class RunError extends CompositeError {
|
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
function createCallTool(client, args) {
|
|
14
|
+
return client.callTool.bind(client)(args);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function createReadResource(client, resourceUri) {
|
|
18
|
+
return client.readResource.bind(client)(resourceUri);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function createGetPrompt(client, promptName, args) {
|
|
22
|
+
return client.getPrompt.bind(client)({
|
|
23
|
+
name: promptName,
|
|
24
|
+
arguments: args,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
13
28
|
export async function runExternalServer({ logger, name, config }) {
|
|
14
29
|
logger.debug(`Starting external server run for server ${name} with config:`, config);
|
|
15
30
|
|
|
@@ -44,21 +59,15 @@ export async function runExternalServer({ logger, name, config }) {
|
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
const [{ tools }, { resources }, { prompts }] = results.map((result) => result.value);
|
|
62
|
+
|
|
47
63
|
return {
|
|
48
64
|
name,
|
|
49
65
|
client,
|
|
50
66
|
tools,
|
|
51
67
|
resources,
|
|
52
68
|
prompts,
|
|
53
|
-
callTool: (args) =>
|
|
54
|
-
readResource: (resourceUri) =>
|
|
55
|
-
|
|
56
|
-
},
|
|
57
|
-
getPrompt: (promptName, args) => {
|
|
58
|
-
return client.getPrompt.bind(client)({
|
|
59
|
-
name: promptName,
|
|
60
|
-
arguments: args,
|
|
61
|
-
});
|
|
62
|
-
},
|
|
69
|
+
callTool: (args) => createCallTool(client, args),
|
|
70
|
+
readResource: (resourceUri) => createReadResource(client, resourceUri),
|
|
71
|
+
getPrompt: (promptName, args) => createGetPrompt(client, promptName, args),
|
|
63
72
|
};
|
|
64
73
|
}
|
|
@@ -2,7 +2,7 @@ import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
|
|
|
2
2
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
3
3
|
import { WebSocketClientTransport } from '@modelcontextprotocol/sdk/client/websocket.js';
|
|
4
4
|
|
|
5
|
-
import { CompositeError } from '
|
|
5
|
+
import { CompositeError } from '#core/libraries/ErrorLibrary.js';
|
|
6
6
|
|
|
7
7
|
export class TransportError extends CompositeError {
|
|
8
8
|
constructor(message, error) {
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getBy } from '../../external/kv.js';
|
|
2
|
+
import { InternalServerError } from './error.js';
|
|
3
|
+
|
|
4
|
+
async function handlePromptsGet(req, logger, mcpServers, requestedMcpServer) {
|
|
5
|
+
const name = req.params.name;
|
|
6
|
+
const promptArgs = req?.params?.arguments || {};
|
|
7
|
+
logger.debug('Prompt get', name, promptArgs);
|
|
8
|
+
|
|
9
|
+
const getPrompt = getBy(mcpServers, requestedMcpServer, name, 'getPrompt', promptArgs);
|
|
10
|
+
if (!getPrompt) {
|
|
11
|
+
throw new InternalServerError(`Prompt not found: ${name}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result = await getPrompt(name, promptArgs);
|
|
15
|
+
logger.debug('Prompt get result', result);
|
|
16
|
+
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function createPromptsGetHandlerWrapper(req, logger, mcpServers, requestedMcpServer) {
|
|
21
|
+
return handlePromptsGet(req, logger, mcpServers, requestedMcpServer);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createPromptsGetHandler(logger, mcpServers, requestedMcpServer) {
|
|
25
|
+
return async (req) => {
|
|
26
|
+
return createPromptsGetHandlerWrapper(req, logger, mcpServers, requestedMcpServer);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { listAll } from '../../external/kv.js';
|
|
2
|
+
|
|
3
|
+
async function handlePromptsList(req, logger, mcpServers, requestedMcpServer) {
|
|
4
|
+
const path = req.path;
|
|
5
|
+
logger.debug('Prompts list', path);
|
|
6
|
+
|
|
7
|
+
const res = await listAll(mcpServers, requestedMcpServer, 'prompts');
|
|
8
|
+
const result = Array.isArray(res) ? { prompts: res } : res;
|
|
9
|
+
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createPromptsListHandlerWrapper(req, logger, mcpServers, requestedMcpServer) {
|
|
14
|
+
return handlePromptsList(req, logger, mcpServers, requestedMcpServer);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createPromptsListHandler(logger, mcpServers, requestedMcpServer) {
|
|
18
|
+
return async (req) => {
|
|
19
|
+
return createPromptsListHandlerWrapper(req, logger, mcpServers, requestedMcpServer);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { listAll } from '../../external/kv.js';
|
|
2
|
+
|
|
3
|
+
async function handleResourcesList(req, logger, mcpServers, requestedMcpServer) {
|
|
4
|
+
const path = req.path;
|
|
5
|
+
logger.debug('Resources list', path);
|
|
6
|
+
|
|
7
|
+
const res = await listAll(mcpServers, requestedMcpServer, 'resources');
|
|
8
|
+
const result = Array.isArray(res) ? { resources: res } : res;
|
|
9
|
+
|
|
10
|
+
return result;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function createResourcesListHandlerWrapper(req, logger, mcpServers, requestedMcpServer) {
|
|
14
|
+
return handleResourcesList(req, logger, mcpServers, requestedMcpServer);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function createResourcesListHandler(logger, mcpServers, requestedMcpServer) {
|
|
18
|
+
return async (req) => {
|
|
19
|
+
return createResourcesListHandlerWrapper(req, logger, mcpServers, requestedMcpServer);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { getBy } from '../../external/kv.js';
|
|
2
|
+
import { InternalServerError } from './error.js';
|
|
3
|
+
|
|
4
|
+
async function handleResourcesRead(req, logger, mcpServers, requestedMcpServer) {
|
|
5
|
+
const path = req.path;
|
|
6
|
+
const uri = req.params.uri;
|
|
7
|
+
logger.debug('Resource read', path, uri);
|
|
8
|
+
|
|
9
|
+
const readResource = getBy(mcpServers, requestedMcpServer, uri, 'readResource');
|
|
10
|
+
if (!readResource) {
|
|
11
|
+
throw new InternalServerError(`Resource not found: ${uri}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const result = await readResource(uri);
|
|
15
|
+
logger.debug('Resource read result', result);
|
|
16
|
+
|
|
17
|
+
return result;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function createResourcesReadHandlerWrapper(req, logger, mcpServers, requestedMcpServer) {
|
|
21
|
+
return handleResourcesRead(req, logger, mcpServers, requestedMcpServer);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function createResourcesReadHandler(logger, mcpServers, requestedMcpServer) {
|
|
25
|
+
return async (req) => {
|
|
26
|
+
return createResourcesReadHandlerWrapper(req, logger, mcpServers, requestedMcpServer);
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { getBy } from '../../external/kv.js';
|
|
2
|
+
import { InternalServerError } from './error.js';
|
|
3
|
+
|
|
4
|
+
const isAsyncIterable = (v) => v && typeof v[Symbol.asyncIterator] === 'function';
|
|
5
|
+
|
|
6
|
+
async function* createLoggedStream(result, logger) {
|
|
7
|
+
for await (const chunk of result) {
|
|
8
|
+
logger.debug('Tool call chunk forwarded', chunk);
|
|
9
|
+
yield chunk;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function handleToolsCall(req, logger, mcpServers, requestedMcpServer) {
|
|
14
|
+
const path = req.path;
|
|
15
|
+
const { name, arguments: args } = req.params;
|
|
16
|
+
logger.debug('Tool call', path, name, args);
|
|
17
|
+
|
|
18
|
+
const callTool = getBy(mcpServers, requestedMcpServer, name, 'callTool', args || {});
|
|
19
|
+
if (!callTool) {
|
|
20
|
+
throw new InternalServerError(`Tool not found: ${name}`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const result = await callTool({
|
|
24
|
+
...req.params,
|
|
25
|
+
name,
|
|
26
|
+
});
|
|
27
|
+
logger.debug('Tool call result', result);
|
|
28
|
+
|
|
29
|
+
if (isAsyncIterable(result)) {
|
|
30
|
+
return createLoggedStream(result, logger);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function createToolsCallHandlerWrapper(req, logger, mcpServers, requestedMcpServer) {
|
|
37
|
+
return handleToolsCall(req, logger, mcpServers, requestedMcpServer);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function createToolsCallHandler(logger, mcpServers, requestedMcpServer) {
|
|
41
|
+
return async (req) => {
|
|
42
|
+
return createToolsCallHandlerWrapper(req, logger, mcpServers, requestedMcpServer);
|
|
43
|
+
};
|
|
44
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { listAll } from '../../external/kv.js';
|
|
2
|
+
|
|
3
|
+
async function handleToolsList(req, logger, mcpServers, requestedMcpServer) {
|
|
4
|
+
const path = req.path;
|
|
5
|
+
logger.debug('Listing tools', path);
|
|
6
|
+
|
|
7
|
+
const res = await listAll(mcpServers, requestedMcpServer, 'tools');
|
|
8
|
+
logger.debug('Tools list result', JSON.stringify(res));
|
|
9
|
+
|
|
10
|
+
const result = Array.isArray(res) ? { tools: res } : res;
|
|
11
|
+
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function createToolsListHandlerWrapper(req, logger, mcpServers, requestedMcpServer) {
|
|
16
|
+
return handleToolsList(req, logger, mcpServers, requestedMcpServer);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function createToolsListHandler(logger, mcpServers, requestedMcpServer) {
|
|
20
|
+
return async (req) => {
|
|
21
|
+
return createToolsListHandlerWrapper(req, logger, mcpServers, requestedMcpServer);
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import cors from 'cors';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
|
|
4
|
+
import { withSession } from './session.js';
|
|
5
|
+
|
|
6
|
+
async function handleMcpRoute(
|
|
7
|
+
req,
|
|
8
|
+
res,
|
|
9
|
+
serverFactory,
|
|
10
|
+
withAuditRequestResponseHandler,
|
|
11
|
+
auditLogger
|
|
12
|
+
) {
|
|
13
|
+
await withSession(serverFactory, withAuditRequestResponseHandler, req, res, auditLogger);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function handleNotFoundRoute(_req, res) {
|
|
17
|
+
res.status(404).json({ error: 'Not found' });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getInternalServer(serverFactory, auditLogger, withAuditRequestResponseHandler) {
|
|
21
|
+
const app = express();
|
|
22
|
+
|
|
23
|
+
// Parse JSON body for POST requests
|
|
24
|
+
app.use(express.json());
|
|
25
|
+
app.use(
|
|
26
|
+
'/mcp',
|
|
27
|
+
cors({
|
|
28
|
+
origin: ['*'],
|
|
29
|
+
methods: ['*'],
|
|
30
|
+
allowedHeaders: ['*'],
|
|
31
|
+
exposedHeaders: ['*'],
|
|
32
|
+
})
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
app.all('/mcp/*', (req, res) => {
|
|
36
|
+
return handleMcpRoute(req, res, serverFactory, withAuditRequestResponseHandler, auditLogger);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// Catch-all for other routes (404)
|
|
40
|
+
app.use(handleNotFoundRoute);
|
|
41
|
+
|
|
42
|
+
return app;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function handleServerListen(logger, port) {
|
|
46
|
+
logger.info(`MCP proxy HTTP server listening on http://localhost:${port}/mcp`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export function runInternalServer(logger, port, app) {
|
|
50
|
+
app.listen(port, '0.0.0.0', () => {
|
|
51
|
+
handleServerListen(logger, port);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
@@ -57,6 +57,16 @@ export function createInternalServer(logger, mcpServers, requestedMcpServer) {
|
|
|
57
57
|
return server;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
function createInternalServerForRequested(logger, mcpServers, requestedMcpServer) {
|
|
61
|
+
return createInternalServer(logger, mcpServers, requestedMcpServer);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function createInternalServerFactoryWrapper(logger, mcpServers, requestedMcpServer) {
|
|
65
|
+
return createInternalServerForRequested(logger, mcpServers, requestedMcpServer);
|
|
66
|
+
}
|
|
67
|
+
|
|
60
68
|
export function createInternalServerFactory(logger, mcpServers) {
|
|
61
|
-
return (requestedMcpServer) =>
|
|
69
|
+
return (requestedMcpServer) => {
|
|
70
|
+
return createInternalServerFactoryWrapper(logger, mcpServers, requestedMcpServer);
|
|
71
|
+
};
|
|
62
72
|
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Conversation filters model
|
|
3
|
+
*/
|
|
4
|
+
import { Defaults } from '../constants/Defaults.js';
|
|
5
|
+
|
|
6
|
+
export class ConversationFilters {
|
|
7
|
+
constructor(data = {}) {
|
|
8
|
+
this.sessionId = data.sessionId || null;
|
|
9
|
+
this.method = data.method || null;
|
|
10
|
+
this.status = data.status || null;
|
|
11
|
+
this.jsonrpcId = data.jsonrpcId || null;
|
|
12
|
+
this.startTime = data.startTime !== undefined ? data.startTime : null;
|
|
13
|
+
this.endTime = data.endTime !== undefined ? data.endTime : null;
|
|
14
|
+
this.limit = data.limit !== undefined ? Number.parseInt(data.limit) : Defaults.DEFAULT_LIMIT;
|
|
15
|
+
this.offset =
|
|
16
|
+
data.offset !== undefined ? Number.parseInt(data.offset) : Defaults.DEFAULT_OFFSET;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
toRepositoryFilters() {
|
|
20
|
+
return {
|
|
21
|
+
sessionId: this.sessionId,
|
|
22
|
+
method: this.method,
|
|
23
|
+
status: this.status,
|
|
24
|
+
jsonrpcId: this.jsonrpcId,
|
|
25
|
+
startTime: this.startTime ? BigInt(this.startTime) : null,
|
|
26
|
+
endTime: this.endTime ? BigInt(this.endTime) : null,
|
|
27
|
+
limit: this.limit,
|
|
28
|
+
offset: this.offset,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request filters model
|
|
3
|
+
* Used for filtering packet/request queries
|
|
4
|
+
*/
|
|
5
|
+
import { Defaults } from '../constants/Defaults.js';
|
|
6
|
+
|
|
7
|
+
export class RequestFilters {
|
|
8
|
+
constructor(data = {}) {
|
|
9
|
+
this.sessionId = data.sessionId || null;
|
|
10
|
+
this.direction = data.direction || null;
|
|
11
|
+
this.method = data.method || null;
|
|
12
|
+
this.jsonrpcMethod = data.jsonrpcMethod || null;
|
|
13
|
+
this.statusCode = data.statusCode !== undefined ? data.statusCode : null;
|
|
14
|
+
this.jsonrpcId = data.jsonrpcId || null;
|
|
15
|
+
this.search = data.search || null;
|
|
16
|
+
this.serverName = data.serverName || null;
|
|
17
|
+
this.startTime = data.startTime !== undefined ? data.startTime : null;
|
|
18
|
+
this.endTime = data.endTime !== undefined ? data.endTime : null;
|
|
19
|
+
this.limit = data.limit !== undefined ? Number.parseInt(data.limit) : Defaults.DEFAULT_LIMIT;
|
|
20
|
+
this.offset =
|
|
21
|
+
data.offset !== undefined ? Number.parseInt(data.offset) : Defaults.DEFAULT_OFFSET;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Convert to repository filter format
|
|
26
|
+
*/
|
|
27
|
+
toRepositoryFilters() {
|
|
28
|
+
return {
|
|
29
|
+
sessionId: this.sessionId,
|
|
30
|
+
direction: this.direction,
|
|
31
|
+
method: this.method,
|
|
32
|
+
jsonrpcMethod: this.jsonrpcMethod,
|
|
33
|
+
statusCode: this.statusCode,
|
|
34
|
+
jsonrpcId: this.jsonrpcId,
|
|
35
|
+
search: this.search,
|
|
36
|
+
serverName: this.serverName,
|
|
37
|
+
startTime: this.startTime ? BigInt(this.startTime) : null,
|
|
38
|
+
endTime: this.endTime ? BigInt(this.endTime) : null,
|
|
39
|
+
limit: this.limit,
|
|
40
|
+
offset: this.offset,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session filters model
|
|
3
|
+
*/
|
|
4
|
+
import { Defaults } from '../constants/Defaults.js';
|
|
5
|
+
|
|
6
|
+
export class SessionFilters {
|
|
7
|
+
constructor(data = {}) {
|
|
8
|
+
this.startTime = data.startTime !== undefined ? data.startTime : null;
|
|
9
|
+
this.endTime = data.endTime !== undefined ? data.endTime : null;
|
|
10
|
+
this.limit = data.limit !== undefined ? Number.parseInt(data.limit) : Defaults.DEFAULT_LIMIT;
|
|
11
|
+
this.offset =
|
|
12
|
+
data.offset !== undefined ? Number.parseInt(data.offset) : Defaults.DEFAULT_OFFSET;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
toRepositoryFilters() {
|
|
16
|
+
return {
|
|
17
|
+
startTime: this.startTime ? BigInt(this.startTime) : null,
|
|
18
|
+
endTime: this.endTime ? BigInt(this.endTime) : null,
|
|
19
|
+
limit: this.limit,
|
|
20
|
+
offset: this.offset,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Model layer exports
|
|
3
|
+
* All models used for service layer communication
|
|
4
|
+
*/
|
|
5
|
+
export { RequestFilters } from './RequestFilters.js';
|
|
6
|
+
export { SessionFilters } from './SessionFilters.js';
|
|
7
|
+
export { ConversationFilters } from './ConversationFilters.js';
|
|
8
|
+
export { ExportFormat } from './ExportFormat.js';
|