@mxf-dev/core 1.0.1 → 2.0.0
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 +18 -0
- package/dist/adapters/FrameworkAdapter.js +1 -1
- package/dist/adapters/FrameworkAdapter.js.map +1 -1
- package/dist/config/ConfigManager.d.ts +9 -8
- package/dist/config/ConfigManager.d.ts.map +1 -1
- package/dist/config/ConfigManager.js +47 -17
- package/dist/config/ConfigManager.js.map +1 -1
- package/dist/config/memory-strata.config.d.ts +25 -0
- package/dist/config/memory-strata.config.d.ts.map +1 -0
- package/dist/config/memory-strata.config.js +107 -0
- package/dist/config/memory-strata.config.js.map +1 -0
- package/dist/constants/ToolNames.d.ts +1 -29
- package/dist/constants/ToolNames.d.ts.map +1 -1
- package/dist/constants/ToolNames.js +4 -17
- package/dist/constants/ToolNames.js.map +1 -1
- package/dist/database/DatabaseAdapterFactory.d.ts +14 -2
- package/dist/database/DatabaseAdapterFactory.d.ts.map +1 -1
- package/dist/database/DatabaseAdapterFactory.js +21 -6
- package/dist/database/DatabaseAdapterFactory.js.map +1 -1
- package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts +7 -1
- package/dist/database/adapters/mongodb/MongoBaseRepository.d.ts.map +1 -1
- package/dist/database/adapters/mongodb/MongoBaseRepository.js +12 -2
- package/dist/database/adapters/mongodb/MongoBaseRepository.js.map +1 -1
- package/dist/events/ClientEventBus.d.ts +16 -77
- package/dist/events/ClientEventBus.d.ts.map +1 -1
- package/dist/events/ClientEventBus.js +38 -311
- package/dist/events/ClientEventBus.js.map +1 -1
- package/dist/events/EventBus.d.ts +1 -1
- package/dist/events/EventBus.d.ts.map +1 -1
- package/dist/events/EventBus.js +5 -4
- package/dist/events/EventBus.js.map +1 -1
- package/dist/events/EventBusBase.d.ts +139 -34
- package/dist/events/EventBusBase.d.ts.map +1 -1
- package/dist/events/EventBusBase.js +366 -88
- package/dist/events/EventBusBase.js.map +1 -1
- package/dist/events/EventNames.d.ts +10 -1
- package/dist/events/EventNames.d.ts.map +1 -1
- package/dist/events/EventNames.js +3 -0
- package/dist/events/EventNames.js.map +1 -1
- package/dist/events/PublicEvents.d.ts +6 -2
- package/dist/events/PublicEvents.d.ts.map +1 -1
- package/dist/events/PublicEvents.js +7 -4
- package/dist/events/PublicEvents.js.map +1 -1
- package/dist/events/ServerEventBus.d.ts +23 -112
- package/dist/events/ServerEventBus.d.ts.map +1 -1
- package/dist/events/ServerEventBus.js +58 -323
- package/dist/events/ServerEventBus.js.map +1 -1
- package/dist/events/event-definitions/LlmBudgetEvents.d.ts +68 -0
- package/dist/events/event-definitions/LlmBudgetEvents.d.ts.map +1 -0
- package/dist/events/event-definitions/LlmBudgetEvents.js +35 -0
- package/dist/events/event-definitions/LlmBudgetEvents.js.map +1 -0
- package/dist/interfaces/IMemoryPersistence.d.ts +41 -0
- package/dist/interfaces/IMemoryPersistence.d.ts.map +1 -0
- package/dist/interfaces/IMemoryPersistence.js +15 -0
- package/dist/interfaces/IMemoryPersistence.js.map +1 -0
- package/dist/middleware/MxpMiddleware.d.ts +8 -1
- package/dist/middleware/MxpMiddleware.d.ts.map +1 -1
- package/dist/middleware/MxpMiddleware.js +42 -20
- package/dist/middleware/MxpMiddleware.js.map +1 -1
- package/dist/models/channelKey.d.ts +1 -0
- package/dist/models/channelKey.d.ts.map +1 -1
- package/dist/models/channelKey.js +5 -0
- package/dist/models/channelKey.js.map +1 -1
- package/dist/models/memoryUtility.d.ts +39 -0
- package/dist/models/memoryUtility.d.ts.map +1 -0
- package/dist/models/memoryUtility.js +39 -0
- package/dist/models/memoryUtility.js.map +1 -0
- package/dist/models/user.d.ts.map +1 -1
- package/dist/models/user.js +23 -1
- package/dist/models/user.js.map +1 -1
- package/dist/mxp/BinaryProtocolLayer.d.ts +24 -8
- package/dist/mxp/BinaryProtocolLayer.d.ts.map +1 -1
- package/dist/mxp/BinaryProtocolLayer.js +90 -103
- package/dist/mxp/BinaryProtocolLayer.js.map +1 -1
- package/dist/mxp/ContextCompressionEngine.d.ts +57 -10
- package/dist/mxp/ContextCompressionEngine.d.ts.map +1 -1
- package/dist/mxp/ContextCompressionEngine.js +170 -128
- package/dist/mxp/ContextCompressionEngine.js.map +1 -1
- package/dist/mxp/MxpTokenOptimizer.d.ts +7 -3
- package/dist/mxp/MxpTokenOptimizer.d.ts.map +1 -1
- package/dist/mxp/MxpTokenOptimizer.js +8 -5
- package/dist/mxp/MxpTokenOptimizer.js.map +1 -1
- package/dist/prompts/MxfAgentSystemPrompt.d.ts +1 -1
- package/dist/prompts/MxfAgentSystemPrompt.d.ts.map +1 -1
- package/dist/prompts/MxfAgentSystemPrompt.js +47 -57
- package/dist/prompts/MxfAgentSystemPrompt.js.map +1 -1
- package/dist/protocols/mcp/ToolError.d.ts +123 -0
- package/dist/protocols/mcp/ToolError.d.ts.map +1 -0
- package/dist/protocols/mcp/ToolError.js +108 -0
- package/dist/protocols/mcp/ToolError.js.map +1 -0
- package/dist/protocols/mcp/defineTool.d.ts +133 -0
- package/dist/protocols/mcp/defineTool.d.ts.map +1 -0
- package/dist/protocols/mcp/defineTool.js +236 -0
- package/dist/protocols/mcp/defineTool.js.map +1 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.d.ts +38 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.d.ts.map +1 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.js +227 -0
- package/dist/protocols/mcp/security/HttpTargetGuard.js.map +1 -0
- package/dist/protocols/mcp/security/McpSecurityGuard.d.ts +9 -1
- package/dist/protocols/mcp/security/McpSecurityGuard.d.ts.map +1 -1
- package/dist/protocols/mcp/security/McpSecurityGuard.js +10 -2
- package/dist/protocols/mcp/security/McpSecurityGuard.js.map +1 -1
- package/dist/protocols/mcp/security/McpToolPolicy.d.ts +81 -0
- package/dist/protocols/mcp/security/McpToolPolicy.d.ts.map +1 -0
- package/dist/protocols/mcp/security/McpToolPolicy.js +202 -0
- package/dist/protocols/mcp/security/McpToolPolicy.js.map +1 -0
- package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts +51 -18
- package/dist/protocols/mcp/services/ExternalMcpServerManager.d.ts.map +1 -1
- package/dist/protocols/mcp/services/ExternalMcpServerManager.js +256 -283
- package/dist/protocols/mcp/services/ExternalMcpServerManager.js.map +1 -1
- package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts +39 -6
- package/dist/protocols/mcp/services/ExternalServerConfigs.d.ts.map +1 -1
- package/dist/protocols/mcp/services/ExternalServerConfigs.js +76 -18
- package/dist/protocols/mcp/services/ExternalServerConfigs.js.map +1 -1
- package/dist/protocols/mcp/tools/AnalyticsTools.js +1 -1
- package/dist/protocols/mcp/tools/AnalyticsTools.js.map +1 -1
- package/dist/protocols/mcp/tools/CodeAnalysisTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/CodeAnalysisTools.js +15 -0
- package/dist/protocols/mcp/tools/CodeAnalysisTools.js.map +1 -1
- package/dist/protocols/mcp/tools/EffectivenessTools.js +3 -3
- package/dist/protocols/mcp/tools/EffectivenessTools.js.map +1 -1
- package/dist/protocols/mcp/tools/GitTools.d.ts +9 -369
- package/dist/protocols/mcp/tools/GitTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/GitTools.js +222 -517
- package/dist/protocols/mcp/tools/GitTools.js.map +1 -1
- package/dist/protocols/mcp/tools/InfrastructureTools.d.ts +56 -24
- package/dist/protocols/mcp/tools/InfrastructureTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/InfrastructureTools.js +117 -26
- package/dist/protocols/mcp/tools/InfrastructureTools.js.map +1 -1
- package/dist/protocols/mcp/tools/MemorySearchTools.d.ts +0 -3
- package/dist/protocols/mcp/tools/MemorySearchTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/MemorySearchTools.js +58 -1
- package/dist/protocols/mcp/tools/MemorySearchTools.js.map +1 -1
- package/dist/protocols/mcp/tools/OrparTools.d.ts +8 -0
- package/dist/protocols/mcp/tools/OrparTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/OrparTools.js +66 -0
- package/dist/protocols/mcp/tools/OrparTools.js.map +1 -1
- package/dist/protocols/mcp/tools/SafetyTools.d.ts +7 -525
- package/dist/protocols/mcp/tools/SafetyTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/SafetyTools.js +349 -514
- package/dist/protocols/mcp/tools/SafetyTools.js.map +1 -1
- package/dist/protocols/mcp/tools/TaskPlanningTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/TaskPlanningTools.js +56 -26
- package/dist/protocols/mcp/tools/TaskPlanningTools.js.map +1 -1
- package/dist/protocols/mcp/tools/TestTools.d.ts +15 -376
- package/dist/protocols/mcp/tools/TestTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/TestTools.js +241 -363
- package/dist/protocols/mcp/tools/TestTools.js.map +1 -1
- package/dist/protocols/mcp/tools/TypeScriptTools.d.ts +6 -276
- package/dist/protocols/mcp/tools/TypeScriptTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/TypeScriptTools.js +223 -337
- package/dist/protocols/mcp/tools/TypeScriptTools.js.map +1 -1
- package/dist/protocols/mcp/tools/WebTools.d.ts +15 -728
- package/dist/protocols/mcp/tools/WebTools.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/WebTools.js +151 -257
- package/dist/protocols/mcp/tools/WebTools.js.map +1 -1
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts +5 -3
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.d.ts.map +1 -1
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js +31 -6
- package/dist/protocols/mcp/tools/shell/ShellExecuteHandler.js.map +1 -1
- package/dist/schemas/EventPayloadSchema.d.ts +21 -0
- package/dist/schemas/EventPayloadSchema.d.ts.map +1 -1
- package/dist/schemas/EventPayloadSchema.js +14 -0
- package/dist/schemas/EventPayloadSchema.js.map +1 -1
- package/dist/services/BackgroundTaskManager.d.ts.map +1 -1
- package/dist/services/BackgroundTaskManager.js +12 -4
- package/dist/services/BackgroundTaskManager.js.map +1 -1
- package/dist/services/BrowserManager.d.ts +1 -1
- package/dist/services/BrowserManager.d.ts.map +1 -1
- package/dist/services/BrowserManager.js +26 -3
- package/dist/services/BrowserManager.js.map +1 -1
- package/dist/services/MemoryCompressor.d.ts +11 -2
- package/dist/services/MemoryCompressor.d.ts.map +1 -1
- package/dist/services/MemoryCompressor.js +8 -26
- package/dist/services/MemoryCompressor.js.map +1 -1
- package/dist/services/MemoryService.d.ts +16 -3
- package/dist/services/MemoryService.d.ts.map +1 -1
- package/dist/services/MemoryService.js +79 -55
- package/dist/services/MemoryService.js.map +1 -1
- package/dist/services/PredictiveAnalyticsService.d.ts +34 -4
- package/dist/services/PredictiveAnalyticsService.d.ts.map +1 -1
- package/dist/services/PredictiveAnalyticsService.js +41 -25
- package/dist/services/PredictiveAnalyticsService.js.map +1 -1
- package/dist/services/QValueManager.d.ts +7 -0
- package/dist/services/QValueManager.d.ts.map +1 -1
- package/dist/services/QValueManager.js +9 -0
- package/dist/services/QValueManager.js.map +1 -1
- package/dist/services/RewardSignalProcessor.d.ts +38 -1
- package/dist/services/RewardSignalProcessor.d.ts.map +1 -1
- package/dist/services/RewardSignalProcessor.js +109 -7
- package/dist/services/RewardSignalProcessor.js.map +1 -1
- package/dist/services/SharedStateService.d.ts +16 -2
- package/dist/services/SharedStateService.d.ts.map +1 -1
- package/dist/services/SharedStateService.js +44 -3
- package/dist/services/SharedStateService.js.map +1 -1
- package/dist/services/TaskEffectivenessService.d.ts +34 -18
- package/dist/services/TaskEffectivenessService.d.ts.map +1 -1
- package/dist/services/TaskEffectivenessService.js +91 -155
- package/dist/services/TaskEffectivenessService.js.map +1 -1
- package/dist/services/WebSearchService.d.ts.map +1 -1
- package/dist/services/WebSearchService.js.map +1 -1
- package/dist/services/dag/TaskDagService.d.ts.map +1 -1
- package/dist/services/dag/TaskDagService.js +2 -0
- package/dist/services/dag/TaskDagService.js.map +1 -1
- package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts +7 -0
- package/dist/services/orpar-memory/OrparMemoryCoordinator.d.ts.map +1 -1
- package/dist/services/orpar-memory/OrparMemoryCoordinator.js +71 -10
- package/dist/services/orpar-memory/OrparMemoryCoordinator.js.map +1 -1
- package/dist/types/MemoryUtilityTypes.d.ts +2 -0
- package/dist/types/MemoryUtilityTypes.d.ts.map +1 -1
- package/dist/types/MemoryUtilityTypes.js.map +1 -1
- package/dist/utils/Logger.d.ts +43 -3
- package/dist/utils/Logger.d.ts.map +1 -1
- package/dist/utils/Logger.js +78 -36
- package/dist/utils/Logger.js.map +1 -1
- package/dist/utils/MxpEncryption.d.ts +19 -6
- package/dist/utils/MxpEncryption.d.ts.map +1 -1
- package/dist/utils/MxpEncryption.js +48 -16
- package/dist/utils/MxpEncryption.js.map +1 -1
- package/package.json +19 -4
- package/src/adapters/FrameworkAdapter.ts +1 -1
- package/src/config/ConfigManager.ts +52 -19
- package/src/config/memory-strata.config.ts +136 -0
- package/src/constants/ToolNames.ts +4 -18
- package/src/database/DatabaseAdapterFactory.ts +23 -6
- package/src/database/adapters/mongodb/MongoBaseRepository.ts +16 -2
- package/src/events/ClientEventBus.ts +68 -403
- package/src/events/EventBus.ts +7 -8
- package/src/events/EventBusBase.ts +479 -116
- package/src/events/EventNames.ts +6 -0
- package/src/events/PublicEvents.ts +7 -4
- package/src/events/ServerEventBus.ts +78 -473
- package/src/events/event-definitions/LlmBudgetEvents.ts +74 -0
- package/src/interfaces/IMemoryPersistence.ts +51 -0
- package/src/middleware/MxpMiddleware.ts +51 -24
- package/src/models/channelKey.ts +18 -4
- package/src/models/memoryUtility.ts +64 -0
- package/src/models/user.ts +36 -4
- package/src/mxp/BinaryProtocolLayer.ts +108 -124
- package/src/mxp/ContextCompressionEngine.ts +219 -161
- package/src/mxp/MxpTokenOptimizer.ts +10 -10
- package/src/prompts/MxfAgentSystemPrompt.ts +45 -55
- package/src/protocols/mcp/ToolError.ts +201 -0
- package/src/protocols/mcp/defineTool.ts +379 -0
- package/src/protocols/mcp/security/HttpTargetGuard.ts +267 -0
- package/src/protocols/mcp/security/McpSecurityGuard.ts +10 -3
- package/src/protocols/mcp/security/McpToolPolicy.ts +221 -0
- package/src/protocols/mcp/services/ExternalMcpServerManager.ts +340 -322
- package/src/protocols/mcp/services/ExternalServerConfigs.ts +82 -19
- package/src/protocols/mcp/tools/AnalyticsTools.ts +1 -1
- package/src/protocols/mcp/tools/CodeAnalysisTools.ts +15 -0
- package/src/protocols/mcp/tools/EffectivenessTools.ts +3 -3
- package/src/protocols/mcp/tools/GitTools.ts +290 -569
- package/src/protocols/mcp/tools/InfrastructureTools.ts +189 -43
- package/src/protocols/mcp/tools/MemorySearchTools.ts +77 -1
- package/src/protocols/mcp/tools/OrparTools.ts +87 -0
- package/src/protocols/mcp/tools/SafetyTools.ts +501 -579
- package/src/protocols/mcp/tools/TaskPlanningTools.ts +81 -39
- package/src/protocols/mcp/tools/TestTools.ts +339 -419
- package/src/protocols/mcp/tools/TypeScriptTools.ts +316 -376
- package/src/protocols/mcp/tools/WebTools.ts +209 -307
- package/src/protocols/mcp/tools/shell/ShellExecuteHandler.ts +53 -14
- package/src/schemas/EventPayloadSchema.ts +37 -0
- package/src/services/BackgroundTaskManager.ts +12 -4
- package/src/services/BrowserManager.ts +41 -1
- package/src/services/MemoryCompressor.ts +20 -32
- package/src/services/MemoryService.ts +96 -58
- package/src/services/PredictiveAnalyticsService.ts +55 -32
- package/src/services/QValueManager.ts +10 -0
- package/src/services/RewardSignalProcessor.ts +138 -9
- package/src/services/SharedStateService.ts +56 -8
- package/src/services/TaskEffectivenessService.ts +114 -187
- package/src/services/WebSearchService.ts +2 -1
- package/src/services/dag/TaskDagService.ts +2 -0
- package/src/services/orpar-memory/OrparMemoryCoordinator.ts +86 -10
- package/src/types/MemoryUtilityTypes.ts +2 -0
- package/src/utils/Logger.ts +116 -40
- package/src/utils/MxpEncryption.ts +69 -34
- package/dist/mxp/MxpEventForwardingEnhancer.d.ts +0 -134
- package/dist/mxp/MxpEventForwardingEnhancer.d.ts.map +0 -1
- package/dist/mxp/MxpEventForwardingEnhancer.js +0 -361
- package/dist/mxp/MxpEventForwardingEnhancer.js.map +0 -1
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts +0 -56
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.d.ts.map +0 -1
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.js +0 -57
- package/dist/protocols/mcp/services/ToolSchemaEnhancements.js.map +0 -1
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts +0 -270
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.d.ts.map +0 -1
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.js +0 -256
- package/dist/protocols/mcp/tools/ControlLoopLifecycle.js.map +0 -1
- package/dist/protocols/mcp/tools/LspTools.d.ts +0 -495
- package/dist/protocols/mcp/tools/LspTools.d.ts.map +0 -1
- package/dist/protocols/mcp/tools/LspTools.js +0 -469
- package/dist/protocols/mcp/tools/LspTools.js.map +0 -1
- package/src/mxp/MxpEventForwardingEnhancer.ts +0 -471
- package/src/protocols/mcp/services/ToolSchemaEnhancements.ts +0 -92
- package/src/protocols/mcp/tools/ControlLoopLifecycle.ts +0 -302
- package/src/protocols/mcp/tools/LspTools.ts +0 -476
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2024 Brad Anderson
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @author Brad Anderson <BradA1878@pm.me>
|
|
17
|
+
* @repository https://github.com/BradA1878/model-exchange-framework
|
|
18
|
+
* @documentation https://mxf-dev.github.io/mxf/
|
|
19
|
+
*/
|
|
20
|
+
import { McpToolDefinition, McpToolHandlerResult, McpToolResultContent } from './McpServerTypes.js';
|
|
21
|
+
import { McpToolExample } from './McpToolSchema.js';
|
|
22
|
+
import { ToolErrorData } from './ToolError.js';
|
|
23
|
+
/**
|
|
24
|
+
* The single result shape every `defineTool` tool returns.
|
|
25
|
+
*
|
|
26
|
+
* Extends the framework's McpToolHandlerResult, so these tools drop into the
|
|
27
|
+
* existing registries and socket paths unchanged, and adds the explicit
|
|
28
|
+
* `isError` flag those shapes were missing.
|
|
29
|
+
*/
|
|
30
|
+
export interface ToolResultEnvelope<TData = unknown> extends McpToolHandlerResult {
|
|
31
|
+
/** Result payload. `data` holds the tool's own output, or a ToolErrorData on failure. */
|
|
32
|
+
content: McpToolResultContent & {
|
|
33
|
+
data: TData | ToolErrorData;
|
|
34
|
+
};
|
|
35
|
+
/** True when the tool failed. Callers branch on this — never on payload shape. */
|
|
36
|
+
isError: boolean;
|
|
37
|
+
/** Execution metadata (tool name, timing, and the error code when isError). */
|
|
38
|
+
metadata: {
|
|
39
|
+
toolName: string;
|
|
40
|
+
executedAt: number;
|
|
41
|
+
durationMs: number;
|
|
42
|
+
/** Present only when isError is true */
|
|
43
|
+
errorCode?: string;
|
|
44
|
+
[key: string]: unknown;
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Context handed to a tool's `run` function.
|
|
49
|
+
*
|
|
50
|
+
* agentId, channelId and requestId are always present — `defineTool` rejects the
|
|
51
|
+
* call before `run` is reached if any is missing, so `run` never has to check.
|
|
52
|
+
*/
|
|
53
|
+
export interface ToolRunContext {
|
|
54
|
+
/** Agent that invoked the tool. Always present. */
|
|
55
|
+
agentId: string;
|
|
56
|
+
/** Channel the invocation belongs to. Always present. */
|
|
57
|
+
channelId: string;
|
|
58
|
+
/** Correlation id for events and logs. Always present. */
|
|
59
|
+
requestId: string;
|
|
60
|
+
/** Any extra context the caller attached. */
|
|
61
|
+
data?: Record<string, unknown>;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Options accepted by {@link defineTool}.
|
|
65
|
+
*/
|
|
66
|
+
export interface DefineToolOptions<TInput, TOutput> {
|
|
67
|
+
/** Tool name exposed to the model. Must be unique across the whole tool set. */
|
|
68
|
+
name: string;
|
|
69
|
+
/**
|
|
70
|
+
* What the tool does, written for the model that decides whether to call it.
|
|
71
|
+
* This is prompt text: state the behavior plainly, and describe only what the
|
|
72
|
+
* implementation actually does.
|
|
73
|
+
*/
|
|
74
|
+
description: string;
|
|
75
|
+
/** Category used for grouping and filtering. */
|
|
76
|
+
category: string;
|
|
77
|
+
/** JSON Schema for the tool's input. Enforced on every entry path. */
|
|
78
|
+
inputSchema: Record<string, any>;
|
|
79
|
+
/**
|
|
80
|
+
* The tool's behavior. Return the payload to send back; throw a ToolError to
|
|
81
|
+
* fail. Do not catch-and-wrap — the factory owns error handling.
|
|
82
|
+
*/
|
|
83
|
+
run: (input: TInput, context: ToolRunContext) => Promise<TOutput> | TOutput;
|
|
84
|
+
/** Optional worked examples surfaced in tool documentation. */
|
|
85
|
+
examples?: McpToolExample[];
|
|
86
|
+
/** Where the tool may execute. Defaults to 'server'. */
|
|
87
|
+
executionSide?: 'server' | 'client' | 'either';
|
|
88
|
+
/** Whether the tool is enabled. Defaults to true. */
|
|
89
|
+
enabled?: boolean;
|
|
90
|
+
/** Extra metadata merged into the registered tool definition. */
|
|
91
|
+
metadata?: Record<string, any>;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* A tool produced by {@link defineTool}.
|
|
95
|
+
*
|
|
96
|
+
* Structurally a McpToolDefinition, so it registers exactly like a hand-written
|
|
97
|
+
* tool, plus the `category` it was declared with.
|
|
98
|
+
*/
|
|
99
|
+
export interface DefinedMcpTool extends McpToolDefinition {
|
|
100
|
+
category: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Declare an MCP tool.
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* export const gitStatusTool = defineTool({
|
|
107
|
+
* name: 'git_status',
|
|
108
|
+
* category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
109
|
+
* description: 'Report staged, modified and untracked files by running `git status`.',
|
|
110
|
+
* inputSchema: {
|
|
111
|
+
* type: 'object',
|
|
112
|
+
* properties: { workingDirectory: { type: 'string' } }
|
|
113
|
+
* },
|
|
114
|
+
* run: async (input, context) => {
|
|
115
|
+
* const result = await runGit(['status'], input.workingDirectory);
|
|
116
|
+
* if (result.exitCode !== 0) {
|
|
117
|
+
* throw ToolError.executionFailed(`git status failed: ${result.stderr}`);
|
|
118
|
+
* }
|
|
119
|
+
* return { files: parse(result.stdout) };
|
|
120
|
+
* }
|
|
121
|
+
* });
|
|
122
|
+
*/
|
|
123
|
+
export declare function defineTool<TInput = Record<string, any>, TOutput = unknown>(options: DefineToolOptions<TInput, TOutput>): DefinedMcpTool;
|
|
124
|
+
/**
|
|
125
|
+
* Type guard: did this tool call fail?
|
|
126
|
+
*
|
|
127
|
+
* Use this instead of inspecting the payload. Results produced by `defineTool`
|
|
128
|
+
* always carry an explicit `isError`.
|
|
129
|
+
*/
|
|
130
|
+
export declare function isToolError(result: unknown): result is ToolResultEnvelope & {
|
|
131
|
+
isError: true;
|
|
132
|
+
};
|
|
133
|
+
//# sourceMappingURL=defineTool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineTool.d.ts","sourceRoot":"","sources":["../../../src/protocols/mcp/defineTool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AA+BH,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAa,aAAa,EAAe,MAAM,gBAAgB,CAAC;AAoCvE;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB,CAAC,KAAK,GAAG,OAAO,CAAE,SAAQ,oBAAoB;IAC7E,yFAAyF;IACzF,OAAO,EAAE,oBAAoB,GAAG;QAAE,IAAI,EAAE,KAAK,GAAG,aAAa,CAAA;KAAE,CAAC;IAChE,kFAAkF;IAClF,OAAO,EAAE,OAAO,CAAC;IACjB,+EAA+E;IAC/E,QAAQ,EAAE;QACN,QAAQ,EAAE,MAAM,CAAC;QACjB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,EAAE,MAAM,CAAC;QACnB,wCAAwC;QACxC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KAC1B,CAAC;CACL;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC3B,mDAAmD;IACnD,OAAO,EAAE,MAAM,CAAC;IAChB,yDAAyD;IACzD,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,MAAM,EAAE,OAAO;IAC9C,gFAAgF;IAChF,IAAI,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IACpB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC;;;OAGG;IACH,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC5E,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,cAAc,EAAE,CAAC;IAC5B,wDAAwD;IACxD,aAAa,CAAC,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAC/C,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAe,SAAQ,iBAAiB;IACrD,QAAQ,EAAE,MAAM,CAAC;CACpB;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,UAAU,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,EACtE,OAAO,EAAE,iBAAiB,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5C,cAAc,CAyJhB;AAED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,IAAI,kBAAkB,GAAG;IAAE,OAAO,EAAE,IAAI,CAAA;CAAE,CAO7F"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2024 Brad Anderson
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @author Brad Anderson <BradA1878@pm.me>
|
|
17
|
+
* @repository https://github.com/BradA1878/model-exchange-framework
|
|
18
|
+
* @documentation https://mxf-dev.github.io/mxf/
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* defineTool.ts
|
|
22
|
+
*
|
|
23
|
+
* The one way to declare an MCP tool.
|
|
24
|
+
*
|
|
25
|
+
* Tools used to hand-roll their own scaffolding: each file repeated its own
|
|
26
|
+
* try/catch, its own `error instanceof Error ? error.message : String(error)`,
|
|
27
|
+
* its own logger call, and its own result wrapper. Four different result shapes
|
|
28
|
+
* emerged across the tool set, so there was no reliable way to tell that a tool
|
|
29
|
+
* had failed.
|
|
30
|
+
*
|
|
31
|
+
* `defineTool` owns that scaffolding. A tool supplies a schema and a `run`
|
|
32
|
+
* function that returns a value or throws a {@link ToolError}; the factory:
|
|
33
|
+
*
|
|
34
|
+
* 1. validates the execution context (agentId / channelId / requestId),
|
|
35
|
+
* 2. validates the input against `inputSchema` with AJV on every entry path —
|
|
36
|
+
* not just the socket path, so a direct handler call is checked too,
|
|
37
|
+
* 3. runs `run` inside a single try/catch,
|
|
38
|
+
* 4. returns one envelope: `{ content: { type, data }, isError, metadata }`.
|
|
39
|
+
*
|
|
40
|
+
* `isError` is explicit (MCP-spec style). Callers test that flag; they never
|
|
41
|
+
* shape-sniff the payload.
|
|
42
|
+
*/
|
|
43
|
+
import { Ajv } from 'ajv';
|
|
44
|
+
import * as ajvFormatsModule from 'ajv-formats';
|
|
45
|
+
import { Logger } from '../../utils/Logger.js';
|
|
46
|
+
import { ToolError, toToolError } from './ToolError.js';
|
|
47
|
+
const ajvFormatsAny = ajvFormatsModule;
|
|
48
|
+
const addFormats = (typeof ajvFormatsAny.default === 'function' ? ajvFormatsAny.default : ajvFormatsModule);
|
|
49
|
+
const logger = new Logger('info', 'defineTool', 'server');
|
|
50
|
+
/**
|
|
51
|
+
* Shared AJV instance for input validation.
|
|
52
|
+
*
|
|
53
|
+
* `strict: false` because tool schemas carry annotation keywords AJV does not
|
|
54
|
+
* know (for example `default` inside nested properties, and MXF's own metadata).
|
|
55
|
+
* `coerceTypes` is deliberately OFF: an LLM sending `"5"` where the schema says
|
|
56
|
+
* `number` is a real mistake worth surfacing, not one to paper over.
|
|
57
|
+
*/
|
|
58
|
+
const ajv = new Ajv({
|
|
59
|
+
allErrors: true,
|
|
60
|
+
strict: false,
|
|
61
|
+
validateFormats: true,
|
|
62
|
+
coerceTypes: false,
|
|
63
|
+
useDefaults: true
|
|
64
|
+
});
|
|
65
|
+
addFormats(ajv);
|
|
66
|
+
/**
|
|
67
|
+
* Content type used for structured tool results.
|
|
68
|
+
*/
|
|
69
|
+
const JSON_CONTENT_TYPE = 'application/json';
|
|
70
|
+
/**
|
|
71
|
+
* Format AJV errors into one line a model can act on.
|
|
72
|
+
*/
|
|
73
|
+
function formatSchemaErrors(validate) {
|
|
74
|
+
const errors = validate.errors ?? [];
|
|
75
|
+
if (errors.length === 0) {
|
|
76
|
+
return 'input did not match the tool schema';
|
|
77
|
+
}
|
|
78
|
+
return errors
|
|
79
|
+
.map(err => {
|
|
80
|
+
// instancePath is '' for a root-level failure (e.g. a missing required
|
|
81
|
+
// property); name that root explicitly rather than printing an empty path.
|
|
82
|
+
const where = err.instancePath ? err.instancePath.replace(/^\//, '') : 'input';
|
|
83
|
+
return `${where} ${err.message}`;
|
|
84
|
+
})
|
|
85
|
+
.join('; ');
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Declare an MCP tool.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* export const gitStatusTool = defineTool({
|
|
92
|
+
* name: 'git_status',
|
|
93
|
+
* category: TOOL_CATEGORIES.VERSION_CONTROL,
|
|
94
|
+
* description: 'Report staged, modified and untracked files by running `git status`.',
|
|
95
|
+
* inputSchema: {
|
|
96
|
+
* type: 'object',
|
|
97
|
+
* properties: { workingDirectory: { type: 'string' } }
|
|
98
|
+
* },
|
|
99
|
+
* run: async (input, context) => {
|
|
100
|
+
* const result = await runGit(['status'], input.workingDirectory);
|
|
101
|
+
* if (result.exitCode !== 0) {
|
|
102
|
+
* throw ToolError.executionFailed(`git status failed: ${result.stderr}`);
|
|
103
|
+
* }
|
|
104
|
+
* return { files: parse(result.stdout) };
|
|
105
|
+
* }
|
|
106
|
+
* });
|
|
107
|
+
*/
|
|
108
|
+
export function defineTool(options) {
|
|
109
|
+
const { name, description, category, inputSchema, run, examples, executionSide = 'server', enabled = true, metadata = {} } = options;
|
|
110
|
+
// Fail at module load, not at call time, if a tool is declared wrong. A tool
|
|
111
|
+
// with no name or no schema cannot be registered or described to a model.
|
|
112
|
+
if (!name || typeof name !== 'string') {
|
|
113
|
+
throw new Error('defineTool: name must be a non-empty string');
|
|
114
|
+
}
|
|
115
|
+
if (!description || typeof description !== 'string') {
|
|
116
|
+
throw new Error(`defineTool(${name}): description must be a non-empty string`);
|
|
117
|
+
}
|
|
118
|
+
if (!category || typeof category !== 'string') {
|
|
119
|
+
throw new Error(`defineTool(${name}): category must be a non-empty string`);
|
|
120
|
+
}
|
|
121
|
+
if (!inputSchema || typeof inputSchema !== 'object') {
|
|
122
|
+
throw new Error(`defineTool(${name}): inputSchema must be an object`);
|
|
123
|
+
}
|
|
124
|
+
if (typeof run !== 'function') {
|
|
125
|
+
throw new Error(`defineTool(${name}): run must be a function`);
|
|
126
|
+
}
|
|
127
|
+
// Compile the schema once, at declaration. A schema AJV cannot compile is a
|
|
128
|
+
// bug in the tool, and it surfaces here rather than on first invocation.
|
|
129
|
+
let validateInput;
|
|
130
|
+
try {
|
|
131
|
+
validateInput = ajv.compile(inputSchema);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
throw new Error(`defineTool(${name}): inputSchema failed to compile: ` +
|
|
135
|
+
`${error instanceof Error ? error.message : String(error)}`);
|
|
136
|
+
}
|
|
137
|
+
const handler = async (rawInput, rawContext) => {
|
|
138
|
+
const startedAt = Date.now();
|
|
139
|
+
const fail = (toolError) => {
|
|
140
|
+
toolError.toolName = name;
|
|
141
|
+
logger.error(`Tool ${name} failed [${toolError.code}]: ${toolError.message}`);
|
|
142
|
+
return {
|
|
143
|
+
content: {
|
|
144
|
+
type: JSON_CONTENT_TYPE,
|
|
145
|
+
data: toolError.toData()
|
|
146
|
+
},
|
|
147
|
+
isError: true,
|
|
148
|
+
metadata: {
|
|
149
|
+
toolName: name,
|
|
150
|
+
executedAt: Date.now(),
|
|
151
|
+
durationMs: Date.now() - startedAt,
|
|
152
|
+
errorCode: toolError.code
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
// ── 1. Validate the execution context ──────────────────────────────
|
|
157
|
+
// agentId and channelId gate every downstream security and memory
|
|
158
|
+
// decision. A missing one is a wiring bug — never default it.
|
|
159
|
+
const context = rawContext;
|
|
160
|
+
if (!context || typeof context !== 'object') {
|
|
161
|
+
return fail(ToolError.invalidInput(`Tool ${name} was called without an execution context. ` +
|
|
162
|
+
`agentId, channelId and requestId are required.`));
|
|
163
|
+
}
|
|
164
|
+
if (typeof context.agentId !== 'string' || context.agentId.length === 0) {
|
|
165
|
+
return fail(ToolError.invalidInput(`Tool ${name} was called without a valid agentId. ` +
|
|
166
|
+
`agentId is required for all MCP tool execution.`));
|
|
167
|
+
}
|
|
168
|
+
if (typeof context.channelId !== 'string' || context.channelId.length === 0) {
|
|
169
|
+
return fail(ToolError.invalidInput(`Tool ${name} was called without a valid channelId. ` +
|
|
170
|
+
`channelId is required for all MCP tool execution.`));
|
|
171
|
+
}
|
|
172
|
+
if (typeof context.requestId !== 'string' || context.requestId.length === 0) {
|
|
173
|
+
return fail(ToolError.invalidInput(`Tool ${name} was called without a valid requestId. ` +
|
|
174
|
+
`requestId is required to correlate tool events.`));
|
|
175
|
+
}
|
|
176
|
+
const runContext = {
|
|
177
|
+
agentId: context.agentId,
|
|
178
|
+
channelId: context.channelId,
|
|
179
|
+
requestId: context.requestId,
|
|
180
|
+
data: context.data
|
|
181
|
+
};
|
|
182
|
+
// ── 2. Validate the input against the schema ───────────────────────
|
|
183
|
+
// AJV runs here so a direct handler call is checked exactly like a call
|
|
184
|
+
// arriving over the socket. `useDefaults` fills declared defaults in place.
|
|
185
|
+
const input = (rawInput ?? {});
|
|
186
|
+
if (!validateInput(input)) {
|
|
187
|
+
return fail(ToolError.invalidInput(`Invalid arguments for ${name}: ${formatSchemaErrors(validateInput)}`, { schemaErrors: validateInput.errors ?? [] }));
|
|
188
|
+
}
|
|
189
|
+
// ── 3. Run the tool ────────────────────────────────────────────────
|
|
190
|
+
try {
|
|
191
|
+
const output = await run(input, runContext);
|
|
192
|
+
return {
|
|
193
|
+
content: {
|
|
194
|
+
type: JSON_CONTENT_TYPE,
|
|
195
|
+
data: output
|
|
196
|
+
},
|
|
197
|
+
isError: false,
|
|
198
|
+
metadata: {
|
|
199
|
+
toolName: name,
|
|
200
|
+
executedAt: Date.now(),
|
|
201
|
+
durationMs: Date.now() - startedAt
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
catch (error) {
|
|
206
|
+
return fail(toToolError(error));
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
name,
|
|
211
|
+
description,
|
|
212
|
+
category,
|
|
213
|
+
inputSchema,
|
|
214
|
+
enabled,
|
|
215
|
+
executionSide,
|
|
216
|
+
examples,
|
|
217
|
+
metadata: {
|
|
218
|
+
...metadata,
|
|
219
|
+
category
|
|
220
|
+
},
|
|
221
|
+
handler: handler
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Type guard: did this tool call fail?
|
|
226
|
+
*
|
|
227
|
+
* Use this instead of inspecting the payload. Results produced by `defineTool`
|
|
228
|
+
* always carry an explicit `isError`.
|
|
229
|
+
*/
|
|
230
|
+
export function isToolError(result) {
|
|
231
|
+
return (typeof result === 'object' &&
|
|
232
|
+
result !== null &&
|
|
233
|
+
'isError' in result &&
|
|
234
|
+
result.isError === true);
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=defineTool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defineTool.js","sourceRoot":"","sources":["../../../src/protocols/mcp/defineTool.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2024 Brad Anderson
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @author Brad Anderson <BradA1878@pm.me>
|
|
17
|
+
* @repository https://github.com/BradA1878/model-exchange-framework
|
|
18
|
+
* @documentation https://mxf-dev.github.io/mxf/
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Result of checking a URL.
|
|
22
|
+
*/
|
|
23
|
+
export interface HttpTargetCheck {
|
|
24
|
+
/** Whether the fetch may proceed */
|
|
25
|
+
allowed: boolean;
|
|
26
|
+
/** Why it was refused — written for the model, so it can correct course */
|
|
27
|
+
reason?: string;
|
|
28
|
+
/** The addresses the hostname resolved to */
|
|
29
|
+
resolvedAddresses?: string[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check whether an agent-supplied URL may be fetched.
|
|
33
|
+
*
|
|
34
|
+
* @param rawUrl - The URL the tool was asked to fetch
|
|
35
|
+
* @returns Whether the fetch may proceed, and why not when it may not
|
|
36
|
+
*/
|
|
37
|
+
export declare function checkHttpTarget(rawUrl: string): Promise<HttpTargetCheck>;
|
|
38
|
+
//# sourceMappingURL=HttpTargetGuard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpTargetGuard.d.ts","sourceRoot":"","sources":["../../../../src/protocols/mcp/security/HttpTargetGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAyBH;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,2EAA2E;IAC3E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6CAA6C;IAC7C,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;CAChC;AAkHD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CA6F9E"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2024 Brad Anderson
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*
|
|
16
|
+
* @author Brad Anderson <BradA1878@pm.me>
|
|
17
|
+
* @repository https://github.com/BradA1878/model-exchange-framework
|
|
18
|
+
* @documentation https://mxf-dev.github.io/mxf/
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* HttpTargetGuard.ts
|
|
22
|
+
*
|
|
23
|
+
* Decides whether an agent-supplied URL may be fetched from the server.
|
|
24
|
+
*
|
|
25
|
+
* The server sits inside the trust boundary: it can reach the MXF API on
|
|
26
|
+
* localhost:3001, Meilisearch, MongoDB, and — on a cloud host — the instance
|
|
27
|
+
* metadata endpoint at 169.254.169.254 that hands out IAM credentials. A tool
|
|
28
|
+
* that fetches an arbitrary URL on the model's behalf turns the server into a
|
|
29
|
+
* proxy across that boundary (server-side request forgery).
|
|
30
|
+
*
|
|
31
|
+
* This guard resolves the hostname and checks every address it resolves to, so a
|
|
32
|
+
* public name that points at 127.0.0.1 is caught as well as a literal IP.
|
|
33
|
+
*
|
|
34
|
+
* The guard fails closed: a target that cannot be resolved or cannot be parsed
|
|
35
|
+
* is refused, with an error saying why. It never silently skips the check.
|
|
36
|
+
*/
|
|
37
|
+
import { promises as dns } from 'dns';
|
|
38
|
+
import { isIP } from 'net';
|
|
39
|
+
import { allowPrivateHttpHosts } from './McpToolPolicy.js';
|
|
40
|
+
/**
|
|
41
|
+
* IPv4 ranges the server must not be steered into.
|
|
42
|
+
* Each entry is [first octet-based CIDR, human name].
|
|
43
|
+
*/
|
|
44
|
+
const BLOCKED_IPV4_RANGES = [
|
|
45
|
+
{ cidr: '0.0.0.0/8', name: '"this network"' },
|
|
46
|
+
{ cidr: '10.0.0.0/8', name: 'RFC1918 private network' },
|
|
47
|
+
{ cidr: '100.64.0.0/10', name: 'carrier-grade NAT' },
|
|
48
|
+
{ cidr: '127.0.0.0/8', name: 'loopback' },
|
|
49
|
+
{ cidr: '169.254.0.0/16', name: 'link-local / cloud instance metadata' },
|
|
50
|
+
{ cidr: '172.16.0.0/12', name: 'RFC1918 private network' },
|
|
51
|
+
{ cidr: '192.0.0.0/24', name: 'IETF protocol assignments' },
|
|
52
|
+
{ cidr: '192.168.0.0/16', name: 'RFC1918 private network' },
|
|
53
|
+
{ cidr: '198.18.0.0/15', name: 'benchmark network' },
|
|
54
|
+
{ cidr: '224.0.0.0/4', name: 'multicast' },
|
|
55
|
+
{ cidr: '240.0.0.0/4', name: 'reserved' }
|
|
56
|
+
];
|
|
57
|
+
/** Convert a dotted-quad IPv4 string to a 32-bit unsigned integer. */
|
|
58
|
+
function ipv4ToInt(address) {
|
|
59
|
+
const octets = address.split('.');
|
|
60
|
+
if (octets.length !== 4) {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
let value = 0;
|
|
64
|
+
for (const octet of octets) {
|
|
65
|
+
// Reject empty, non-numeric, or out-of-range octets rather than coercing.
|
|
66
|
+
if (!/^\d{1,3}$/.test(octet)) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const num = Number(octet);
|
|
70
|
+
if (num > 255) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
value = (value << 8) | num;
|
|
74
|
+
}
|
|
75
|
+
// `>>> 0` forces the result back to unsigned — the shifts above produce a
|
|
76
|
+
// signed 32-bit int for addresses above 127.255.255.255.
|
|
77
|
+
return value >>> 0;
|
|
78
|
+
}
|
|
79
|
+
/** Is an IPv4 address inside the given CIDR block? */
|
|
80
|
+
function ipv4InCidr(address, cidr) {
|
|
81
|
+
const [network, prefixText] = cidr.split('/');
|
|
82
|
+
const prefix = Number(prefixText);
|
|
83
|
+
const addressInt = ipv4ToInt(address);
|
|
84
|
+
const networkInt = ipv4ToInt(network);
|
|
85
|
+
if (addressInt === null || networkInt === null) {
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
// A /0 mask would shift by 32, which is a no-op in JS — handle it explicitly.
|
|
89
|
+
if (prefix === 0) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
const mask = (0xffffffff << (32 - prefix)) >>> 0;
|
|
93
|
+
return (addressInt & mask) === (networkInt & mask);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Is this address one the server must not be steered into?
|
|
97
|
+
*
|
|
98
|
+
* @returns the name of the matched range, or null when the address is fine
|
|
99
|
+
*/
|
|
100
|
+
function matchBlockedRange(address) {
|
|
101
|
+
const version = isIP(address);
|
|
102
|
+
if (version === 4) {
|
|
103
|
+
for (const range of BLOCKED_IPV4_RANGES) {
|
|
104
|
+
if (ipv4InCidr(address, range.cidr)) {
|
|
105
|
+
return range.name;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (version === 6) {
|
|
111
|
+
const normalized = address.toLowerCase();
|
|
112
|
+
// IPv6 loopback
|
|
113
|
+
if (normalized === '::1' || normalized === '0:0:0:0:0:0:0:1') {
|
|
114
|
+
return 'IPv6 loopback';
|
|
115
|
+
}
|
|
116
|
+
// Unspecified address
|
|
117
|
+
if (normalized === '::' || normalized === '0:0:0:0:0:0:0:0') {
|
|
118
|
+
return 'IPv6 unspecified address';
|
|
119
|
+
}
|
|
120
|
+
// Unique local addresses, fc00::/7
|
|
121
|
+
if (/^f[cd][0-9a-f]{2}:/.test(normalized)) {
|
|
122
|
+
return 'IPv6 unique local address';
|
|
123
|
+
}
|
|
124
|
+
// Link-local, fe80::/10
|
|
125
|
+
if (/^fe[89ab][0-9a-f]:/.test(normalized)) {
|
|
126
|
+
return 'IPv6 link-local address';
|
|
127
|
+
}
|
|
128
|
+
// IPv4-mapped (::ffff:127.0.0.1) — re-check the embedded IPv4 address,
|
|
129
|
+
// otherwise ::ffff:169.254.169.254 would walk straight past this guard.
|
|
130
|
+
const mapped = normalized.match(/^::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/);
|
|
131
|
+
if (mapped) {
|
|
132
|
+
return matchBlockedRange(mapped[1]);
|
|
133
|
+
}
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Check whether an agent-supplied URL may be fetched.
|
|
140
|
+
*
|
|
141
|
+
* @param rawUrl - The URL the tool was asked to fetch
|
|
142
|
+
* @returns Whether the fetch may proceed, and why not when it may not
|
|
143
|
+
*/
|
|
144
|
+
export async function checkHttpTarget(rawUrl) {
|
|
145
|
+
let url;
|
|
146
|
+
try {
|
|
147
|
+
url = new URL(rawUrl);
|
|
148
|
+
}
|
|
149
|
+
catch {
|
|
150
|
+
return {
|
|
151
|
+
allowed: false,
|
|
152
|
+
reason: `"${rawUrl}" is not a valid URL.`
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
// Only HTTP(S). file:, gopher:, ftp: and friends reach places an HTTP client
|
|
156
|
+
// has no business reaching.
|
|
157
|
+
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
|
|
158
|
+
return {
|
|
159
|
+
allowed: false,
|
|
160
|
+
reason: `Protocol "${url.protocol}" is not allowed. Use http: or https:.`
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// The operator can open this up for local development. Off by default.
|
|
164
|
+
if (allowPrivateHttpHosts()) {
|
|
165
|
+
return { allowed: true };
|
|
166
|
+
}
|
|
167
|
+
const hostname = url.hostname.replace(/^\[|\]$/g, ''); // strip IPv6 brackets
|
|
168
|
+
// A literal IP needs no DNS round trip.
|
|
169
|
+
if (isIP(hostname) !== 0) {
|
|
170
|
+
const blocked = matchBlockedRange(hostname);
|
|
171
|
+
if (blocked) {
|
|
172
|
+
return {
|
|
173
|
+
allowed: false,
|
|
174
|
+
reason: `Refusing to fetch ${hostname}: it is a ${blocked} address. ` +
|
|
175
|
+
`This tool may only reach public internet hosts. ` +
|
|
176
|
+
`Set MXF_HTTP_ALLOW_PRIVATE_HOSTS=true to permit private addresses.`,
|
|
177
|
+
resolvedAddresses: [hostname]
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
return { allowed: true, resolvedAddresses: [hostname] };
|
|
181
|
+
}
|
|
182
|
+
// "localhost" and anything under .localhost resolve to loopback by definition.
|
|
183
|
+
const lowerHost = hostname.toLowerCase();
|
|
184
|
+
if (lowerHost === 'localhost' || lowerHost.endsWith('.localhost')) {
|
|
185
|
+
return {
|
|
186
|
+
allowed: false,
|
|
187
|
+
reason: `Refusing to fetch ${hostname}: it is a loopback address. ` +
|
|
188
|
+
`This tool may only reach public internet hosts. ` +
|
|
189
|
+
`Set MXF_HTTP_ALLOW_PRIVATE_HOSTS=true to permit private addresses.`
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// Resolve the name and check every address behind it. A public hostname can
|
|
193
|
+
// legitimately resolve to 127.0.0.1, and a malicious one will.
|
|
194
|
+
let addresses;
|
|
195
|
+
try {
|
|
196
|
+
const records = await dns.lookup(hostname, { all: true, verbatim: true });
|
|
197
|
+
addresses = records.map(record => record.address);
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
// Fail closed. An unresolvable host is not a host we quietly try anyway.
|
|
201
|
+
return {
|
|
202
|
+
allowed: false,
|
|
203
|
+
reason: `Could not resolve "${hostname}": ` +
|
|
204
|
+
`${error instanceof Error ? error.message : String(error)}`
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (addresses.length === 0) {
|
|
208
|
+
return {
|
|
209
|
+
allowed: false,
|
|
210
|
+
reason: `"${hostname}" did not resolve to any address.`
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
for (const address of addresses) {
|
|
214
|
+
const blocked = matchBlockedRange(address);
|
|
215
|
+
if (blocked) {
|
|
216
|
+
return {
|
|
217
|
+
allowed: false,
|
|
218
|
+
reason: `Refusing to fetch ${hostname}: it resolves to ${address}, ` +
|
|
219
|
+
`a ${blocked} address. This tool may only reach public internet hosts. ` +
|
|
220
|
+
`Set MXF_HTTP_ALLOW_PRIVATE_HOSTS=true to permit private addresses.`,
|
|
221
|
+
resolvedAddresses: addresses
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return { allowed: true, resolvedAddresses: addresses };
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=HttpTargetGuard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpTargetGuard.js","sourceRoot":"","sources":["../../../../src/protocols/mcp/security/HttpTargetGuard.ts"],"names":[],"mappings":"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"}
|